Browser Persistence
Relevant source files
The following files were used as context for generating this wiki page:
- src/app/script/klecks/storage/kl-indexed-db.ts
- src/app/script/klecks/storage/kl-recovery-manager.ts
- src/app/script/klecks/storage/project-store.ts
- src/app/script/klecks/ui/components/browser-storage-ui.ts
- src/app/script/klecks/ui/components/browser-storage-banner.ts
- src/app/script/main-standalone.ts
- src/app/script/app/kl-app.ts
Browser Persistence in Rocreate is a multi-layered system designed to ensure user artwork is preserved across browser sessions. It utilizes IndexedDB for large-scale data storage and a specialized Recovery Manager to handle unexpected tab closures or crashes. The system provides both manual storage (saving a project to the browser's permanent storage) and automatic background recovery mechanisms.
The architecture is built around three primary objectives: providing a reliable "Store" mechanism for explicit saves, maintaining a "Recovery" state for session continuity, and offering a user interface for managing stored projects. It relies on the browser's persistent storage APIs to prevent data loss due to aggressive cache clearing.
Architecture and Components
The persistence system is composed of several specialized classes and utility modules that manage the lifecycle of a project's data.
Core Storage Layers
The following diagram illustrates the relationship between the low-level database wrapper and the high-level project management services.
The diagram shows how KlApp coordinates with the ProjectStore and KlRecoveryManager, both of which utilize the central KL_INDEXED_DB wrapper to interact with the browser's storage.
Sources: src/app/script/app/kl-app.ts, src/app/script/main-standalone.ts:39-55
Key Classes and Responsibilities
| Component | Responsibility | Relevant Files |
|---|---|---|
KL_INDEXED_DB | Low-level wrapper for the IndexedDB API. Handles connection, versioning, and basic CRUD operations. | kl-indexed-db.ts |
ProjectStore | Manages "Store" operations where a user explicitly saves a project. Handles project metadata and thumbnails. | project-store.ts |
KlRecoveryManager | Automatically tracks active projects and provides a mechanism to recover unsaved work after a crash or refresh. | kl-recovery-manager.ts |
BrowserStorageUi | The UI component allowing users to store, open, or clear projects from the browser storage. | browser-storage-ui.ts |
requestPersistentStorage | Utility function to request the browser's navigator.storage.persist() permission to prevent data eviction. | request-persistent-storage.ts |
Sources: src/app/script/klecks/ui/components/browser-storage-ui.ts:24-60, src/app/script/klecks/storage/kl-recovery-manager.ts, src/app/script/klecks/storage/project-store.ts
Project Storage and Retrieval
The ProjectStore class is the primary interface for manual project persistence. It allows the application to save a full TKlProject and its associated metadata.
Storage Workflow
When a user triggers a "Store" operation, the application follows a sequence to ensure data integrity and user awareness.
The sequence diagram demonstrates the flow from the UI component through the ProjectStore to the database, including a check for project ID mismatches to prevent accidental overwrites.
Sources: src/app/script/klecks/ui/components/browser-storage-ui.ts:98-144, src/app/script/klecks/storage/project-store.ts
Initialization and Connection
The system initializes the database during the standalone application startup. It defines stores for projects and recovery data.
// From main-standalone.ts: lines 39-44
KL_INDEXED_DB.init(
getKlIndexedDbName(),
KL_INDEXED_DB_STORES,
KL_INDEXED_DB_VERSION,
KL_INDEXED_DB_UPGRADER,
);
The database initialization uses specific constants for versioning and store definitions. If testConnection() fails, the application notifies the user that storage is inaccessible.
Sources: src/app/script/main-standalone.ts:39-47
Recovery Mechanism
The KlRecoveryManager provides a safety net for unsaved work. It is initialized if IndexedDB is available and is used to retrieve the most recent auto-saved state upon application load.
Recovery Logic
During startup, the application checks for an existing recovery state:
main-standalone.tscreates aKlRecoveryManager.- It calls
klRecoveryManager.getRecovery(). - If a project is found, it is passed to the
KlAppconstructor to restore the session. - The user is notified with a "Tab recovered" message.
Sources: src/app/script/main-standalone.ts:54-68, src/app/script/app/kl-app.ts:167-175
Cross-Tab Communication
To prevent user confusion and potential data corruption, Rocreate uses a CrossTabChannel to detect if a specific project is already open in another browser tab.
This flow ensures that users are warned before opening the same project in multiple instances, which could lead to conflicts in the persistent storage.
Sources: src/app/script/klecks/ui/components/browser-storage-banner.ts:38-60, src/app/script/app/kl-app.ts:940-972
Data Persistence UI Components
Browser Storage UI
The BrowserStorageUi class provides the visual management interface. It displays a thumbnail of the stored project and its age (e.g., "5min ago").
- Store Button: Triggers
ProjectStore.store(). Labels toggle between "Store" and "Overwrite" based on whether a project already exists in the store. - Clear Button: Prompts the user before invoking
ProjectStore.clear(). - Thumbnail: Automatically updated via the
TProjectStoreListenerinterface.
Sources: src/app/script/klecks/ui/components/browser-storage-ui.ts:62-96, src/app/script/klecks/ui/components/browser-storage-ui.ts:251-260
Save Reminder
The SaveReminder system (managed within KlApp) monitors project changes and prompts the user to save if unsaved work has existed for a certain threshold (e.g., 20 minutes). It provides a direct action to save as PSD or to the browser store.
Sources: src/app/script/app/kl-app.ts:1040-1055, src/app/script/klecks/ui/tool-tabs/file-ui.ts:152-168
Summary
Browser Persistence in Rocreate ensures a robust creative environment by combining manual saves with automatic recovery. By abstracting IndexedDB through the ProjectStore and KlRecoveryManager, the system maintains a high degree of data safety while managing complex scenarios like multi-tab usage and browser storage eviction policies.