feat: add project management features including open/save functionality and recovery support

This commit is contained in:
syntaxbullet
2026-07-10 23:46:01 +02:00
parent 6d652c3264
commit 9697075d29
15 changed files with 613 additions and 2 deletions

View File

@@ -0,0 +1,55 @@
import type { RecoveryStorage } from "@platform/projectStorage";
export const browserRecoveryStorage: RecoveryStorage = {
async read(key) {
return request<string | undefined>("readonly", (store) => store.get(key)).then((value) => value ?? null);
},
async write(key, value) {
await request("readwrite", (store) => store.put(value, key));
},
async remove(key) {
await request("readwrite", (store) => store.delete(key));
},
};
const RECOVERY_DATABASE = "image-studio";
const RECOVERY_STORE = "recovery";
function openRecoveryDatabase(): Promise<IDBDatabase> {
return new Promise((resolve, reject) => {
const open = indexedDB.open(RECOVERY_DATABASE, 1);
open.onupgradeneeded = () => {
if (!open.result.objectStoreNames.contains(RECOVERY_STORE)) open.result.createObjectStore(RECOVERY_STORE);
};
open.onsuccess = () => resolve(open.result);
open.onerror = () => reject(open.error ?? new Error("Could not open recovery storage."));
});
}
async function request<T>(mode: IDBTransactionMode, operation: (store: IDBObjectStore) => IDBRequest<T>): Promise<T> {
const database = await openRecoveryDatabase();
return new Promise((resolve, reject) => {
const transaction = database.transaction(RECOVERY_STORE, mode);
const databaseRequest = operation(transaction.objectStore(RECOVERY_STORE));
databaseRequest.onsuccess = () => resolve(databaseRequest.result);
databaseRequest.onerror = () => reject(databaseRequest.error ?? new Error("Recovery storage operation failed."));
transaction.oncomplete = () => database.close();
transaction.onerror = () => {
database.close();
reject(transaction.error ?? new Error("Recovery storage transaction failed."));
};
});
}
export function downloadProjectFile(source: string, fileName: string): void {
const url = URL.createObjectURL(new Blob([source], { type: "application/json" }));
const link = document.createElement("a");
link.href = url;
link.download = fileName;
link.click();
URL.revokeObjectURL(url);
}
export function readProjectFile(file: File): Promise<string> {
return file.text();
}

View File

@@ -0,0 +1,5 @@
export type RecoveryStorage = {
read(key: string): Promise<string | null>;
write(key: string, value: string): Promise<void>;
remove(key: string): Promise<void>;
};