web_ppt / frontend /src /store /snapshot.ts
CatPtain's picture
Upload 339 files
89ce340 verified
import { defineStore } from 'pinia'
import type { IndexableTypeArray } from 'dexie'
import { db, type Snapshot } from '@/utils/database'
import { useSlidesStore } from './slides'
import { useMainStore } from './main'
export interface ScreenState {
snapshotCursor: number
snapshotLength: number
}
export const useSnapshotStore = defineStore('snapshot', {
state: (): ScreenState => ({
snapshotCursor: -1, // 历史快照指针
snapshotLength: 0, // 历史快照长度
}),
getters: {
canUndo(state) {
return state.snapshotCursor > 0
},
canRedo(state) {
return state.snapshotCursor < state.snapshotLength - 1
},
},
actions: {
setSnapshotCursor(cursor: number) {
this.snapshotCursor = cursor
},
setSnapshotLength(length: number) {
this.snapshotLength = length
},
async initSnapshotDatabase() {
const slidesStore = useSlidesStore()
const newFirstSnapshot = {
index: slidesStore.slideIndex,
slides: JSON.parse(JSON.stringify(slidesStore.slides)),
}
await db.snapshots.add(newFirstSnapshot)
this.setSnapshotCursor(0)
this.setSnapshotLength(1)
},
async addSnapshot() {
const slidesStore = useSlidesStore()
// 获取当前indexeddb中全部快照的ID
const allKeys = await db.snapshots.orderBy('id').keys()
let needDeleteKeys: IndexableTypeArray = []
// 记录需要删除的快照ID
// 若当前快照指针不处在最后一位,那么再添加快照时,应该将当前指针位置后面的快照全部删除,对应的实际情况是:
// 用户撤回多次后,再进行操作(添加快照),此时原先被撤销的快照都应该被删除
if (this.snapshotCursor >= 0 && this.snapshotCursor < allKeys.length - 1) {
needDeleteKeys = allKeys.slice(this.snapshotCursor + 1)
}
// 添加新快照
const snapshot = {
index: slidesStore.slideIndex,
slides: JSON.parse(JSON.stringify(slidesStore.slides)),
}
await db.snapshots.add(snapshot)
// 计算当前快照长度,用于设置快照指针的位置(此时指针应该处在最后一位,即:快照长度 - 1)
let snapshotLength = allKeys.length - needDeleteKeys.length + 1
// 快照数量超过长度限制时,应该将头部多余的快照删除
const snapshotLengthLimit = 20
if (snapshotLength > snapshotLengthLimit) {
needDeleteKeys.push(allKeys[0])
snapshotLength--
}
// 快照数大于1时,需要保证撤回操作后维持页面焦点不变:也就是将倒数第二个快照对应的索引设置为当前页的索引
// https://github.com/pipipi-pikachu/PPTist/issues/27
if (snapshotLength >= 2) {
db.snapshots.update(allKeys[snapshotLength - 2] as number, { index: slidesStore.slideIndex })
}
await db.snapshots.bulkDelete(needDeleteKeys as number[])
this.setSnapshotCursor(snapshotLength - 1)
this.setSnapshotLength(snapshotLength)
},
async unDo() {
if (this.snapshotCursor <= 0) return
const slidesStore = useSlidesStore()
const mainStore = useMainStore()
const snapshotCursor = this.snapshotCursor - 1
const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()
const snapshot = snapshots[snapshotCursor]
const { index, slides } = snapshot
const slideIndex = index > slides.length - 1 ? slides.length - 1 : index
slidesStore.setSlides(slides)
slidesStore.updateSlideIndex(slideIndex)
this.setSnapshotCursor(snapshotCursor)
mainStore.setActiveElementIdList([])
},
async reDo() {
if (this.snapshotCursor >= this.snapshotLength - 1) return
const slidesStore = useSlidesStore()
const mainStore = useMainStore()
const snapshotCursor = this.snapshotCursor + 1
const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()
const snapshot = snapshots[snapshotCursor]
const { index, slides } = snapshot
const slideIndex = index > slides.length - 1 ? slides.length - 1 : index
slidesStore.setSlides(slides)
slidesStore.updateSlideIndex(slideIndex)
this.setSnapshotCursor(snapshotCursor)
mainStore.setActiveElementIdList([])
},
},
})