From 4c0d668cc1fcb8a11ce63364a547358e83fc0f24 Mon Sep 17 00:00:00 2001 From: static Date: Wed, 22 Jan 2025 13:50:36 +0900 Subject: [PATCH] =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EC=97=90=20=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EB=B0=8F=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=EC=97=90=20=EC=B6=94=EA=B0=80=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/modules/filesystem.ts | 4 +- .../molecules/Categories/Categories.svelte | 12 +-- src/lib/server/db/file.ts | 9 +++ src/lib/server/schemas/file.ts | 1 + src/lib/server/services/file.ts | 3 + .../(fullscreen)/file/[id]/+page.svelte | 77 +++++++++++++------ src/routes/api/file/[id]/+server.ts | 2 + 7 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/lib/modules/filesystem.ts b/src/lib/modules/filesystem.ts index cfafbbe..f098456 100644 --- a/src/lib/modules/filesystem.ts +++ b/src/lib/modules/filesystem.ts @@ -46,6 +46,7 @@ export interface FileInfo { name: string; createdAt?: Date; lastModifiedAt: Date; + categoryIds: number[]; } type CategoryId = "root" | number; @@ -160,7 +161,7 @@ const fetchFileInfoFromIndexedDB = async (id: number, info: Writable { @@ -204,6 +205,7 @@ const fetchFileInfoFromServer = async ( name, createdAt, lastModifiedAt, + categoryIds: metadata.categories, }); await storeFileInfo({ id, diff --git a/src/lib/molecules/Categories/Categories.svelte b/src/lib/molecules/Categories/Categories.svelte index 2fdbfad..ef21e0e 100644 --- a/src/lib/molecules/Categories/Categories.svelte +++ b/src/lib/molecules/Categories/Categories.svelte @@ -12,8 +12,10 @@ let { categories, onCategoryClick }: Props = $props(); -
- {#each categories as category} - - {/each} -
+{#if categories.length > 0} +
+ {#each categories as category} + + {/each} +
+{/if} diff --git a/src/lib/server/db/file.ts b/src/lib/server/db/file.ts index 8b7819b..46c8d66 100644 --- a/src/lib/server/db/file.ts +++ b/src/lib/server/db/file.ts @@ -441,6 +441,15 @@ export const addFileToCategory = async (fileId: number, categoryId: number) => { }); }; +export const getAllFileCategories = async (fileId: number) => { + const categories = await db + .selectFrom("file_category") + .select("category_id") + .where("file_id", "=", fileId) + .execute(); + return categories.map(({ category_id }) => ({ id: category_id })); +}; + export const removeFileFromCategory = async (fileId: number, categoryId: number) => { await db.transaction().execute(async (trx) => { const res = await trx diff --git a/src/lib/server/schemas/file.ts b/src/lib/server/schemas/file.ts index 8f552f7..ed0af94 100644 --- a/src/lib/server/schemas/file.ts +++ b/src/lib/server/schemas/file.ts @@ -18,6 +18,7 @@ export const fileInfoResponse = z.object({ createdAtIv: z.string().base64().nonempty().optional(), lastModifiedAt: z.string().base64().nonempty(), lastModifiedAtIv: z.string().base64().nonempty(), + categories: z.number().int().positive().array(), }); export type FileInfoResponse = z.infer; diff --git a/src/lib/server/services/file.ts b/src/lib/server/services/file.ts index 0f2d371..519bdfd 100644 --- a/src/lib/server/services/file.ts +++ b/src/lib/server/services/file.ts @@ -13,6 +13,7 @@ import { getFile, setFileEncName, unregisterFile, + getAllFileCategories, type NewFile, } from "$lib/server/db/file"; import type { Ciphertext } from "$lib/server/db/schema"; @@ -24,6 +25,7 @@ export const getFileInformation = async (userId: number, fileId: number) => { error(404, "Invalid file id"); } + const categories = await getAllFileCategories(fileId); return { parentId: file.parentId ?? ("root" as const), mekVersion: file.mekVersion, @@ -34,6 +36,7 @@ export const getFileInformation = async (userId: number, fileId: number) => { encName: file.encName, encCreatedAt: file.encCreatedAt, encLastModifiedAt: file.encLastModifiedAt, + categories: categories.map(({ id }) => id), }; }; diff --git a/src/routes/(fullscreen)/file/[id]/+page.svelte b/src/routes/(fullscreen)/file/[id]/+page.svelte index 2b27d89..89dc04d 100644 --- a/src/routes/(fullscreen)/file/[id]/+page.svelte +++ b/src/routes/(fullscreen)/file/[id]/+page.svelte @@ -2,18 +2,29 @@ import FileSaver from "file-saver"; import { untrack } from "svelte"; import { get, type Writable } from "svelte/store"; + import { goto } from "$app/navigation"; import { TopBar } from "$lib/components"; - import { getFileInfo, type FileInfo } from "$lib/modules/filesystem"; + import { EntryButton } from "$lib/components/buttons"; + import { + getFileInfo, + getCategoryInfo, + type FileInfo, + type CategoryInfo, + } from "$lib/modules/filesystem"; + import Categories from "$lib/molecules/Categories"; import { fileDownloadStatusStore, isFileDownloading, masterKeyStore } from "$lib/stores"; import AddToCategoryBottomSheet from "./AddToCategoryBottomSheet.svelte"; import DownloadStatus from "./DownloadStatus.svelte"; import { requestFileDownload, requestFileAdditionToCategory } from "./service"; + import IconAddCircle from "~icons/material-symbols/add-circle"; + let { data } = $props(); let info: Writable | undefined = $state(); + let categories: Writable[] = $state([]); - let isAddToCategoryBottomSheetOpen = $state(true); + let isAddToCategoryBottomSheetOpen = $state(false); const downloadStatus = $derived( $fileDownloadStatusStore.find((statusStore) => { @@ -50,6 +61,7 @@ const addToCategory = async (categoryId: number) => { await requestFileAdditionToCategory(data.id, categoryId); isAddToCategoryBottomSheetOpen = false; + info = getFileInfo(data.id, $masterKeyStore?.get(1)?.key!); // TODO: FIXME }; $effect(() => { @@ -58,6 +70,13 @@ viewerType = undefined; }); + $effect(() => { + categories = + $info?.categoryIds.map((id) => getCategoryInfo(id, $masterKeyStore?.get(1)?.key!)) ?? []; + + // TODO: Sorting + }); + $effect(() => { if ($info && $info.dataKey && $info.contentIv) { untrack(() => { @@ -89,28 +108,42 @@
- -
- {#snippet viewerLoading(message: string)} -
-

{message}

-
- {/snippet} +
+ + {#if $info && viewerType} +
+ {#snippet viewerLoading(message: string)} +

{message}

+ {/snippet} - {#if $info && viewerType === "image"} - {#if fileBlobUrl} - {$info.name} - {:else} - {@render viewerLoading("이미지를 불러오고 있어요.")} - {/if} - {:else if viewerType === "video"} - {#if fileBlobUrl} - - - {:else} - {@render viewerLoading("비디오를 불러오고 있어요.")} - {/if} + {#if viewerType === "image"} + {#if fileBlobUrl} + {$info.name} + {:else} + {@render viewerLoading("이미지를 불러오고 있어요.")} + {/if} + {:else if viewerType === "video"} + {#if fileBlobUrl} + + + {:else} + {@render viewerLoading("비디오를 불러오고 있어요.")} + {/if} + {/if} +
{/if} +
+

카테고리

+
+ goto(`/category/${id}`)} /> + (isAddToCategoryBottomSheetOpen = true)}> +
+ +

카테고리에 추가하기

+
+
+
+
diff --git a/src/routes/api/file/[id]/+server.ts b/src/routes/api/file/[id]/+server.ts index 892f62b..23e9385 100644 --- a/src/routes/api/file/[id]/+server.ts +++ b/src/routes/api/file/[id]/+server.ts @@ -26,6 +26,7 @@ export const GET: RequestHandler = async ({ locals, params }) => { encName, encCreatedAt, encLastModifiedAt, + categories, } = await getFileInformation(userId, id); return json( fileInfoResponse.parse({ @@ -41,6 +42,7 @@ export const GET: RequestHandler = async ({ locals, params }) => { createdAtIv: encCreatedAt?.iv, lastModifiedAt: encLastModifiedAt.ciphertext, lastModifiedAtIv: encLastModifiedAt.iv, + categories, } satisfies FileInfoResponse), ); };