Session, project, and deliverable caches were written from scattered effects, and the legacy message migration ran twice on mount. One hook keeps that write path in a single place. Co-authored-by: Cursor <cursoragent@cursor.com>
75 lines
2.0 KiB
TypeScript
75 lines
2.0 KiB
TypeScript
import { useEffect, type Dispatch, type MutableRefObject, type SetStateAction } from 'react';
|
|
import {
|
|
migrateAndClearLegacyMessages,
|
|
saveActiveSessionId,
|
|
saveDeliverables,
|
|
saveProjects,
|
|
saveSessions,
|
|
saveUsers,
|
|
} from '../data/storage';
|
|
import { applyRestoredFileRaw, restoreFileRawToDeliverables } from '../data/fileStore';
|
|
import type { UserProfile } from '../types/docgov';
|
|
import type { DeliverableItem, ProjectInfo, ProjectSession } from '../types/workbench';
|
|
|
|
export interface WorkbenchPersistenceInput {
|
|
sessions: ProjectSession[];
|
|
activeSessionId: string;
|
|
allUsers: UserProfile[];
|
|
deliverables: DeliverableItem[];
|
|
deliverablesRef: MutableRefObject<DeliverableItem[]>;
|
|
setDeliverables: Dispatch<SetStateAction<DeliverableItem[]>>;
|
|
projects: ProjectInfo[];
|
|
}
|
|
|
|
/**
|
|
* 工作台本地缓存的写入与一次性迁移。
|
|
* 必须在对应 useState 初始化之后调用;demo seed 清理仍留在渲染前,不能放进 effect。
|
|
*/
|
|
export function useWorkbenchPersistence(input: WorkbenchPersistenceInput): void {
|
|
const {
|
|
sessions,
|
|
activeSessionId,
|
|
allUsers,
|
|
deliverables,
|
|
deliverablesRef,
|
|
setDeliverables,
|
|
projects,
|
|
} = input;
|
|
|
|
useEffect(() => {
|
|
saveSessions(sessions);
|
|
}, [sessions]);
|
|
|
|
useEffect(() => {
|
|
saveActiveSessionId(activeSessionId);
|
|
}, [activeSessionId]);
|
|
|
|
useEffect(() => {
|
|
saveUsers(allUsers);
|
|
}, [allUsers]);
|
|
|
|
useEffect(() => {
|
|
saveDeliverables(deliverables);
|
|
}, [deliverables]);
|
|
|
|
useEffect(() => {
|
|
saveProjects(projects);
|
|
}, [projects]);
|
|
|
|
useEffect(() => {
|
|
let cancelled = false;
|
|
const snapshot = deliverablesRef.current;
|
|
restoreFileRawToDeliverables(snapshot).then((restored) => {
|
|
if (cancelled || restored === snapshot) return;
|
|
setDeliverables((prev) => applyRestoredFileRaw(prev, restored));
|
|
});
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, [deliverablesRef, setDeliverables]);
|
|
|
|
useEffect(() => {
|
|
void migrateAndClearLegacyMessages();
|
|
}, []);
|
|
}
|