diff --git a/src/lib/components/organisms/Category/Category.svelte b/src/lib/components/organisms/Category/Category.svelte index 4da2a07..4472519 100644 --- a/src/lib/components/organisms/Category/Category.svelte +++ b/src/lib/components/organisms/Category/Category.svelte @@ -1,10 +1,9 @@
@@ -90,7 +87,7 @@
{#key info} - {#each files as { info, isRecursive }} + {#each $files as { info, isRecursive }} - import type { Writable } from "svelte/store"; import { ActionEntryButton } from "$lib/components/atoms"; import { DirectoryEntryLabel } from "$lib/components/molecules"; - import type { FileInfo, FileInfoStore } from "$lib/modules/filesystem2"; + import type { FileInfo } from "$lib/modules/filesystem2"; import { requestFileThumbnailDownload, type SelectedFile } from "./service"; import IconClose from "~icons/material-symbols/close"; interface Props { - info: FileInfoStore; + info: FileInfo; onclick: (selectedFile: SelectedFile) => void; onRemoveClick?: (selectedFile: SelectedFile) => void; } @@ -18,22 +17,22 @@ let thumbnail: string | undefined = $state(); const openFile = () => { - const { id, dataKey, dataKeyVersion, name } = $info.data as FileInfo; + const { id, dataKey, dataKeyVersion, name } = info; if (!dataKey || !dataKeyVersion) return; // TODO: Error handling onclick({ id, dataKey, dataKeyVersion, name }); }; const removeFile = () => { - const { id, dataKey, dataKeyVersion, name } = $info.data as FileInfo; + const { id, dataKey, dataKeyVersion, name } = info; if (!dataKey || !dataKeyVersion) return; // TODO: Error handling onRemoveClick!({ id, dataKey, dataKeyVersion, name }); }; $effect(() => { - if ($info.data?.dataKey) { - requestFileThumbnailDownload($info.data.id, $info.data.dataKey) + if (info.dataKey) { + requestFileThumbnailDownload(info.id, info.dataKey) .then((thumbnailUrl) => { thumbnail = thumbnailUrl ?? undefined; }) @@ -47,13 +46,11 @@ }); -{#if $info.status === "success"} - - - -{/if} + + + diff --git a/src/lib/hooks/callApi.ts b/src/lib/hooks/callApi.ts index 1699ec2..a544130 100644 --- a/src/lib/hooks/callApi.ts +++ b/src/lib/hooks/callApi.ts @@ -1,11 +1,24 @@ -export const callGetApi = async (input: RequestInfo, fetchInternal = fetch) => { - return await fetchInternal(input); +interface FetchOptions { + fetch?: typeof fetch; + signal?: AbortSignal; +} + +export const callGetApi = async ( + input: RequestInfo, + { fetch = globalThis.fetch, signal }: FetchOptions = {}, +) => { + return await fetch(input, { method: "GET", signal }); }; -export const callPostApi = async (input: RequestInfo, payload?: T, fetchInternal = fetch) => { - return await fetchInternal(input, { +export const callPostApi = async ( + input: RequestInfo, + payload?: T, + { fetch = globalThis.fetch, signal }: FetchOptions = {}, +) => { + return await fetch(input, { method: "POST", headers: { "Content-Type": "application/json" }, body: payload ? JSON.stringify(payload) : undefined, + signal, }); }; diff --git a/src/lib/modules/filesystem2/directory.ts b/src/lib/modules/filesystem2/directory.ts index d7612d1..91ae655 100644 --- a/src/lib/modules/filesystem2/directory.ts +++ b/src/lib/modules/filesystem2/directory.ts @@ -1,5 +1,4 @@ import { useQueryClient, createQuery, createMutation } from "@tanstack/svelte-query"; -import { browser } from "$app/environment"; import { callGetApi, callPostApi } from "$lib/hooks"; import { getDirectoryInfos as getDirectoryInfosFromIndexedDB, @@ -44,17 +43,11 @@ export type DirectoryInfo = subDirectoryIds: number[]; fileIds: number[]; }; +export type SubDirectoryInfo = DirectoryInfo & { id: number }; -const initializedIds = new Set(); let temporaryIdCounter = -1; const getInitialDirectoryInfo = async (id: DirectoryId) => { - if (!browser || initializedIds.has(id)) { - return undefined; - } else { - initializedIds.add(id); - } - const [directory, subDirectories, files] = await Promise.all([ id !== "root" ? getDirectoryInfoFromIndexedDB(id) : undefined, getDirectoryInfosFromIndexedDB(id), @@ -72,16 +65,18 @@ const getInitialDirectoryInfo = async (id: DirectoryId) => { }; export const getDirectoryInfo = (id: DirectoryId, masterKey: CryptoKey) => { - const queryClient = useQueryClient(); - getInitialDirectoryInfo(id).then((info) => { - if (info && !queryClient.getQueryData(["directory", id])) { - queryClient.setQueryData(["directory", id], info); - } - }); // Intended return createQuery({ queryKey: ["directory", id], - queryFn: async () => { - const res = await callGetApi(`/api/directory/${id}`); // TODO: 404 + queryFn: async ({ client, signal }) => { + if (!client.getQueryData(["directory", id])) { + const initialInfo = await getInitialDirectoryInfo(id); + if (initialInfo) { + setTimeout(() => client.invalidateQueries({ queryKey: ["directory", id] }), 0); + return initialInfo; + } + } + + const res = await callGetApi(`/api/directory/${id}`, { signal }); // TODO: 404 const { metadata, subDirectories: subDirectoryIds, @@ -202,7 +197,7 @@ export const useDirectoryRename = () => { onMutate: async ({ id, newName }) => { await queryClient.cancelQueries({ queryKey: ["directory", id] }); - const prevInfo = queryClient.getQueryData(["directory", id]); + const prevInfo = queryClient.getQueryData(["directory", id]); if (prevInfo) { queryClient.setQueryData(["directory", id], { ...prevInfo, @@ -214,7 +209,7 @@ export const useDirectoryRename = () => { }, onError: (_error, { id }, context) => { if (context?.oldName) { - queryClient.setQueryData(["directory", id], (prevInfo) => { + queryClient.setQueryData(["directory", id], (prevInfo) => { if (!prevInfo) return undefined; return { ...prevInfo, name: context.oldName! }; }); diff --git a/src/lib/modules/filesystem2/file.ts b/src/lib/modules/filesystem2/file.ts index b344a4b..79b42ab 100644 --- a/src/lib/modules/filesystem2/file.ts +++ b/src/lib/modules/filesystem2/file.ts @@ -1,5 +1,4 @@ import { useQueryClient, createQuery, createMutation } from "@tanstack/svelte-query"; -import { browser } from "$app/environment"; import { callGetApi, callPostApi } from "$lib/hooks"; import { getFileInfo as getFileInfoFromIndexedDB, @@ -26,31 +25,23 @@ export interface FileInfo { categoryIds: number[]; } -const initializedFileIds = new Set(); - -const getInitialFileInfo = async (id: number) => { - if (!browser || initializedFileIds.has(id)) { - return undefined; - } - initializedFileIds.add(id); - return await getFileInfoFromIndexedDB(id); -}; - const decryptDate = async (ciphertext: string, iv: string, dataKey: CryptoKey) => { return new Date(parseInt(await decryptString(ciphertext, iv, dataKey), 10)); }; export const getFileInfo = (id: number, masterKey: CryptoKey) => { - const queryClient = useQueryClient(); - getInitialFileInfo(id).then((info) => { - if (info && !queryClient.getQueryData(["file", id])) { - queryClient.setQueryData(["file", id], info); - } - }); // Intended return createQuery({ queryKey: ["file", id], - queryFn: async () => { - const res = await callGetApi(`/api/file/${id}`); // TODO: 404 + queryFn: async ({ client, signal }) => { + if (!client.getQueryData(["file", id])) { + const initialInfo = await getFileInfoFromIndexedDB(id); + if (initialInfo) { + setTimeout(() => client.invalidateQueries({ queryKey: ["file", id] }), 0); + return initialInfo; + } + } + + const res = await callGetApi(`/api/file/${id}`, { signal }); // TODO: 404 const metadata: FileInfoResponse = await res.json(); const { dataKey } = await unwrapDataKey(metadata.dek, masterKey); diff --git a/src/routes/(fullscreen)/settings/thumbnail/+page.ts b/src/routes/(fullscreen)/settings/thumbnail/+page.ts index a16cb8e..c520985 100644 --- a/src/routes/(fullscreen)/settings/thumbnail/+page.ts +++ b/src/routes/(fullscreen)/settings/thumbnail/+page.ts @@ -4,7 +4,7 @@ import type { MissingThumbnailFileScanResponse } from "$lib/server/schemas"; import type { PageLoad } from "./$types"; export const load: PageLoad = async ({ fetch }) => { - const res = await callPostApi("/api/file/scanMissingThumbnails", undefined, fetch); + const res = await callPostApi("/api/file/scanMissingThumbnails", undefined, { fetch }); if (!res.ok) { error(500, "Internal server error"); } diff --git a/src/routes/(main)/directory/[[id]]/+page.svelte b/src/routes/(main)/directory/[[id]]/+page.svelte index 76695c3..fa7e7b0 100644 --- a/src/routes/(main)/directory/[[id]]/+page.svelte +++ b/src/routes/(main)/directory/[[id]]/+page.svelte @@ -109,7 +109,7 @@ goto("/file/uploads")} /> goto("/file/downloads")} />
- {#key $info} + {#key $info.data.id} goto(`/${type}/${id}`)} diff --git a/src/routes/(main)/directory/[[id]]/DirectoryEntries/DirectoryEntries.svelte b/src/routes/(main)/directory/[[id]]/DirectoryEntries/DirectoryEntries.svelte index 8377ae7..cc21dd4 100644 --- a/src/routes/(main)/directory/[[id]]/DirectoryEntries/DirectoryEntries.svelte +++ b/src/routes/(main)/directory/[[id]]/DirectoryEntries/DirectoryEntries.svelte @@ -1,12 +1,11 @@ -{#if subDirectories.length + files.length > 0} +{#if $subDirectories.length + $everyFiles.length > 0}
- {#each subDirectories as { info }} + {#each $subDirectories as { info }} {/each} - {#each files as file} + {#each $everyFiles as file} {#if file.type === "file"} {:else} diff --git a/src/routes/(main)/directory/[[id]]/DirectoryEntries/File.svelte b/src/routes/(main)/directory/[[id]]/DirectoryEntries/File.svelte index cbaa965..4a14054 100644 --- a/src/routes/(main)/directory/[[id]]/DirectoryEntries/File.svelte +++ b/src/routes/(main)/directory/[[id]]/DirectoryEntries/File.svelte @@ -1,7 +1,7 @@ -{#if $info.status === "success"} - - - -{/if} + + + diff --git a/src/routes/(main)/directory/[[id]]/DirectoryEntries/SubDirectory.svelte b/src/routes/(main)/directory/[[id]]/DirectoryEntries/SubDirectory.svelte index 2c4b4fd..9568e74 100644 --- a/src/routes/(main)/directory/[[id]]/DirectoryEntries/SubDirectory.svelte +++ b/src/routes/(main)/directory/[[id]]/DirectoryEntries/SubDirectory.svelte @@ -1,15 +1,13 @@ -{#if $info} - - - -{/if} + + + diff --git a/src/routes/(main)/directory/[[id]]/DirectoryEntries/UploadingFile.svelte b/src/routes/(main)/directory/[[id]]/DirectoryEntries/UploadingFile.svelte index a6df05a..498bb56 100644 --- a/src/routes/(main)/directory/[[id]]/DirectoryEntries/UploadingFile.svelte +++ b/src/routes/(main)/directory/[[id]]/DirectoryEntries/UploadingFile.svelte @@ -1,36 +1,35 @@ -{#if isFileUploading($status.status)} +{#if isFileUploading(status.status)}
-

- {$status.name} +

+ {status.name}

- {#if $status.status === "encryption-pending"} + {#if status.status === "encryption-pending"} 준비 중 - {:else if $status.status === "encrypting"} + {:else if status.status === "encrypting"} 암호화하는 중 - {:else if $status.status === "upload-pending"} + {:else if status.status === "upload-pending"} 업로드를 기다리는 중 - {:else if $status.status === "uploading"} - 전송됨 {Math.floor(($status.progress ?? 0) * 100)}% · - {formatNetworkSpeed(($status.rate ?? 0) * 8)} + {:else if status.status === "uploading"} + 전송됨 {Math.floor((status.progress ?? 0) * 100)}% · + {formatNetworkSpeed((status.rate ?? 0) * 8)} {/if}

diff --git a/src/routes/(main)/menu/+page.ts b/src/routes/(main)/menu/+page.ts index 30a265a..0055128 100644 --- a/src/routes/(main)/menu/+page.ts +++ b/src/routes/(main)/menu/+page.ts @@ -4,7 +4,7 @@ import type { UserInfoResponse } from "$lib/server/schemas"; import type { PageLoad } from "./$types"; export const load: PageLoad = async ({ fetch }) => { - const res = await callGetApi("/api/user", fetch); + const res = await callGetApi("/api/user", { fetch }); if (!res.ok) { error(500, "Internal server error"); }