import { PptxHandoutMaster, PptxHandler, PptxNotesMaster, PptxSection, PptxSlide, PptxSlideMaster } from 'pptx-viewer-core'; import { DeckSaveIntent } from 'pptx-viewer-shared'; /** * autosave.svelte.ts: debounced crash-recovery autosave for the Svelte viewer. * * A runes port that fuses the two shared semantics the other bindings use: * - React's persistence target: each successful save writes the serialized * `.pptx` bytes to the shared IndexedDB recovery store * (`saveAutosaveSnapshot`, keyed by `filePath`), so a host can offer * restore-on-load with `getAutosaveSnapshot` / `listAutosaveSnapshots` * (both re-exported from this package). This binding does NOT auto-restore; * matching React/Vue, recovery is a host concern. * - Vue's debounce-on-edit trigger: an edit marks the document dirty and * (re)arms a debounce timer instead of polling on a fixed interval. * * The debounce is CAPPED by the shared `nextAutosaveDelayMs`, so it keeps the * same promise React's and Angular's polling engines do: a snapshot lands no * later than one interval after the FIRST unsaved edit, and no more often than * once per interval. Without that cap a user who keeps typing keeps re-arming * the timer, and at the two-minute AutoRecover cadence that is a whole session * of work that never reaches the recovery store. * * The controller registers its own edit-watching `$effect` in the constructor, * so the SFC only has to construct it once during setup and read its reactive * `status` / `isDirty` for the toolbar indicator. */ /** * Autosave status, surfaced for the toolbar status pill. * * - `idle` : nothing has been saved yet (or no edits since mount). * - `disabled` : autosave is inactive (off, not editable, or no file path). * - `saving` : a save is currently in flight. * - `saved` : the most recent save succeeded. * - `error` : the most recent save threw. */ export type AutosaveStatus = 'idle' | 'disabled' | 'saving' | 'saved' | 'error'; export interface AutosaveDeps { /** * Master on/off: the resolved activation (`resolveAutosaveActivation` in * shared), which folds the host policy, the user's toggle, editability and * the collaboration read-only veto into one answer. */ getEnabled: () => boolean; /** Debounce window in milliseconds, and the ceiling on deferring a save. */ getIntervalMs: () => number; /** IndexedDB record key (host `filePath`); autosave is disabled without one. */ getFilePath: () => string | undefined; /** The current editable slides (watched for edits). */ getSlides: () => PptxSlide[]; getSlideMasters?: () => PptxSlideMaster[]; getNotesMaster?: () => PptxNotesMaster | undefined; getHandoutMaster?: () => PptxHandoutMaster | undefined; getSections?: () => PptxSection[]; /** The live core handler used to serialize slides to `.pptx` bytes. */ getHandler: () => PptxHandler | null; /** * The Protect-Presentation state, forwarded to the shared save decision. * Optional, and deliberately inert: a recovery snapshot is written in the * clear whatever it says (see `deck-save-encryption` in * `pptx-viewer-shared`). It is threaded through so the snapshot path uses * the same one decision function as every real save. */ getSaveIntent?: () => DeckSaveIntent; /** * Monotonic load counter: a change means a fresh presentation was seeded (not * a user edit), so the watcher clears dirty instead of arming a save. */ getLoadCount: () => number; /** * Monotonic SEED counter, bumped in the same synchronous block that installs * the loaded slides (`EditorState.seedNonce`). * * `getLoadCount` alone is not enough, because the loader bumps it in an * earlier flush than the effect that copies its slides into the editor: this * watcher ran once on the count change (old slides, so nothing to do) and * then a second time on the slide reassignment, with the count already * settled - indistinguishable from an edit. Merely OPENING a deck therefore * marked it dirty and wrote a crash-recovery snapshot, so the next visit * offered to recover unsaved changes that never existed. */ getSeedNonce?: () => number; /** Host callback with the freshly-serialized bytes on each successful save. */ onSaved?: (bytes: Uint8Array) => void; } export declare class AutosaveController { #private; /** Current autosave lifecycle status (reactive). */ status: AutosaveStatus; /** Whether there are unsaved edits pending (reactive). */ isDirty: boolean; /** Epoch ms of the last successful save, or null (reactive). */ lastSavedAt: number | null; constructor(deps: AutosaveDeps); /** Force an immediate save, bypassing the debounce window. */ save(): Promise; } //# sourceMappingURL=autosave.svelte.d.ts.map