From 2e3cd4f8a2f19a13489d6307855aea25e42b5018 Mon Sep 17 00:00:00 2001 From: static Date: Thu, 1 Jan 2026 23:52:47 +0900 Subject: [PATCH] =?UTF-8?q?=EB=84=A4=ED=8A=B8=EC=9B=8C=ED=81=AC=20?= =?UTF-8?q?=ED=98=B8=EC=B6=9C=20=EA=B2=B0=EA=B3=BC=EA=B0=80=20IndexedDB?= =?UTF-8?q?=EC=97=90=20=EC=BA=90=EC=8B=9C=EB=90=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8D=98=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../organisms/Category/Category.svelte | 17 ++++ src/lib/modules/filesystem/category.ts | 83 +++++++++++++++---- src/lib/modules/filesystem/directory.ts | 52 +++++++++--- src/lib/modules/filesystem/file.ts | 42 ++++++++-- 4 files changed, 158 insertions(+), 36 deletions(-) diff --git a/src/lib/components/organisms/Category/Category.svelte b/src/lib/components/organisms/Category/Category.svelte index 81471e6..3728f5f 100644 --- a/src/lib/components/organisms/Category/Category.svelte +++ b/src/lib/components/organisms/Category/Category.svelte @@ -1,6 +1,7 @@
diff --git a/src/lib/modules/filesystem/category.ts b/src/lib/modules/filesystem/category.ts index 310a220..dc25506 100644 --- a/src/lib/modules/filesystem/category.ts +++ b/src/lib/modules/filesystem/category.ts @@ -52,25 +52,76 @@ const fetchFromServer = async (id: CategoryId, masterKey: CryptoKey) => { metadata, subCategories: subCategoriesRaw, files: filesRaw, - } = await trpc().category.get.query({ id }); - const [subCategories, files] = await Promise.all([ - Promise.all( - subCategoriesRaw.map(async (category) => ({ + } = await trpc().category.get.query({ id, recurse: true }); + const subCategories = await Promise.all( + subCategoriesRaw.map(async (category) => { + const decrypted = await decryptCategoryMetadata(category, masterKey); + const existing = await IndexedDB.getCategoryInfo(category.id); + await IndexedDB.storeCategoryInfo({ id: category.id, - ...(await decryptCategoryMetadata(category, masterKey)), - })), - ), - filesRaw - ? Promise.all( - filesRaw.map(async (file) => ({ + parentId: id, + name: decrypted.name, + files: existing?.files ?? [], + isFileRecursive: existing?.isFileRecursive ?? false, + }); + return { + id: category.id, + ...decrypted, + }; + }), + ); + + const existingFiles = filesRaw + ? await IndexedDB.bulkGetFileInfos(filesRaw.map((file) => file.id)) + : []; + const files = filesRaw + ? await Promise.all( + filesRaw.map(async (file, index) => { + const decrypted = await decryptFileMetadata(file, masterKey); + const existing = existingFiles[index]; + if (existing) { + const categoryIds = file.isRecursive + ? existing.categoryIds + : Array.from(new Set([...existing.categoryIds, id as number])); + await IndexedDB.storeFileInfo({ + id: file.id, + parentId: existing.parentId, + contentType: file.contentType, + name: decrypted.name, + createdAt: decrypted.createdAt, + lastModifiedAt: decrypted.lastModifiedAt, + categoryIds, + }); + } + return { id: file.id, contentType: file.contentType, isRecursive: file.isRecursive, - ...(await decryptFileMetadata(file, masterKey)), - })), - ) - : undefined, - ]); + ...decrypted, + }; + }), + ) + : undefined; + + const decryptedMetadata = metadata + ? await decryptCategoryMetadata(metadata, masterKey) + : undefined; + if (id !== "root" && metadata && decryptedMetadata) { + const existingCategory = await IndexedDB.getCategoryInfo(id); + await IndexedDB.storeCategoryInfo({ + id: id as number, + parentId: metadata.parent, + name: decryptedMetadata.name, + files: + files?.map((file) => ({ + id: file.id, + isRecursive: file.isRecursive, + })) ?? + existingCategory?.files ?? + [], + isFileRecursive: existingCategory?.isFileRecursive ?? false, + }); + } if (id === "root") { return { @@ -84,7 +135,7 @@ const fetchFromServer = async (id: CategoryId, masterKey: CryptoKey) => { exists: true as const, subCategories, files, - ...(await decryptCategoryMetadata(metadata!, masterKey)), + ...decryptedMetadata!, }; } } catch (e) { diff --git a/src/lib/modules/filesystem/directory.ts b/src/lib/modules/filesystem/directory.ts index 6417758..6449480 100644 --- a/src/lib/modules/filesystem/directory.ts +++ b/src/lib/modules/filesystem/directory.ts @@ -39,22 +39,52 @@ const fetchFromServer = async (id: DirectoryId, masterKey: CryptoKey) => { subDirectories: subDirectoriesRaw, files: filesRaw, } = await trpc().directory.get.query({ id }); - const [subDirectories, files] = await Promise.all([ + const existingFiles = await IndexedDB.bulkGetFileInfos(filesRaw.map((file) => file.id)); + const [subDirectories, files, decryptedMetadata] = await Promise.all([ Promise.all( - subDirectoriesRaw.map(async (directory) => ({ - id: directory.id, - ...(await decryptDirectoryMetadata(directory, masterKey)), - })), + subDirectoriesRaw.map(async (directory) => { + const decrypted = await decryptDirectoryMetadata(directory, masterKey); + await IndexedDB.storeDirectoryInfo({ + id: directory.id, + parentId: id, + name: decrypted.name, + }); + return { + id: directory.id, + ...decrypted, + }; + }), ), Promise.all( - filesRaw.map(async (file) => ({ - id: file.id, - contentType: file.contentType, - ...(await decryptFileMetadata(file, masterKey)), - })), + filesRaw.map(async (file, index) => { + const decrypted = await decryptFileMetadata(file, masterKey); + await IndexedDB.storeFileInfo({ + id: file.id, + parentId: id, + contentType: file.contentType, + name: decrypted.name, + createdAt: decrypted.createdAt, + lastModifiedAt: decrypted.lastModifiedAt, + categoryIds: existingFiles[index]?.categoryIds ?? [], + }); + return { + id: file.id, + contentType: file.contentType, + ...decrypted, + }; + }), ), + metadata ? decryptDirectoryMetadata(metadata, masterKey) : undefined, ]); + if (id !== "root" && metadata && decryptedMetadata) { + await IndexedDB.storeDirectoryInfo({ + id, + parentId: metadata.parent, + name: decryptedMetadata.name, + }); + } + if (id === "root") { return { id, @@ -69,7 +99,7 @@ const fetchFromServer = async (id: DirectoryId, masterKey: CryptoKey) => { parentId: metadata!.parent, subDirectories, files, - ...(await decryptDirectoryMetadata(metadata!, masterKey)), + ...decryptedMetadata!, }; } } catch (e) { diff --git a/src/lib/modules/filesystem/file.ts b/src/lib/modules/filesystem/file.ts index d8411bf..45fef78 100644 --- a/src/lib/modules/filesystem/file.ts +++ b/src/lib/modules/filesystem/file.ts @@ -66,15 +66,26 @@ const bulkFetchFromIndexedDB = async (ids: number[]) => { const fetchFromServer = async (id: number, masterKey: CryptoKey) => { try { const { categories: categoriesRaw, ...metadata } = await trpc().file.get.query({ id }); - const [categories] = await Promise.all([ + const [categories, decryptedMetadata] = await Promise.all([ Promise.all( categoriesRaw.map(async (category) => ({ id: category.id, ...(await decryptCategoryMetadata(category, masterKey)), })), ), + decryptFileMetadata(metadata, masterKey), ]); + await IndexedDB.storeFileInfo({ + id, + parentId: metadata.parent, + contentType: metadata.contentType, + name: decryptedMetadata.name, + createdAt: decryptedMetadata.createdAt, + lastModifiedAt: decryptedMetadata.lastModifiedAt, + categoryIds: categories.map((category) => category.id), + }); + return { id, exists: true as const, @@ -82,7 +93,7 @@ const fetchFromServer = async (id: number, masterKey: CryptoKey) => { contentType: metadata.contentType, contentIv: metadata.contentIv, categories, - ...(await decryptFileMetadata(metadata, masterKey)), + ...decryptedMetadata, }; } catch (e) { if (isTRPCClientError(e) && e.data?.code === "NOT_FOUND") { @@ -97,12 +108,25 @@ const bulkFetchFromServer = async (ids: number[], masterKey: CryptoKey) => { const filesRaw = await trpc().file.bulkGet.query({ ids }); const files = await Promise.all( filesRaw.map(async (file) => { - const categories = await Promise.all( - file.categories.map(async (category) => ({ - id: category.id, - ...(await decryptCategoryMetadata(category, masterKey)), - })), - ); + const [categories, decryptedMetadata] = await Promise.all([ + Promise.all( + file.categories.map(async (category) => ({ + id: category.id, + ...(await decryptCategoryMetadata(category, masterKey)), + })), + ), + decryptFileMetadata(file, masterKey), + ]); + + await IndexedDB.storeFileInfo({ + id: file.id, + parentId: file.parent, + contentType: file.contentType, + name: decryptedMetadata.name, + createdAt: decryptedMetadata.createdAt, + lastModifiedAt: decryptedMetadata.lastModifiedAt, + categoryIds: categories.map((category) => category.id), + }); return { id: file.id, exists: true as const, @@ -110,7 +134,7 @@ const bulkFetchFromServer = async (ids: number[], masterKey: CryptoKey) => { contentType: file.contentType, contentIv: file.contentIv, categories, - ...(await decryptFileMetadata(file, masterKey)), + ...decryptedMetadata, }; }), );