mirror of
https://github.com/OpenCut-app/OpenCut.git
synced 2026-07-13 21:52:53 +02:00
108 lines
2.3 KiB
TypeScript
108 lines
2.3 KiB
TypeScript
import type { EditorCore } from "@/core";
|
|
|
|
type SaveManagerOptions = {
|
|
debounceMs?: number;
|
|
};
|
|
|
|
export class SaveManager {
|
|
private debounceMs: number;
|
|
private isPaused = false;
|
|
private isSaving = false;
|
|
private hasPendingSave = false;
|
|
private saveTimer: ReturnType<typeof setTimeout> | null = null;
|
|
private unsubscribeHandlers: Array<() => void> = [];
|
|
|
|
constructor(
|
|
private editor: EditorCore,
|
|
{ debounceMs = 800 }: SaveManagerOptions = {},
|
|
) {
|
|
this.debounceMs = debounceMs;
|
|
}
|
|
|
|
start(): void {
|
|
if (this.unsubscribeHandlers.length > 0) return;
|
|
|
|
this.unsubscribeHandlers = [
|
|
this.editor.scenes.subscribe(() => {
|
|
this.markDirty();
|
|
}),
|
|
this.editor.timeline.subscribe(() => {
|
|
this.markDirty();
|
|
}),
|
|
];
|
|
}
|
|
|
|
stop(): void {
|
|
for (const unsubscribe of this.unsubscribeHandlers) {
|
|
unsubscribe();
|
|
}
|
|
this.unsubscribeHandlers = [];
|
|
this.clearTimer();
|
|
}
|
|
|
|
pause(): void {
|
|
this.isPaused = true;
|
|
}
|
|
|
|
resume(): void {
|
|
this.isPaused = false;
|
|
if (this.hasPendingSave) {
|
|
this.queueSave();
|
|
}
|
|
}
|
|
|
|
markDirty({ force = false }: { force?: boolean } = {}): void {
|
|
if (this.isPaused && !force) return;
|
|
this.hasPendingSave = true;
|
|
this.queueSave();
|
|
}
|
|
|
|
async flush(): Promise<void> {
|
|
this.hasPendingSave = true;
|
|
await this.saveNow();
|
|
}
|
|
|
|
getIsDirty(): boolean {
|
|
return this.hasPendingSave || this.isSaving;
|
|
}
|
|
|
|
private queueSave(): void {
|
|
if (this.isSaving) return;
|
|
if (this.saveTimer) {
|
|
clearTimeout(this.saveTimer);
|
|
}
|
|
this.saveTimer = setTimeout(() => {
|
|
void this.saveNow();
|
|
}, this.debounceMs);
|
|
}
|
|
|
|
private async saveNow(): Promise<void> {
|
|
if (this.isSaving) return;
|
|
if (!this.hasPendingSave) return;
|
|
|
|
const activeProject = this.editor.project.getActive();
|
|
if (!activeProject) return;
|
|
if (this.editor.project.getIsLoading()) return;
|
|
if (this.editor.project.getMigrationState().isMigrating) return;
|
|
|
|
this.isSaving = true;
|
|
this.hasPendingSave = false;
|
|
this.clearTimer();
|
|
|
|
try {
|
|
await this.editor.project.saveCurrentProject();
|
|
} finally {
|
|
this.isSaving = false;
|
|
if (this.hasPendingSave) {
|
|
this.queueSave();
|
|
}
|
|
}
|
|
}
|
|
|
|
private clearTimer(): void {
|
|
if (!this.saveTimer) return;
|
|
clearTimeout(this.saveTimer);
|
|
this.saveTimer = null;
|
|
}
|
|
}
|