패키지 버전 업데이트 및 SvelteKit 3, Tailwind CSS 4로 마이그레이션

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
staticandClaude Opus 5.5 committed 2026-10-11 20:49:24 +09:00
1 parent 35f3e92b5a
commit 67989f4741
155 files changed
+1834 -2299

No files matched your search

+1 -1
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import { AdaptiveDiv } from "$lib/components/atoms";
import { AdaptiveDiv } from "#lib/components/atoms/index.js";
let { children } = $props();
</script>
@@ -1,7 +1,7 @@
<script lang="ts">
import { goto } from "$app/navigation";
import { BottomDiv, Button, FullscreenDiv, TextInput } from "$lib/components/atoms";
import { TitledDiv, TopBar } from "$lib/components/molecules";
import { BottomDiv, Button, FullscreenDiv, TextInput } from "#lib/components/atoms/index.js";
import { TitledDiv, TopBar } from "#lib/components/molecules/index.js";
import { requestPasswordChange } from "./service";
let oldPassword = $state("");
@@ -24,9 +24,9 @@
<title>비밀번호 바꾸기</title>
</svelte:head>
<TopBar class="flex-shrink-0" />
<TopBar class="shrink-0" />
<FullscreenDiv>
<TitledDiv class="!pt-0" titleClass="!text-2xl" childrenClass="flex flex-col gap-y-2">
<TitledDiv class="pt-0!" titleClass="text-2xl!" childrenClass="flex flex-col gap-y-2">
{#snippet title()}
기존 비밀번호와 새 비밀번호를 입력해 주세요.
{/snippet}
@@ -1,4 +1,4 @@
import { trpc } from "$trpc/client";
import { trpc } from "#trpc/client.js";
export const requestPasswordChange = async (oldPassword: string, newPassword: string) => {
try {
@@ -1,9 +1,15 @@
<script lang="ts">
import { goto } from "$app/navigation";
import { BottomDiv, Button, FullscreenDiv, TextButton, TextInput } from "$lib/components/atoms";
import { TitledDiv } from "$lib/components/molecules";
import { ForceLoginModal } from "$lib/components/organisms";
import { clientKeyStore, masterKeyStore } from "$lib/stores";
import {
BottomDiv,
Button,
FullscreenDiv,
TextButton,
TextInput,
} from "#lib/components/atoms/index.js";
import { TitledDiv } from "#lib/components/molecules/index.js";
import { ForceLoginModal } from "#lib/components/organisms/index.js";
import { clientKeyStore, masterKeyStore } from "#lib/stores/index.js";
import {
requestLogin,
requestClientRegistrationAndSessionUpgrade,
@@ -1,11 +1,11 @@
import { trpc } from "$trpc/client";
import { trpc } from "#trpc/client.js";
export { requestLogout } from "$lib/services/auth";
export { requestDeletedFilesCleanup } from "$lib/services/file";
export { requestLogout } from "#lib/services/auth.js";
export { requestDeletedFilesCleanup } from "#lib/services/file.js";
export {
requestClientRegistrationAndSessionUpgrade,
requestMasterKeyDownload,
} from "$lib/services/key";
} from "#lib/services/key.js";
export const requestLogin = async (email: string, password: string) => {
try {
@@ -1,9 +1,9 @@
<script lang="ts">
import { onMount } from "svelte";
import { goto } from "$app/navigation";
import { FullscreenDiv } from "$lib/components/atoms";
import { TitledDiv } from "$lib/components/molecules";
import { clientKeyStore, masterKeyStore } from "$lib/stores";
import { FullscreenDiv } from "#lib/components/atoms/index.js";
import { TitledDiv } from "#lib/components/molecules/index.js";
import { clientKeyStore, masterKeyStore } from "#lib/stores/index.js";
import { generatePublicKeyFingerprint, requestMasterKeyDownload } from "./service";
import IconFingerprint from "~icons/material-symbols/fingerprint";
@@ -22,7 +22,7 @@
($clientKeyStore &&
(await requestMasterKeyDownload($clientKeyStore.decryptKey, $clientKeyStore.verifyKey)))
) {
await goto(data.redirectPath, { replaceState: true });
await goto(data.redirectPath, { replace: true });
}
});
</script>
@@ -1,6 +1,6 @@
import { concatenateBuffers, exportRSAKey, digestMessage } from "$lib/modules/crypto";
import { concatenateBuffers, exportRSAKey, digestMessage } from "#lib/modules/crypto/index.js";
export { requestMasterKeyDownload } from "$lib/services/key";
export { requestMasterKeyDownload } from "#lib/services/key.js";
export const generatePublicKeyFingerprint = async (encryptKey: CryptoKey, verifyKey: CryptoKey) => {
const { key: encryptKeyBuffer } = await exportRSAKey(encryptKey);
@@ -3,13 +3,13 @@
import { untrack } from "svelte";
import { goto } from "$app/navigation";
import { page } from "$app/state";
import { FullscreenDiv } from "$lib/components/atoms";
import { Categories, IconEntryButton, TopBar } from "$lib/components/molecules";
import { getFileInfo, type MaybeFileInfo } from "$lib/modules/filesystem";
import { captureVideoThumbnail } from "$lib/modules/thumbnail";
import { getFileDownloadState } from "$lib/modules/file";
import { masterKeyStore } from "$lib/stores";
import { HybridPromise } from "$lib/utils";
import { FullscreenDiv } from "#lib/components/atoms/index.js";
import { Categories, IconEntryButton, TopBar } from "#lib/components/molecules/index.js";
import { getFileInfo, type MaybeFileInfo } from "#lib/modules/filesystem/index.js";
import { captureVideoThumbnail } from "#lib/modules/thumbnail.js";
import { getFileDownloadState } from "#lib/modules/file/index.js";
import { masterKeyStore } from "#lib/stores/index.js";
import { HybridPromise } from "#lib/utils/index.js";
import AddToCategoryBottomSheet from "./AddToCategoryBottomSheet.svelte";
import DownloadStatus from "./DownloadStatus.svelte";
import {
@@ -150,7 +150,7 @@
<div onclick={(e) => e.stopPropagation()}>
<button
onclick={() => (isMenuOpen = !isMenuOpen)}
class="w-full rounded-full p-1 text-2xl active:bg-black active:bg-opacity-[0.04]"
class="w-full rounded-full p-1 text-2xl active:bg-black/4"
>
<IconMoreVert />
</button>
@@ -1,10 +1,10 @@
<script lang="ts">
import { BottomDiv, BottomSheet, Button, FullscreenDiv } from "$lib/components/atoms";
import { SubCategories } from "$lib/components/molecules";
import { CategoryCreateModal } from "$lib/components/organisms";
import { getCategoryInfo, type MaybeCategoryInfo } from "$lib/modules/filesystem";
import { masterKeyStore } from "$lib/stores";
import { HybridPromise } from "$lib/utils";
import { BottomDiv, BottomSheet, Button, FullscreenDiv } from "#lib/components/atoms/index.js";
import { SubCategories } from "#lib/components/molecules/index.js";
import { CategoryCreateModal } from "#lib/components/organisms/index.js";
import { getCategoryInfo, type MaybeCategoryInfo } from "#lib/modules/filesystem/index.js";
import { masterKeyStore } from "#lib/stores/index.js";
import { HybridPromise } from "#lib/utils/index.js";
import { requestCategoryCreation } from "./service";
interface Props {
@@ -1,6 +1,6 @@
<script lang="ts">
import { isFileDownloading, type FileDownloadState } from "$lib/modules/file";
import { formatNetworkSpeed } from "$lib/utils";
import { isFileDownloading, type FileDownloadState } from "#lib/modules/file/index.js";
import { formatNetworkSpeed } from "#lib/utils/index.js";
interface Props {
state: FileDownloadState;
@@ -46,7 +46,7 @@
{#if isOpen && (directoryId || downloadUrl || fileBlob)}
<div
class="absolute right-2 top-full z-20 min-w-44 space-y-1 rounded-lg bg-white px-1 py-2 shadow-2xl"
class="absolute top-full right-2 z-20 min-w-44 space-y-1 rounded-lg bg-white px-1 py-2 shadow-2xl"
transition:fly={{ y: -8, duration: 200 }}
>
<p class="px-3 pt-2 text-sm font-semibold text-gray-600">더보기</p>
+6 -6
View File
@@ -1,10 +1,10 @@
import { storeFileThumbnailCache } from "$lib/modules/file";
import { prepareFileDecryption, getDecryptedFileUrl } from "$lib/serviceWorker";
import { requestFileThumbnailUpload } from "$lib/services/file";
import { trpc } from "$trpc/client";
import { storeFileThumbnailCache } from "#lib/modules/file/index.js";
import { prepareFileDecryption, getDecryptedFileUrl } from "#lib/serviceWorker/index.js";
import { requestFileThumbnailUpload } from "#lib/services/file.js";
import { trpc } from "#trpc/client.js";
export { requestCategoryCreation, requestFileRemovalFromCategory } from "$lib/services/category";
export { requestFileDownload } from "$lib/services/file";
export { requestCategoryCreation, requestFileRemovalFromCategory } from "#lib/services/category.js";
export { requestFileDownload } from "#lib/services/file.js";
export const requestVideoStream = async (
fileId: number,
@@ -1,14 +1,14 @@
<script lang="ts">
import { onMount } from "svelte";
import { FullscreenDiv } from "$lib/components/atoms";
import { TopBar } from "$lib/components/molecules";
import { FullscreenDiv } from "#lib/components/atoms/index.js";
import { TopBar } from "#lib/components/molecules/index.js";
import {
getDownloadingFiles,
clearDownloadedFiles,
type FileDownloadState,
} from "$lib/modules/file";
import { bulkGetFileInfo, type MaybeFileInfo } from "$lib/modules/filesystem";
import { masterKeyStore } from "$lib/stores";
} from "#lib/modules/file/index.js";
import { bulkGetFileInfo, type MaybeFileInfo } from "#lib/modules/filesystem/index.js";
import { masterKeyStore } from "#lib/stores/index.js";
import File from "./File.svelte";
let downloadingFiles: { info: MaybeFileInfo; state: FileDownloadState }[] = $state([]);
@@ -1,7 +1,7 @@
<script lang="ts">
import type { FileDownloadState } from "$lib/modules/file";
import type { SummarizedFileInfo } from "$lib/modules/filesystem";
import { formatNetworkSpeed } from "$lib/utils";
import type { FileDownloadState } from "#lib/modules/file/index.js";
import type { SummarizedFileInfo } from "#lib/modules/filesystem/index.js";
import { formatNetworkSpeed } from "#lib/utils/index.js";
import IconCloud from "~icons/material-symbols/cloud";
import IconCloudDownload from "~icons/material-symbols/cloud-download";
@@ -19,7 +19,7 @@
</script>
<div class="flex h-14 items-center gap-x-4 p-2">
<div class="flex-shrink-0 text-lg text-gray-600">
<div class="shrink-0 text-lg text-gray-600">
{#if state.status === "download-pending"}
<IconCloud />
{:else if state.status === "downloading"}
@@ -34,7 +34,7 @@
<IconError class="text-red-500" />
{/if}
</div>
<div class="flex-grow overflow-hidden">
<div class="grow overflow-hidden">
<p title={info.name} class="truncate font-medium">
{info.name}
</p>
@@ -1,7 +1,7 @@
<script lang="ts">
import { FullscreenDiv } from "$lib/components/atoms";
import { TopBar } from "$lib/components/molecules";
import { getUploadingFiles, clearUploadedFiles } from "$lib/modules/file";
import { FullscreenDiv } from "#lib/components/atoms/index.js";
import { TopBar } from "#lib/components/molecules/index.js";
import { getUploadingFiles, clearUploadedFiles } from "#lib/modules/file/index.js";
import File from "./File.svelte";
const uploadingFiles = getUploadingFiles();
@@ -1,6 +1,6 @@
<script lang="ts">
import type { FileUploadState } from "$lib/modules/file";
import { formatNetworkSpeed } from "$lib/utils";
import type { FileUploadState } from "#lib/modules/file/index.js";
import { formatNetworkSpeed } from "#lib/utils/index.js";
import IconPending from "~icons/material-symbols/pending";
import IconLockClock from "~icons/material-symbols/lock-clock";
@@ -17,7 +17,7 @@
</script>
<div class="flex h-14 items-center gap-x-4 p-2">
<div class="flex-shrink-0 text-lg text-gray-600">
<div class="shrink-0 text-lg text-gray-600">
{#if state.status === "queued" || state.status === "encryption-pending"}
<IconPending />
{:else if state.status === "encrypting"}
@@ -32,7 +32,7 @@
<IconError class="text-red-500" />
{/if}
</div>
<div class="flex-grow overflow-hidden">
<div class="grow overflow-hidden">
<p title={state.name} class="truncate font-medium">
{state.name}
</p>
+11 -7
View File
@@ -1,15 +1,19 @@
<script lang="ts">
import { onMount } from "svelte";
import { goto } from "$app/navigation";
import { FileThumbnailButton, FullscreenDiv, RowVirtualizer } from "$lib/components/atoms";
import { TopBar } from "$lib/components/molecules";
import {
FileThumbnailButton,
FullscreenDiv,
RowVirtualizer,
} from "#lib/components/atoms/index.js";
import { TopBar } from "#lib/components/molecules/index.js";
import {
bulkGetFileInfo,
type MaybeFileInfo,
type SummarizedFileInfo,
} from "$lib/modules/filesystem";
import { masterKeyStore } from "$lib/stores";
import { formatDate, formatDateSortable, SortBy, sortEntries } from "$lib/utils";
} from "#lib/modules/filesystem/index.js";
import { masterKeyStore } from "#lib/stores/index.js";
import { formatDate, formatDateSortable, SortBy, sortEntries } from "#lib/utils/index.js";
let { data } = $props();
@@ -65,7 +69,7 @@
count={rows.length}
estimateItemHeight={(index) =>
rows[index]!.type === "header" ? 28 : 181 + (rows[index]!.isLast ? 16 : 4)}
class="flex flex-grow flex-col"
class="flex grow flex-col"
>
{#snippet item(index)}
{@const row = rows[index]!}
@@ -83,7 +87,7 @@
{/if}
{/snippet}
{#snippet placeholder()}
<div class="flex h-full flex-grow items-center justify-center">
<div class="flex h-full grow items-center justify-center">
<p class="text-gray-500">
{#if files.length === 0}
업로드된 파일이 없어요.
+1 -1
View File
@@ -1,4 +1,4 @@
import { trpc } from "$trpc/client";
import { trpc } from "#trpc/client.js";
import type { PageLoad } from "./$types";
export const load: PageLoad = async ({ parent }) => {
@@ -1,10 +1,10 @@
<script lang="ts">
import FileSaver from "file-saver";
import { goto } from "$app/navigation";
import { BottomDiv, Button, FullscreenDiv, TextButton } from "$lib/components/atoms";
import { TitledDiv } from "$lib/components/molecules";
import { serializeClientKeys, storeClientKeys } from "$lib/modules/key";
import { clientKeyStore } from "$lib/stores";
import { BottomDiv, Button, FullscreenDiv, TextButton } from "#lib/components/atoms/index.js";
import { TitledDiv } from "#lib/components/molecules/index.js";
import { serializeClientKeys, storeClientKeys } from "#lib/modules/key.js";
import { clientKeyStore } from "#lib/stores/index.js";
import BeforeContinueBottomSheet from "./BeforeContinueBottomSheet.svelte";
import BeforeContinueModal from "./BeforeContinueModal.svelte";
import {
@@ -89,7 +89,7 @@
암호 키를 파일로 내보낼까요?
{/snippet}
<div class="space-y-2 break-keep text-lg text-gray-800">
<div class="space-y-2 text-lg break-keep text-gray-800">
<p>
모든 디바이스의 암호 키가 유실되면, 서버에 저장된 데이터를 영원히 복호화할 수 없게 돼요.
</p>
+1 -1
View File
@@ -1,5 +1,5 @@
import { error } from "@sveltejs/kit";
import { keyExportState } from "$lib/utils";
import { keyExportState } from "#lib/utils/index.js";
import type { PageLoad } from "./$types";
export const load: PageLoad = async () => {
@@ -1,5 +1,5 @@
<script lang="ts">
import { BottomDiv, BottomSheet, Button, FullscreenDiv } from "$lib/components/atoms";
import { BottomDiv, BottomSheet, Button, FullscreenDiv } from "#lib/components/atoms/index.js";
interface Props {
onRetryClick: () => void;
@@ -12,7 +12,7 @@
<BottomSheet bind:isOpen class="flex flex-col">
<FullscreenDiv>
<div class="space-y-2 break-keep py-4">
<div class="space-y-2 py-4 break-keep">
<p class="text-xl font-bold">암호 키 파일을 저장하셨나요?</p>
<p>
암호 키 파일은 유출 방지를 위해 이 화면에서만 저장할 수 있어요. 파일이 잘 저장되었는지 다시
@@ -1,5 +1,5 @@
<script lang="ts">
import { ActionModal } from "$lib/components/molecules";
import { ActionModal } from "#lib/components/molecules/index.js";
interface Props {
isOpen: boolean;
@@ -1,5 +1,5 @@
export { requestSessionUpgrade } from "$lib/services/auth";
export { requestSessionUpgrade } from "#lib/services/auth.js";
export {
requestClientRegistration,
requestInitialMasterKeyAndHmacSecretRegistration,
} from "$lib/services/key";
} from "#lib/services/key.js";
@@ -1,12 +1,12 @@
<script lang="ts">
import { onMount } from "svelte";
import { goto } from "$app/navigation";
import { BottomDiv, Button, FullscreenDiv, TextButton } from "$lib/components/atoms";
import { TitledDiv } from "$lib/components/molecules";
import { ForceLoginModal } from "$lib/components/organisms";
import { storeClientKeys } from "$lib/modules/key";
import { clientKeyStore } from "$lib/stores";
import { gotoStateful } from "$lib/utils";
import { BottomDiv, Button, FullscreenDiv, TextButton } from "#lib/components/atoms/index.js";
import { TitledDiv } from "#lib/components/molecules/index.js";
import { ForceLoginModal } from "#lib/components/organisms/index.js";
import { storeClientKeys } from "#lib/modules/key.js";
import { clientKeyStore } from "#lib/stores/index.js";
import { gotoStateful } from "#lib/utils/index.js";
import Order from "./Order.svelte";
import {
generateClientKeys,
@@ -111,7 +111,7 @@
onMount(async () => {
if ($clientKeyStore) {
await goto(data.redirectPath, { replaceState: true });
await goto(data.redirectPath, { replace: true });
}
});
</script>
@@ -12,12 +12,12 @@
<div class="flex gap-x-3">
<div class="flex flex-col">
<p
class="flex h-8 w-8 items-center justify-center rounded-full bg-gray-200 text-lg font-bold text-gray-700"
class="flex size-8 items-center justify-center rounded-full bg-gray-200 text-lg font-bold text-gray-700"
>
{order}
</p>
{#if !isLast}
<div class="mx-auto mt-2 w-0.5 flex-grow rounded-full bg-gray-300"></div>
<div class="mx-auto mt-2 w-0.5 grow rounded-full bg-gray-300"></div>
{/if}
</div>
<div class="mb-5 space-y-1 break-keep">
@@ -10,16 +10,16 @@ import {
makeAESKeyNonextractable,
wrapHmacSecret,
generateHmacSecret,
} from "$lib/modules/crypto";
import { deserializeClientKeys } from "$lib/modules/key";
import { clientKeyStore } from "$lib/stores";
} from "#lib/modules/crypto/index.js";
import { deserializeClientKeys } from "#lib/modules/key.js";
import { clientKeyStore } from "#lib/stores/index.js";
export { requestLogout } from "$lib/services/auth";
export { requestDeletedFilesCleanup } from "$lib/services/file";
export { requestLogout } from "#lib/services/auth.js";
export { requestDeletedFilesCleanup } from "#lib/services/file.js";
export {
requestClientRegistrationAndSessionUpgrade,
requestInitialMasterKeyAndHmacSecretRegistration,
} from "$lib/services/key";
} from "#lib/services/key.js";
export const generateClientKeys = async () => {
const { encryptKey, decryptKey } = await generateEncryptionKeyPair();
+9 -9
View File
@@ -4,14 +4,14 @@
import { untrack } from "svelte";
import { slide } from "svelte/transition";
import { goto } from "$app/navigation";
import { Chip, FullscreenDiv, RowVirtualizer } from "$lib/components/atoms";
import { Chip, FullscreenDiv, RowVirtualizer } from "#lib/components/atoms/index.js";
import {
getDirectoryInfo,
type LocalCategoryInfo,
type MaybeDirectoryInfo,
} from "$lib/modules/filesystem";
import { masterKeyStore } from "$lib/stores";
import { HybridPromise, searchString, sortEntries } from "$lib/utils";
} from "#lib/modules/filesystem/index.js";
import { masterKeyStore } from "#lib/stores/index.js";
import { HybridPromise, searchString, sortEntries } from "#lib/utils/index.js";
import Directory from "./Directory.svelte";
import File from "./File.svelte";
import SearchBar from "./SearchBar.svelte";
@@ -170,9 +170,9 @@
</svelte:head>
<SearchBar bind:value={filters.name} />
<FullscreenDiv class="bg-gray-100 !px-0">
<div class="flex flex-grow flex-col space-y-4">
<div class="space-y-2 bg-white p-4 !pt-0">
<FullscreenDiv class="bg-gray-100 px-0!">
<div class="flex grow flex-col space-y-4">
<div class="space-y-2 bg-white p-4 pt-0!">
<div class="space-y-3">
<div class="flex flex-wrap gap-2">
<Chip bind:selected={filters.includeImages}>사진</Chip>
@@ -214,7 +214,7 @@
</div>
</div>
{#if hasAnyFilter}
<div class="flex flex-grow flex-col space-y-2 bg-white p-4">
<div class="flex grow flex-col space-y-2 bg-white p-4">
<p class="text-lg font-bold text-gray-800">
검색 결과
{#if result.length > 0}
@@ -238,7 +238,7 @@
{/snippet}
</RowVirtualizer>
{:else}
<div class="flex flex-grow items-center justify-center py-8">
<div class="flex grow items-center justify-center py-8">
<p class="text-gray-500">검색 결과가 없어요.</p>
</div>
{/if}
@@ -1,7 +1,7 @@
<script lang="ts">
import { ActionEntryButton } from "$lib/components/atoms";
import { DirectoryEntryLabel } from "$lib/components/molecules";
import type { SubDirectoryInfo } from "$lib/modules/filesystem";
import { ActionEntryButton } from "#lib/components/atoms/index.js";
import { DirectoryEntryLabel } from "#lib/components/molecules/index.js";
import type { SubDirectoryInfo } from "#lib/modules/filesystem/index.js";
interface Props {
info: SubDirectoryInfo;
+5 -5
View File
@@ -1,9 +1,9 @@
<script lang="ts">
import { ActionEntryButton } from "$lib/components/atoms";
import { DirectoryEntryLabel } from "$lib/components/molecules";
import { getFileThumbnail } from "$lib/modules/file";
import type { SummarizedFileInfo } from "$lib/modules/filesystem";
import { formatDateTime } from "$lib/utils";
import { ActionEntryButton } from "#lib/components/atoms/index.js";
import { DirectoryEntryLabel } from "#lib/components/molecules/index.js";
import { getFileThumbnail } from "#lib/modules/file/index.js";
import type { SummarizedFileInfo } from "#lib/modules/filesystem/index.js";
import { formatDateTime } from "#lib/utils/index.js";
interface Props {
info: SummarizedFileInfo;
@@ -8,10 +8,10 @@
let { value = $bindable() }: Props = $props();
</script>
<div class={"sticky top-0 z-10 flex items-center gap-x-2 px-2 py-3 backdrop-blur-2xl"}>
<div class="sticky top-0 z-10 flex items-center gap-x-2 px-2 py-3 backdrop-blur-2xl">
<button
onclick={() => history.back()}
class="w-[2.3rem] flex-shrink-0 rounded-full p-1 active:bg-black active:bg-opacity-[0.04]"
class="w-[2.3rem] shrink-0 rounded-full p-1 active:bg-black/4"
>
<IconArrowBack class="text-2xl" />
</button>
@@ -19,6 +19,6 @@
bind:value
type="text"
placeholder="검색"
class="mr-1 h-[2.3rem] min-w-0 flex-grow rounded-lg bg-gray-100 px-3 py-1.5 placeholder-gray-600 focus:outline-none"
class="mr-1 h-[2.3rem] min-w-0 grow rounded-lg bg-gray-100 px-3 py-1.5 placeholder-gray-600 focus:outline-hidden"
/>
</div>
@@ -1,13 +1,13 @@
<script lang="ts">
import { BottomDiv, BottomSheet, Button, FullscreenDiv } from "$lib/components/atoms";
import { SubCategories } from "$lib/components/molecules";
import { BottomDiv, BottomSheet, Button, FullscreenDiv } from "#lib/components/atoms/index.js";
import { SubCategories } from "#lib/components/molecules/index.js";
import {
getCategoryInfo,
type LocalCategoryInfo,
type MaybeCategoryInfo,
} from "$lib/modules/filesystem";
import { masterKeyStore } from "$lib/stores";
import { HybridPromise } from "$lib/utils";
} from "#lib/modules/filesystem/index.js";
import { masterKeyStore } from "#lib/stores/index.js";
import { HybridPromise } from "#lib/utils/index.js";
interface Props {
isOpen: boolean;
+3 -3
View File
@@ -4,9 +4,9 @@ import {
type LocalDirectoryInfo,
type FileInfo,
type LocalCategoryInfo,
} from "$lib/modules/filesystem";
import { HybridPromise } from "$lib/utils";
import { trpc } from "$trpc/client";
} from "#lib/modules/filesystem/index.js";
import { HybridPromise } from "#lib/utils/index.js";
import { trpc } from "#trpc/client.js";
export interface SearchFilter {
ancestorId: DirectoryId;
+11 -8
View File
@@ -1,12 +1,15 @@
<script lang="ts">
import { onMount } from "svelte";
import { FullscreenDiv } from "$lib/components/atoms";
import { TopBar } from "$lib/components/molecules";
import type { FileCacheIndex } from "$lib/indexedDB";
import { getFileCacheIndex, deleteFileCache as doDeleteFileCache } from "$lib/modules/file";
import { bulkGetFileInfo, type MaybeFileInfo } from "$lib/modules/filesystem";
import { masterKeyStore } from "$lib/stores";
import { formatFileSize } from "$lib/utils";
import { FullscreenDiv } from "#lib/components/atoms/index.js";
import { TopBar } from "#lib/components/molecules/index.js";
import type { FileCacheIndex } from "#lib/indexedDB/index.js";
import {
getFileCacheIndex,
deleteFileCache as doDeleteFileCache,
} from "#lib/modules/file/index.js";
import { bulkGetFileInfo, type MaybeFileInfo } from "#lib/modules/filesystem/index.js";
import { masterKeyStore } from "#lib/stores/index.js";
import { formatFileSize } from "#lib/utils/index.js";
import File from "./File.svelte";
interface FileCache {
@@ -58,7 +61,7 @@
</div>
</div>
{:else}
<div class="flex flex-grow items-center justify-center">
<div class="flex grow items-center justify-center">
<p class="text-gray-500">
{#if fileCache}
캐시된 파일이 없어요.
+7 -7
View File
@@ -1,7 +1,7 @@
<script lang="ts">
import type { FileCacheIndex } from "$lib/indexedDB";
import type { MaybeFileInfo } from "$lib/modules/filesystem";
import { formatDate, formatFileSize } from "$lib/utils";
import type { FileCacheIndex } from "#lib/indexedDB/index.js";
import type { MaybeFileInfo } from "#lib/modules/filesystem/index.js";
import { formatDate, formatFileSize } from "#lib/utils/index.js";
import IconDraft from "~icons/material-symbols/draft";
import IconScanDelete from "~icons/material-symbols/scan-delete";
@@ -18,15 +18,15 @@
<div class="flex h-14 items-center gap-x-4 p-2">
{#if info.exists}
<div class="flex-shrink-0 rounded-full bg-blue-100 p-1 text-xl">
<div class="shrink-0 rounded-full bg-blue-100 p-1 text-xl">
<IconDraft class="text-blue-400" />
</div>
{:else}
<div class="flex-shrink-0 rounded-full bg-red-100 p-1 text-xl">
<div class="shrink-0 rounded-full bg-red-100 p-1 text-xl">
<IconScanDelete class="text-red-400" />
</div>
{/if}
<div class="flex-grow overflow-hidden">
<div class="grow overflow-hidden">
{#if info.exists}
<p title={info.name} class="truncate font-medium">{info.name}</p>
{:else}
@@ -38,7 +38,7 @@
</div>
<button
onclick={() => setTimeout(() => onDeleteClick(index.fileId), 100)}
class="flex-shrink-0 rounded-full p-1 active:bg-gray-100"
class="shrink-0 rounded-full p-1 active:bg-gray-100"
>
<IconDelete class="text-lg text-gray-600" />
</button>
@@ -1,12 +1,12 @@
<script lang="ts">
import { onMount } from "svelte";
import { goto } from "$app/navigation";
import { BottomDiv, Button, FullscreenDiv } from "$lib/components/atoms";
import { IconEntryButton, TopBar } from "$lib/components/molecules";
import { deleteAllFileThumbnailCaches } from "$lib/modules/file";
import type { MaybeFileInfo } from "$lib/modules/filesystem";
import { masterKeyStore } from "$lib/stores";
import { sortEntries } from "$lib/utils";
import { BottomDiv, Button, FullscreenDiv } from "#lib/components/atoms/index.js";
import { IconEntryButton, TopBar } from "#lib/components/molecules/index.js";
import { deleteAllFileThumbnailCaches } from "#lib/modules/file/index.js";
import type { MaybeFileInfo } from "#lib/modules/filesystem/index.js";
import { masterKeyStore } from "#lib/stores/index.js";
import { sortEntries } from "#lib/utils/index.js";
import File from "./File.svelte";
import {
getThumbnailGenerationStatus,
@@ -55,15 +55,15 @@
</svelte:head>
<TopBar title="썸네일" />
<FullscreenDiv class="bg-gray-100 !px-0">
<div class="flex flex-grow flex-col space-y-4">
<div class="bg-white p-4 !pt-0">
<FullscreenDiv class="bg-gray-100 px-0!">
<div class="flex grow flex-col space-y-4">
<div class="bg-white p-4 pt-0!">
<IconEntryButton icon={IconDelete} onclick={deleteAllFileThumbnailCaches} class="w-full">
저장된 썸네일 모두 삭제하기
</IconEntryButton>
</div>
{#if files.length > 0}
<div class="flex-grow space-y-2 bg-white p-4">
<div class="grow space-y-2 bg-white p-4">
<p class="text-lg font-bold text-gray-800">썸네일이 누락된 파일</p>
<div class="space-y-4">
<p class="break-keep text-gray-800">
@@ -1,4 +1,4 @@
import { trpc } from "$trpc/client";
import { trpc } from "#trpc/client.js";
import type { PageLoad } from "./$types";
export const load: PageLoad = async ({ parent }) => {
@@ -9,10 +9,10 @@
</script>
<script lang="ts">
import { ActionEntryButton } from "$lib/components/atoms";
import { DirectoryEntryLabel } from "$lib/components/molecules";
import type { FileInfo } from "$lib/modules/filesystem";
import { formatDateTime } from "$lib/utils";
import { ActionEntryButton } from "#lib/components/atoms/index.js";
import { DirectoryEntryLabel } from "#lib/components/molecules/index.js";
import type { FileInfo } from "#lib/modules/filesystem/index.js";
import { formatDateTime } from "#lib/utils/index.js";
import type { GenerationStatus } from "./service";
import IconCamera from "~icons/material-symbols/camera";
@@ -1,11 +1,11 @@
import { limitFunction } from "p-limit";
import { SvelteMap } from "svelte/reactivity";
import { storeFileThumbnailCache } from "$lib/modules/file";
import { getFileInfo, type FileInfo } from "$lib/modules/filesystem";
import { generateThumbnail } from "$lib/modules/thumbnail";
import { requestFileDownload, requestFileThumbnailUpload } from "$lib/services/file";
import { HybridPromise, Scheduler } from "$lib/utils";
import type { RouterOutputs } from "$trpc/router.server";
import { storeFileThumbnailCache } from "#lib/modules/file/index.js";
import { getFileInfo, type FileInfo } from "#lib/modules/filesystem/index.js";
import { generateThumbnail } from "#lib/modules/thumbnail.js";
import { requestFileDownload, requestFileThumbnailUpload } from "#lib/services/file.js";
import { HybridPromise, Scheduler } from "#lib/utils/index.js";
import type { RouterOutputs } from "#trpc/router.server.js";
export type GenerationStatus =
"queued" | "generation-pending" | "generating" | "uploading" | "uploaded" | "error";