diff --git a/src/lib/indexedDB/cacheIndex.ts b/src/lib/indexedDB/cacheIndex.ts index fb03377..c820007 100644 --- a/src/lib/indexedDB/cacheIndex.ts +++ b/src/lib/indexedDB/cacheIndex.ts @@ -22,3 +22,7 @@ export const getFileCacheIndex = async () => { export const storeFileCacheIndex = async (fileCacheIndex: FileCacheIndex) => { await cacheIndex.fileCache.put(fileCacheIndex); }; + +export const deleteFileCacheIndex = async (fileId: number) => { + await cacheIndex.fileCache.delete(fileId); +}; diff --git a/src/lib/modules/cache.ts b/src/lib/modules/cache.ts index 383fb75..62c92c0 100644 --- a/src/lib/modules/cache.ts +++ b/src/lib/modules/cache.ts @@ -1,9 +1,10 @@ import { getFileCacheIndex as getFileCacheIndexFromIndexedDB, - storeFileCacheIndex as storeFileCacheIndexToIndexedDB, + storeFileCacheIndex, + deleteFileCacheIndex, type FileCacheIndex, } from "$lib/indexedDB"; -import { readFileFromOpfs, writeFileToOpfs } from "$lib/modules/opfs"; +import { readFile, writeFile, deleteFile } from "$lib/modules/opfs"; const fileCacheIndex = new Map(); @@ -22,13 +23,13 @@ export const getFileCache = async (fileId: number) => { if (!cacheIndex) return null; cacheIndex.lastRetrievedAt = new Date(); - storeFileCacheIndexToIndexedDB(cacheIndex); // Intended - return await readFileFromOpfs(`/cache/${fileId}`); + storeFileCacheIndex(cacheIndex); // Intended + return await readFile(`/cache/${fileId}`); }; export const storeFileCache = async (fileId: number, fileBuffer: ArrayBuffer) => { const now = new Date(); - await writeFileToOpfs(`/cache/${fileId}`, fileBuffer); + await writeFile(`/cache/${fileId}`, fileBuffer); const cacheIndex: FileCacheIndex = { fileId, @@ -37,5 +38,11 @@ export const storeFileCache = async (fileId: number, fileBuffer: ArrayBuffer) => size: fileBuffer.byteLength, }; fileCacheIndex.set(fileId, cacheIndex); - await storeFileCacheIndexToIndexedDB(cacheIndex); + await storeFileCacheIndex(cacheIndex); +}; + +export const deleteFileCache = async (fileId: number) => { + await deleteFile(`/cache/${fileId}`); + fileCacheIndex.delete(fileId); + await deleteFileCacheIndex(fileId); }; diff --git a/src/lib/modules/opfs.ts b/src/lib/modules/opfs.ts index f96e6ba..8aedc43 100644 --- a/src/lib/modules/opfs.ts +++ b/src/lib/modules/opfs.ts @@ -18,31 +18,32 @@ const getFileHandle = async (path: string, create = true) => { try { let directoryHandle: FileSystemDirectoryHandle = rootHandle; - for (const part of parts.slice(0, -1)) { if (!part) continue; directoryHandle = await directoryHandle.getDirectoryHandle(part, { create }); } - return directoryHandle.getFileHandle(parts[parts.length - 1]!, { create }); + const filename = parts[parts.length - 1]!; + const fileHandle = await directoryHandle.getFileHandle(filename, { create }); + return { parentHandle: directoryHandle, filename, fileHandle }; } catch (e) { if (e instanceof DOMException && e.name === "NotFoundError") { - return null; + return {}; } throw e; } }; -export const readFileFromOpfs = async (path: string) => { - const fileHandle = await getFileHandle(path, false); +export const readFile = async (path: string) => { + const { fileHandle } = await getFileHandle(path, false); if (!fileHandle) return null; const file = await fileHandle.getFile(); return await file.arrayBuffer(); }; -export const writeFileToOpfs = async (path: string, data: ArrayBuffer) => { - const fileHandle = await getFileHandle(path); +export const writeFile = async (path: string, data: ArrayBuffer) => { + const { fileHandle } = await getFileHandle(path); const writable = await fileHandle!.createWritable(); try { @@ -51,3 +52,10 @@ export const writeFileToOpfs = async (path: string, data: ArrayBuffer) => { await writable.close(); } }; + +export const deleteFile = async (path: string) => { + const { parentHandle, filename } = await getFileHandle(path, false); + if (!parentHandle) return; + + await parentHandle.removeEntry(filename); +}; diff --git a/src/routes/(fullscreen)/setting/cache/+page.svelte b/src/routes/(fullscreen)/setting/cache/+page.svelte index 4c799fc..a32b5c6 100644 --- a/src/routes/(fullscreen)/setting/cache/+page.svelte +++ b/src/routes/(fullscreen)/setting/cache/+page.svelte @@ -7,7 +7,7 @@ import { getFileInfo } from "$lib/modules/file"; import { masterKeyStore, type FileInfo } from "$lib/stores"; import File from "./File.svelte"; - import { formatFileSize } from "./service"; + import { formatFileSize, deleteFileCache as doDeleteFileCache } from "./service"; interface FileCache { index: FileCacheIndex; @@ -17,6 +17,11 @@ let fileCache: FileCache[] | undefined = $state(); let fileCacheTotalSize = $state(0); + const deleteFileCache = async (fileId: number) => { + await doDeleteFileCache(fileId); + fileCache = fileCache?.filter(({ index }) => index.fileId !== fileId); + }; + onMount(() => { fileCache = getFileCacheIndex() .map((index) => ({ @@ -45,7 +50,7 @@
{#each fileCache as { index, fileInfo }} - + {/each}
diff --git a/src/routes/(fullscreen)/setting/cache/File.svelte b/src/routes/(fullscreen)/setting/cache/File.svelte index f5dfcbb..e92cc5c 100644 --- a/src/routes/(fullscreen)/setting/cache/File.svelte +++ b/src/routes/(fullscreen)/setting/cache/File.svelte @@ -6,14 +6,15 @@ import IconDraft from "~icons/material-symbols/draft"; import IconScanDelete from "~icons/material-symbols/scan-delete"; - // import IconDelete from "~icons/material-symbols/delete"; + import IconDelete from "~icons/material-symbols/delete"; interface Props { index: FileCacheIndex; info: Writable; + onDeleteClick: (fileId: number) => void; } - let { index, info }: Props = $props(); + let { index, info, onDeleteClick }: Props = $props();
@@ -36,7 +37,10 @@ 읽음 {formatDate(index.lastRetrievedAt)} · {formatFileSize(index.size)}

- + diff --git a/src/routes/(fullscreen)/setting/cache/service.ts b/src/routes/(fullscreen)/setting/cache/service.ts index ec16564..a3fb37b 100644 --- a/src/routes/(fullscreen)/setting/cache/service.ts +++ b/src/routes/(fullscreen)/setting/cache/service.ts @@ -1 +1,7 @@ +import { deleteFileCache as doDeleteFileCache } from "$lib/modules/cache"; + export { formatDate, formatFileSize } from "$lib/modules/util"; + +export const deleteFileCache = async (fileId: number) => { + await doDeleteFileCache(fileId); +}; diff --git a/src/routes/(main)/directory/[[id]]/service.ts b/src/routes/(main)/directory/[[id]]/service.ts index fa3fcfc..bf1f867 100644 --- a/src/routes/(main)/directory/[[id]]/service.ts +++ b/src/routes/(main)/directory/[[id]]/service.ts @@ -1,6 +1,7 @@ import ExifReader from "exifreader"; import { callGetApi, callPostApi } from "$lib/hooks"; import { storeHmacSecrets } from "$lib/indexedDB"; +import { deleteFileCache } from "$lib/modules/cache"; import { encodeToBase64, generateDataKey, @@ -191,4 +192,5 @@ export const requestDirectoryEntryRename = async ( export const requestDirectoryEntryDeletion = async (entry: SelectedDirectoryEntry) => { await callPostApi(`/api/${entry.type}/${entry.id}/delete`); + await deleteFileCache(entry.id); };