29 lines
2.2 KiB
TypeScript
29 lines
2.2 KiB
TypeScript
export type DraftStorage = Pick<Storage, 'getItem' | 'setItem' | 'removeItem' | 'key' | 'length'>
|
|
const prefix = 'workbench-draft-v1:'
|
|
export function draftKey(scope: string[]) { return prefix + JSON.stringify(scope) }
|
|
export function readDraft<T>(storage: DraftStorage, scope: string[], empty: T, valid: (value: unknown) => value is T, olderVersions = false): T {
|
|
const raw = storage.getItem(draftKey(scope))
|
|
if (raw !== null) { const record = JSON.parse(raw); if (record.cleared) return empty; if (!valid(record.value)) throw new Error('草稿格式无法读取'); return record.value }
|
|
if (olderVersions) {
|
|
const base = scope.slice(0,-1), current = Number(scope.at(-1)); let latest = -1, found: T | undefined
|
|
for (let i=0;i<storage.length;i++) { const key=storage.key(i); if (!key?.startsWith(prefix)) continue
|
|
const parts=JSON.parse(key.slice(prefix.length)); if (!Array.isArray(parts) || JSON.stringify(parts.slice(0,-1))!==JSON.stringify(base)) continue
|
|
const version=Number(parts.at(-1)); if (version>=current || version<=latest) continue
|
|
const record=JSON.parse(storage.getItem(key) ?? 'null'); if (record?.cleared) continue
|
|
if (valid(record?.value)) { latest=version; found=record.value }
|
|
}
|
|
if(found) return found
|
|
}
|
|
return empty
|
|
}
|
|
export function writeDraft<T>(storage: DraftStorage, scope: string[], value: T) { storage.setItem(draftKey(scope), JSON.stringify({ value }, (key, item) => key === 'sending' || key === 'error' ? undefined : item)) }
|
|
export function clearDraft(storage: DraftStorage, scope: string[], allVersions = false) {
|
|
if(allVersions) { const base=scope.slice(0,-1); const keys:string[]=[]; for(let i=0;i<storage.length;i++){const key=storage.key(i);if(!key?.startsWith(prefix))continue; const parts=JSON.parse(key.slice(prefix.length));if(JSON.stringify(parts.slice(0,-1))===JSON.stringify(base))keys.push(key)} for(const key of keys)storage.removeItem(key) }
|
|
storage.setItem(draftKey(scope), JSON.stringify({cleared:true}))
|
|
}
|
|
export function clearIfUnchanged(storage: DraftStorage, scope: string[], expected: string | null) {
|
|
if(storage.getItem(draftKey(scope))!==expected) return false
|
|
clearDraft(storage,scope)
|
|
return true
|
|
}
|