// The RAW the current photo came from, parked in the origin private file system // so the studio can go back to it instead of asking for 30MB a second time (see // native_raw_processing_opfs_architecture.md). One slot only: the studio holds // one photo, and the previous RAW is stale the moment the next one lands. // // The session keeps the *developed* JPEG, so the ordinary reload path never // touches this — it is the fallback for an empty IndexedDB, and the file a // future full-resolution or different-settings develop would read. // // ponytail: OPFS's own sync-access handle would let LibRaw read in place, but // LibRaw.open takes a BufferSource, so every path here reads a Blob anyway. // Switch to createSyncAccessHandle if that API ever grows a worker-side reader. const FILE = 'current_image.raw'; const NAME = 'current_image.name'; async function opfs(name: string, create: boolean): Promise { const root = await navigator.storage?.getDirectory?.(); if (!root) return null; return root.getFileHandle(name, { create }); } async function write(name: string, data: BlobPart): Promise { const fh = await opfs(name, true); if (!fh) return; const w = await fh.createWritable(); await w.write(data); await w.close(); } export async function storeRaw(bytes: Uint8Array, fileName: string): Promise { try { await write(FILE, bytes as unknown as BufferSource); await write(NAME, fileName); } catch { // No OPFS (private mode, older browser): the photo still develops, it just // cannot be recovered after a reload. Nothing here is worth failing a load. } } export async function readRaw(): Promise<{ name: string; bytes: Uint8Array } | null> { try { const fh = await opfs(FILE, false); if (!fh) return null; const nameHandle = await opfs(NAME, false); const name = nameHandle ? (await (await nameHandle.getFile()).text()).trim() : FILE; return { name: name || FILE, bytes: new Uint8Array(await (await fh.getFile()).arrayBuffer()) }; } catch { return null; } } export async function clearRaw(): Promise { try { const root = await navigator.storage?.getDirectory?.(); await root?.removeEntry(FILE).catch(() => undefined); await root?.removeEntry(NAME).catch(() => undefined); } catch { // Absent is the desired state. } }