This commit is contained in:
pipipi-pikachu 2020-12-20 20:23:46 +08:00
parent 5461dde2c8
commit a1fba0dbea
11 changed files with 169 additions and 33 deletions

11
package-lock.json generated
View File

@ -5986,6 +5986,11 @@
"integrity": "sha1-AU7o+PZpxcWAI9pkuBecCDooxGw=",
"dev": true
},
"dexie": {
"version": "3.0.3",
"resolved": "https://registry.npm.taobao.org/dexie/download/dexie-3.0.3.tgz",
"integrity": "sha1-7eY4Sd/l8H4T6Zu3KgQOisHSnas="
},
"diff": {
"version": "4.0.2",
"resolved": "https://registry.npm.taobao.org/diff/download/diff-4.0.2.tgz?cache=0&sync_timestamp=1604803633979&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdiff%2Fdownload%2Fdiff-4.0.2.tgz",
@ -7319,7 +7324,7 @@
},
"fork-ts-checker-webpack-plugin-v5": {
"version": "npm:fork-ts-checker-webpack-plugin@5.2.1",
"resolved": "https://registry.npm.taobao.org/fork-ts-checker-webpack-plugin/download/fork-ts-checker-webpack-plugin-5.2.1.tgz?cache=0&sync_timestamp=1608028579163&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffork-ts-checker-webpack-plugin%2Fdownload%2Ffork-ts-checker-webpack-plugin-5.2.1.tgz",
"resolved": "https://registry.npm.taobao.org/fork-ts-checker-webpack-plugin/download/fork-ts-checker-webpack-plugin-5.2.1.tgz?cache=0&sync_timestamp=1607084938170&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffork-ts-checker-webpack-plugin%2Fdownload%2Ffork-ts-checker-webpack-plugin-5.2.1.tgz",
"integrity": "sha1-eTJthpeXkG+osk4qvPlCH8gFRQ0=",
"dev": true,
"optional": true,
@ -7416,7 +7421,7 @@
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz",
"resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1606205010380&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz",
"integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=",
"dev": true,
"optional": true,
@ -15944,7 +15949,7 @@
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz",
"resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1606205010380&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz",
"integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=",
"dev": true,
"optional": true,

View File

@ -13,6 +13,7 @@
"clipboard": "^2.0.6",
"core-js": "^3.6.5",
"crypto-js": "^4.0.0",
"dexie": "^3.0.3",
"lodash": "^4.17.20",
"store2": "^2.12.0",
"vue": "^3.0.0",

View File

@ -2,17 +2,19 @@
<router-view/>
</template>
<script>
<script lang="ts">
import { defineComponent, onMounted } from 'vue'
import { useStore } from 'vuex'
import { MutationTypes } from '@/store'
import { MutationTypes, ActionTypes, State } from '@/store'
export default defineComponent({
name: 'app',
setup() {
const store = useStore()
const store = useStore<State>()
onMounted(() => {
store.commit(MutationTypes.SET_AVAILABLE_FONTS)
store.dispatch(ActionTypes.INIT_SNAPSHOT_DATABASE)
})
},
})

View File

@ -0,0 +1,15 @@
import { useStore } from 'vuex'
import debounce from 'lodash/debounce'
import { State, ActionTypes } from '@/store'
export default () => {
const store = useStore<State>()
const addHistorySnapshot = debounce(function() {
store.dispatch(ActionTypes.ADD_SNAPSHOT)
}, 300, { trailing: true })
return {
addHistorySnapshot,
}
}

View File

@ -0,0 +1,20 @@
import { useStore } from 'vuex'
import throttle from 'lodash/throttle'
import { State, ActionTypes } from '@/store'
export default () => {
const store = useStore<State>()
const redo = throttle(function() {
store.dispatch(ActionTypes.RE_DO)
}, 100, { leading: true, trailing: false })
const undo = throttle(function() {
store.dispatch(ActionTypes.UN_DO)
}, 100, { leading: true, trailing: false })
return {
redo,
undo,
}
}

73
src/store/actions.ts Normal file
View File

@ -0,0 +1,73 @@
import { ActionTree } from 'vuex'
import { IndexableTypeArray } from 'dexie'
import { State } from './index'
import { ActionTypes, MutationTypes } from './constants'
import db, { Snapshot } from '@/utils/database'
export const actions: ActionTree<State, State> = {
async [ActionTypes.INIT_SNAPSHOT_DATABASE]({ commit }) {
const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()
const snapshot = snapshots.slice(-1)[0]
if(snapshot) {
db.snapshots.clear()
commit(MutationTypes.SET_SLIDES, snapshot.slides)
}
},
async [ActionTypes.ADD_SNAPSHOT]({ state, commit }) {
const allKeys = await db.snapshots.orderBy('id').keys()
let needDeleteKeys: IndexableTypeArray = []
if(state.snapshotCursor >= 0 && state.snapshotCursor < allKeys.length - 1) {
needDeleteKeys = allKeys.slice(state.snapshotCursor + 1)
}
const snapshot = {
index: state.slideIndex,
slides: state.slides,
}
await db.snapshots.add(snapshot)
let snapshotLength = allKeys.length - needDeleteKeys.length + 1
if(snapshotLength > 20) {
needDeleteKeys.push(allKeys[0])
snapshotLength--
}
await db.snapshots.bulkDelete(needDeleteKeys)
commit(MutationTypes.SET_SNAPSHOT_CURSOR, snapshotLength - 1)
commit(MutationTypes.SET_SNAPSHOT_LENGTH, snapshotLength)
},
async [ActionTypes.UN_DO]({ state, commit }) {
if(state.snapshotCursor > 0) return
const snapshotCursor = state.snapshotCursor - 1
const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()
const snapshot = snapshots[snapshotCursor]
const { index, slides } = snapshot
commit(MutationTypes.SET_SLIDES, slides)
commit(MutationTypes.UPDATE_SLIDE_INDEX, index)
commit(MutationTypes.SET_SNAPSHOT_CURSOR, snapshotCursor)
commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
},
async [ActionTypes.RE_DO]({ state, commit }) {
if(state.snapshotCursor < state.snapshotLength - 1) return
const snapshotCursor = state.snapshotCursor + 1
const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()
const snapshot = snapshots[snapshotCursor]
const { index, slides } = snapshot
commit(MutationTypes.SET_SLIDES, slides)
commit(MutationTypes.UPDATE_SLIDE_INDEX, index)
commit(MutationTypes.SET_SNAPSHOT_CURSOR, snapshotCursor)
commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
},
}

View File

@ -18,13 +18,18 @@ export enum MutationTypes {
ADD_ELEMENT = 'addElement',
UPDATE_ELEMENT = 'updateElement',
// history
SET_CURSOR = 'setCursor',
UNDO = 'undo',
REDO = 'redo',
SET_HISTORY_RECORD_LENGTH = 'setHistoryRecordLength',
// snapshot
SET_SNAPSHOT_CURSOR = 'setSnapshotCursor',
SET_SNAPSHOT_LENGTH = 'setSnapshotLength',
// keyboard
SET_CTRL_KEY_STATE = 'setCtrlKeyState',
SET_SHIFT_KEY_STATE = 'setShiftKeyState',
}
export enum ActionTypes {
INIT_SNAPSHOT_DATABASE = 'initSnapshotDatabase',
ADD_SNAPSHOT = 'addSnapshot',
UN_DO = 'undo',
RE_DO = 'redo',
}

View File

@ -30,11 +30,11 @@ export const getters: GetterTree<State, State> = {
},
canUndo(state) {
return state.cursor > 0
return state.snapshotCursor > 0
},
canRedo(state) {
return state.cursor < state.historyRecordLength - 1
return state.snapshotCursor < state.snapshotLength - 1
},
ctrlOrShiftKeyActive(state) {

View File

@ -1,13 +1,14 @@
import { createStore } from 'vuex'
import { mutations } from './mutations'
import { getters } from './getters'
import { MutationTypes } from './constants'
import { actions } from './actions'
import { mutations } from './mutations'
import { MutationTypes, ActionTypes } from './constants'
import { Slide } from '@/types/slides'
import { slides } from '@/mocks/index'
import { FontName } from '@/configs/fontName'
export { MutationTypes }
export { MutationTypes, ActionTypes }
export interface State {
activeElementIdList: string[];
@ -19,8 +20,8 @@ export interface State {
availableFonts: FontName[];
slides: Slide[];
slideIndex: number;
cursor: number;
historyRecordLength: number;
snapshotCursor: number;
snapshotLength: number;
ctrlKeyState: boolean;
shiftKeyState: boolean;
}
@ -35,8 +36,8 @@ const state: State = {
availableFonts: [],
slides: slides,
slideIndex: 0,
cursor: -1,
historyRecordLength: 0,
snapshotCursor: -1,
snapshotLength: 0,
ctrlKeyState: false,
shiftKeyState: false,
}
@ -45,4 +46,5 @@ export default createStore({
state,
getters,
mutations,
actions,
})

View File

@ -101,22 +101,14 @@ export const mutations: MutationTree<State> = {
state.slides[slideIndex].elements = (elements as PPTElement[])
},
// history
// snapshot
[MutationTypes.SET_CURSOR](state, cursor: number) {
state.cursor = cursor
[MutationTypes.SET_SNAPSHOT_CURSOR](state, cursor: number) {
state.snapshotCursor = cursor
},
[MutationTypes.UNDO](state) {
state.cursor -= 1
},
[MutationTypes.REDO](state) {
state.cursor += 1
},
[MutationTypes.SET_HISTORY_RECORD_LENGTH](state, length: number) {
state.historyRecordLength = length
[MutationTypes.SET_SNAPSHOT_LENGTH](state, length: number) {
state.snapshotLength = length
},
// keyBoard

21
src/utils/database.ts Normal file
View File

@ -0,0 +1,21 @@
import Dexie from 'dexie'
import { Slide } from '@/types/slides'
export interface Snapshot {
index: number;
slides: Slide[];
}
class SnapshotDatabase extends Dexie {
public snapshots: Dexie.Table<Snapshot, number>
public constructor() {
super('SnapshotDatabase')
this.version(1).stores({
snapshots: '++id'
})
this.snapshots = this.table('snapshots')
}
}
export default new SnapshotDatabase()