import type { IndexedDbStore } from "./indexedDbStore.svelte.js"; import { getOPFSRoot, type OPFSStorage } from "./opfsStorage.js"; const legacyArtPattern = /^art_(.+)_(128|512)$/; const opfsStorageVersion = 1; const migrateArtFiles = async (storage: OPFSStorage): Promise => { if (!navigator.storage?.getDirectory) return; const legacyFiles = new Map(); const canonicalFiles = new Set(); for await (const [name, handle] of (await getOPFSRoot()).entries()) { if (handle.kind !== "file") continue; const match = name.match(legacyArtPattern); if (match) { const files = legacyFiles.get(match[1]) ?? {}; files[match[2] === "512" ? "high" : "low"] = name; legacyFiles.set(match[1], files); } else if (name.startsWith("art_")) { canonicalFiles.add(name); } } for (const [id, files] of legacyFiles) { const canonical = `art_${id}`; if (!canonicalFiles.has(canonical)) { for (const source of [files.high, files.low]) { if (!source) continue; const blob = await storage.readBlob(source); if (!blob) continue; await storage.writeBlob(canonical, blob); break; } } for (const name of [files.low, files.high]) { if (name) await storage.deleteBlob(name); } } }; export const migrateOfflineStorage = async ( store: IndexedDbStore, storage: OPFSStorage, ): Promise => { const currentOpfsVersion = (await store.getMetadata("opfsVersion")) ?? 0; if (currentOpfsVersion >= opfsStorageVersion) return; try { await globalThis.caches?.delete("getCoverArt"); } catch (err) { console.warn("failed to delete legacy cover art cache:", err); } try { globalThis.indexedDB?.deleteDatabase("tinysub_pwa"); } catch (err) { console.warn("failed to delete legacy sync database:", err); } try { await migrateArtFiles(storage); await store.setMetadata("opfsVersion", opfsStorageVersion); } catch (err) { console.warn("failed to migrate cached art:", err); } };