mirror of
https://github.com/kmc7468/arkvault.git
synced 2026-11-04 08:10:28 +09:00
패키지 버전 업데이트 및 SvelteKit 3, Tailwind CSS 4로 마이그레이션
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
35f3e92b5a
commit
67989f4741
155 files changed
+1834
-2299
No files matched your search
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,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,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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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";
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { AdaptiveDiv } from "$lib/components/atoms";
|
||||
import { AdaptiveDiv } from "#lib/components/atoms/index.js";
|
||||
import BottomBar from "./BottomBar.svelte";
|
||||
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
<div class="flex h-screen flex-col justify-between">
|
||||
<AdaptiveDiv class="w-full flex-grow">
|
||||
<AdaptiveDiv class="w-full grow">
|
||||
{@render children()}
|
||||
</AdaptiveDiv>
|
||||
<BottomBar />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { goto } from "$app/navigation";
|
||||
import { page } from "$app/state";
|
||||
import { AdaptiveDiv } from "$lib/components/atoms";
|
||||
import { AdaptiveDiv } from "#lib/components/atoms/index.js";
|
||||
|
||||
import IconHome from "~icons/material-symbols/home";
|
||||
import IconFolder from "~icons/material-symbols/folder";
|
||||
@@ -18,11 +18,11 @@
|
||||
];
|
||||
</script>
|
||||
|
||||
<div class="sticky bottom-0 h-20 flex-shrink-0 rounded-t-2xl border-t border-gray-300 bg-white">
|
||||
<div class="sticky bottom-0 h-20 shrink-0 rounded-t-2xl border-t border-gray-300 bg-white">
|
||||
<AdaptiveDiv class="flex justify-evenly px-4 py-2">
|
||||
{#each pages as { path, label, icon: Icon }}
|
||||
<button
|
||||
onclick={() => goto(path, { replaceState: true })}
|
||||
onclick={() => goto(path, { replace: true })}
|
||||
class={[
|
||||
"w-16 active:rounded-xl active:bg-gray-100",
|
||||
!page.url.pathname.startsWith(path) && "text-gray-600",
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { goto } from "$app/navigation";
|
||||
import { CheckBox, RowVirtualizer } from "$lib/components/atoms";
|
||||
import { SubCategories, TopBar } from "$lib/components/molecules";
|
||||
import { CategoryCreateModal } from "$lib/components/organisms";
|
||||
import { updateCategoryInfo } from "$lib/indexedDB";
|
||||
import { getCategoryInfo, type MaybeCategoryInfo } from "$lib/modules/filesystem";
|
||||
import { masterKeyStore } from "$lib/stores";
|
||||
import { HybridPromise, sortEntries } from "$lib/utils";
|
||||
import { CheckBox, RowVirtualizer } from "#lib/components/atoms/index.js";
|
||||
import { SubCategories, TopBar } from "#lib/components/molecules/index.js";
|
||||
import { CategoryCreateModal } from "#lib/components/organisms/index.js";
|
||||
import { updateCategoryInfo } from "#lib/indexedDB/index.js";
|
||||
import { getCategoryInfo, type MaybeCategoryInfo } from "#lib/modules/filesystem/index.js";
|
||||
import { masterKeyStore } from "#lib/stores/index.js";
|
||||
import { HybridPromise, sortEntries } from "#lib/utils/index.js";
|
||||
import CategoryDeleteModal from "./CategoryDeleteModal.svelte";
|
||||
import CategoryMenuBottomSheet from "./CategoryMenuBottomSheet.svelte";
|
||||
import CategoryRenameModal from "./CategoryRenameModal.svelte";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { ActionModal } from "$lib/components/molecules";
|
||||
import { truncateString } from "$lib/utils";
|
||||
import { ActionModal } from "#lib/components/molecules/index.js";
|
||||
import { truncateString } from "#lib/utils/index.js";
|
||||
import { useContext } from "./service.svelte";
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { BottomSheet } from "$lib/components/atoms";
|
||||
import { CategoryLabel, IconEntryButton } from "$lib/components/molecules";
|
||||
import { BottomSheet } from "#lib/components/atoms/index.js";
|
||||
import { CategoryLabel, IconEntryButton } from "#lib/components/molecules/index.js";
|
||||
import { useContext } from "./service.svelte";
|
||||
|
||||
import IconEdit from "~icons/material-symbols/edit";
|
||||
@@ -19,7 +19,7 @@
|
||||
{#if context.selectedCategory}
|
||||
{@const { name } = context.selectedCategory}
|
||||
<BottomSheet bind:isOpen class="p-4">
|
||||
<CategoryLabel {name} class="h-12 p-2" textClass="!font-semibold" />
|
||||
<CategoryLabel {name} class="h-12 p-2" textClass="font-semibold!" />
|
||||
<div class="my-2 h-px w-full bg-gray-200"></div>
|
||||
<IconEntryButton icon={IconEdit} onclick={onRenameClick} class="h-12 w-full">
|
||||
이름 바꾸기
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { RenameModal } from "$lib/components/organisms";
|
||||
import { RenameModal } from "#lib/components/organisms/index.js";
|
||||
import { useContext } from "./service.svelte";
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -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 { CategoryFileInfo } 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 { CategoryFileInfo } from "#lib/modules/filesystem/index.js";
|
||||
import { formatDateTime } from "#lib/utils/index.js";
|
||||
import type { SelectedFile } from "./service.svelte";
|
||||
|
||||
import IconClose from "~icons/material-symbols/close";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { getContext, setContext } from "svelte";
|
||||
import { encryptString } from "$lib/modules/crypto";
|
||||
import type { SelectedCategory } from "$lib/components/molecules";
|
||||
import { trpc } from "$trpc/client";
|
||||
import { encryptString } from "#lib/modules/crypto/index.js";
|
||||
import type { SelectedCategory } from "#lib/components/molecules/index.js";
|
||||
import { trpc } from "#trpc/client.js";
|
||||
|
||||
export { requestCategoryCreation, requestFileRemovalFromCategory } from "$lib/services/category";
|
||||
export { requestCategoryCreation, requestFileRemovalFromCategory } from "#lib/services/category.js";
|
||||
|
||||
export interface SelectedFile {
|
||||
id: number;
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
import { onMount } from "svelte";
|
||||
import { goto } from "$app/navigation";
|
||||
import { page } from "$app/state";
|
||||
import { FloatingButton } from "$lib/components/atoms";
|
||||
import { TopBar } from "$lib/components/molecules";
|
||||
import { getDirectoryInfo, type MaybeDirectoryInfo } from "$lib/modules/filesystem";
|
||||
import { masterKeyStore, hmacSecretStore } from "$lib/stores";
|
||||
import { HybridPromise } from "$lib/utils";
|
||||
import { FloatingButton } from "#lib/components/atoms/index.js";
|
||||
import { TopBar } from "#lib/components/molecules/index.js";
|
||||
import { getDirectoryInfo, type MaybeDirectoryInfo } from "#lib/modules/filesystem/index.js";
|
||||
import { masterKeyStore, hmacSecretStore } from "#lib/stores/index.js";
|
||||
import { HybridPromise } from "#lib/utils/index.js";
|
||||
import DirectoryCreateModal from "./DirectoryCreateModal.svelte";
|
||||
import DirectoryEntries from "./DirectoryEntries";
|
||||
import DownloadStatusCard from "./DownloadStatusCard.svelte";
|
||||
@@ -109,16 +109,13 @@
|
||||
<input bind:this={fileInput} onchange={uploadFile} type="file" multiple class="hidden" />
|
||||
|
||||
<div class="flex h-full flex-col">
|
||||
<TopBar title={info?.name ?? "내 파일"} {showBackButton} class="flex-shrink-0">
|
||||
<button
|
||||
onclick={onSearchClick}
|
||||
class="w-[2.3rem] flex-shrink-0 rounded-full p-1 active:bg-black active:bg-opacity-[0.04]"
|
||||
>
|
||||
<TopBar title={info?.name ?? "내 파일"} {showBackButton} class="shrink-0">
|
||||
<button onclick={onSearchClick} class="w-[2.3rem] shrink-0 rounded-full p-1 active:bg-black/4">
|
||||
<IconSearch class="text-2xl" />
|
||||
</button>
|
||||
</TopBar>
|
||||
{#if info?.exists}
|
||||
<div class="flex flex-grow flex-col px-4 pb-4">
|
||||
<div class="flex grow flex-col px-4 pb-4">
|
||||
<div class="flex gap-x-2">
|
||||
<UploadStatusCard onclick={() => goto("/file/uploads")} />
|
||||
<DownloadStatusCard onclick={() => goto("/file/downloads")} />
|
||||
@@ -149,7 +146,7 @@
|
||||
onclick={() => {
|
||||
isEntryCreateBottomSheetOpen = true;
|
||||
}}
|
||||
class="bottom-24 right-4"
|
||||
class="right-4 bottom-24"
|
||||
/>
|
||||
<EntryCreateBottomSheet
|
||||
bind:isOpen={isEntryCreateBottomSheetOpen}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { TextInputModal } from "$lib/components/organisms";
|
||||
import { TextInputModal } from "#lib/components/organisms/index.js";
|
||||
|
||||
interface Props {
|
||||
isOpen: boolean;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { ActionEntryButton, RowVirtualizer } from "$lib/components/atoms";
|
||||
import { DirectoryEntryLabel } from "$lib/components/molecules";
|
||||
import { getUploadingFiles, type LiveFileUploadState } from "$lib/modules/file";
|
||||
import type { DirectoryInfo } from "$lib/modules/filesystem";
|
||||
import { sortEntries } from "$lib/utils";
|
||||
import { ActionEntryButton, RowVirtualizer } from "#lib/components/atoms/index.js";
|
||||
import { DirectoryEntryLabel } from "#lib/components/molecules/index.js";
|
||||
import { getUploadingFiles, type LiveFileUploadState } from "#lib/modules/file/index.js";
|
||||
import type { DirectoryInfo } from "#lib/modules/filesystem/index.js";
|
||||
import { sortEntries } from "#lib/utils/index.js";
|
||||
import File from "./File.svelte";
|
||||
import SubDirectory from "./SubDirectory.svelte";
|
||||
import UploadingFile from "./UploadingFile.svelte";
|
||||
@@ -54,7 +54,7 @@
|
||||
: entries[index]!.type!}
|
||||
estimateItemHeight={() => 56}
|
||||
itemGap={4}
|
||||
class="pb-[4.5rem]"
|
||||
class="pb-18"
|
||||
>
|
||||
{#snippet item(index)}
|
||||
{@const entry = entries[index]!}
|
||||
@@ -76,7 +76,7 @@
|
||||
{/snippet}
|
||||
</RowVirtualizer>
|
||||
{:else}
|
||||
<div class="flex flex-grow items-center justify-center">
|
||||
<div class="flex grow items-center justify-center">
|
||||
<p class="text-gray-500">폴더가 비어 있어요.</p>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -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";
|
||||
import type { SelectedEntry } from "../service.svelte";
|
||||
|
||||
import IconMoreVert from "~icons/material-symbols/more-vert";
|
||||
|
||||
@@ -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";
|
||||
import type { SelectedEntry } from "../service.svelte";
|
||||
|
||||
import IconMoreVert from "~icons/material-symbols/more-vert";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { LiveFileUploadState } from "$lib/modules/file";
|
||||
import { formatNetworkSpeed } from "$lib/utils";
|
||||
import type { LiveFileUploadState } from "#lib/modules/file/index.js";
|
||||
import { formatNetworkSpeed } from "#lib/utils/index.js";
|
||||
|
||||
import IconDraft from "~icons/material-symbols/draft";
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
</script>
|
||||
|
||||
<div class="flex h-14 gap-x-4 p-2">
|
||||
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center text-xl">
|
||||
<div class="flex size-10 shrink-0 items-center justify-center text-xl">
|
||||
<IconDraft class="text-gray-600" />
|
||||
</div>
|
||||
<div class="flex flex-grow flex-col overflow-hidden text-gray-800">
|
||||
<div class="flex grow flex-col overflow-hidden text-gray-800">
|
||||
<p title={state.name} class="truncate font-medium">
|
||||
{state.name}
|
||||
</p>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { getDownloadingFiles } from "$lib/modules/file";
|
||||
import { getDownloadingFiles } from "#lib/modules/file/index.js";
|
||||
|
||||
interface Props {
|
||||
onclick: () => void;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { ActionModal } from "$lib/components/molecules";
|
||||
import { truncateString } from "$lib/utils";
|
||||
import { ActionModal } from "#lib/components/molecules/index.js";
|
||||
import { truncateString } from "#lib/utils/index.js";
|
||||
|
||||
interface Props {
|
||||
file: File | undefined;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { BottomSheet } from "$lib/components/atoms";
|
||||
import { IconEntryButton } from "$lib/components/molecules";
|
||||
import { BottomSheet } from "#lib/components/atoms/index.js";
|
||||
import { IconEntryButton } from "#lib/components/molecules/index.js";
|
||||
|
||||
import IconCreateNewFolder from "~icons/material-symbols/create-new-folder";
|
||||
import IconUploadFile from "~icons/material-symbols/upload-file";
|
||||
@@ -19,7 +19,7 @@
|
||||
icon={IconCreateNewFolder}
|
||||
onclick={onDirectoryCreateClick}
|
||||
class="h-16 w-full"
|
||||
iconClass="!text-2xl text-yellow-500"
|
||||
iconClass="text-2xl! text-yellow-500"
|
||||
>
|
||||
폴더 만들기
|
||||
</IconEntryButton>
|
||||
@@ -27,7 +27,7 @@
|
||||
icon={IconUploadFile}
|
||||
onclick={onFileUploadClick}
|
||||
class="h-16 w-full"
|
||||
iconClass="!text-2xl text-blue-400"
|
||||
iconClass="text-2xl! text-blue-400"
|
||||
>
|
||||
파일 업로드
|
||||
</IconEntryButton>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { ActionModal } from "$lib/components/molecules";
|
||||
import { truncateString } from "$lib/utils";
|
||||
import { ActionModal } from "#lib/components/molecules/index.js";
|
||||
import { truncateString } from "#lib/utils/index.js";
|
||||
import { useContext } from "./service.svelte";
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { BottomSheet } from "$lib/components/atoms";
|
||||
import { DirectoryEntryLabel, IconEntryButton } from "$lib/components/molecules";
|
||||
import { BottomSheet } from "#lib/components/atoms/index.js";
|
||||
import { DirectoryEntryLabel, IconEntryButton } from "#lib/components/molecules/index.js";
|
||||
import { useContext } from "./service.svelte";
|
||||
|
||||
import IconFavorite from "~icons/material-symbols/favorite";
|
||||
@@ -22,7 +22,7 @@
|
||||
{#if context.selectedEntry}
|
||||
{@const { name, type, isFavorite } = context.selectedEntry}
|
||||
<BottomSheet bind:isOpen class="p-4">
|
||||
<DirectoryEntryLabel {type} {name} class="h-12 p-2" textClass="!font-semibold" />
|
||||
<DirectoryEntryLabel {type} {name} class="h-12 p-2" textClass="font-semibold!" />
|
||||
<div class="my-2 h-px w-full bg-gray-200"></div>
|
||||
<IconEntryButton
|
||||
icon={isFavorite ? IconFavorite : IconFavoriteBorder}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { RenameModal } from "$lib/components/organisms";
|
||||
import { RenameModal } from "#lib/components/organisms/index.js";
|
||||
import { useContext } from "./service.svelte";
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { getUploadingFiles } from "$lib/modules/file";
|
||||
import { getUploadingFiles } from "#lib/modules/file/index.js";
|
||||
|
||||
interface Props {
|
||||
onclick: () => void;
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
import { getContext, setContext } from "svelte";
|
||||
import { storeHmacSecrets } from "$lib/indexedDB";
|
||||
import { generateDataKey, wrapDataKey, unwrapHmacSecret, encryptString } from "$lib/modules/crypto";
|
||||
import { storeHmacSecrets } from "#lib/indexedDB/index.js";
|
||||
import {
|
||||
generateDataKey,
|
||||
wrapDataKey,
|
||||
unwrapHmacSecret,
|
||||
encryptString,
|
||||
} from "#lib/modules/crypto/index.js";
|
||||
import {
|
||||
storeFileCache,
|
||||
deleteFileCache,
|
||||
storeFileThumbnailCache,
|
||||
deleteFileThumbnailCache,
|
||||
uploadFile,
|
||||
} from "$lib/modules/file";
|
||||
import type { DataKey } from "$lib/modules/filesystem";
|
||||
import { hmacSecretStore, type MasterKey, type HmacSecret } from "$lib/stores";
|
||||
import { trpc } from "$trpc/client";
|
||||
} from "#lib/modules/file/index.js";
|
||||
import type { DataKey } from "#lib/modules/filesystem/index.js";
|
||||
import { hmacSecretStore, type MasterKey, type HmacSecret } from "#lib/stores/index.js";
|
||||
import { trpc } from "#trpc/client.js";
|
||||
|
||||
export interface SelectedEntry {
|
||||
type: "directory" | "file";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { goto } from "$app/navigation";
|
||||
import { RowVirtualizer } from "$lib/components/atoms";
|
||||
import { TopBar } from "$lib/components/molecules";
|
||||
import { masterKeyStore } from "$lib/stores";
|
||||
import { RowVirtualizer } from "#lib/components/atoms/index.js";
|
||||
import { TopBar } from "#lib/components/molecules/index.js";
|
||||
import { masterKeyStore } from "#lib/stores/index.js";
|
||||
import Directory from "./Directory.svelte";
|
||||
import File from "./File.svelte";
|
||||
import { requestFavoriteEntries, requestRemoveFavorite, type FavoriteEntry } from "./service";
|
||||
@@ -48,12 +48,12 @@
|
||||
<TopBar title="즐겨찾기" showBackButton={false}>
|
||||
<button
|
||||
onclick={() => goto("/search?from=favorites")}
|
||||
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"
|
||||
>
|
||||
<IconSearch />
|
||||
</button>
|
||||
</TopBar>
|
||||
<div class="flex flex-grow flex-col px-4 pb-4">
|
||||
<div class="flex grow flex-col px-4 pb-4">
|
||||
{#if entries.length > 0}
|
||||
<RowVirtualizer
|
||||
count={entries.length}
|
||||
@@ -79,7 +79,7 @@
|
||||
{/snippet}
|
||||
</RowVirtualizer>
|
||||
{:else}
|
||||
<div class="flex flex-grow items-center justify-center">
|
||||
<div class="flex grow items-center justify-center">
|
||||
<p class="text-gray-500">
|
||||
{#if isLoading}
|
||||
즐겨찾기 목록을 불러오고 있어요.
|
||||
|
||||
@@ -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,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";
|
||||
|
||||
import IconClose from "~icons/material-symbols/close";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
import IconClose from "~icons/material-symbols/close";
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ import {
|
||||
type SummarizedFileInfo,
|
||||
type SubDirectoryInfo,
|
||||
type LocalDirectoryInfo,
|
||||
} from "$lib/modules/filesystem";
|
||||
import { HybridPromise, sortEntries } from "$lib/utils";
|
||||
import { trpc } from "$trpc/client";
|
||||
import type { RouterOutputs } from "$trpc/router.server";
|
||||
} from "#lib/modules/filesystem/index.js";
|
||||
import { HybridPromise, sortEntries } from "#lib/utils/index.js";
|
||||
import { trpc } from "#trpc/client.js";
|
||||
import type { RouterOutputs } from "#trpc/router.server.js";
|
||||
|
||||
export type FavoriteEntry =
|
||||
| { type: "directory"; name: string; details: SubDirectoryInfo }
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { goto } from "$app/navigation";
|
||||
import { EntryButton, FileThumbnailButton } from "$lib/components/atoms";
|
||||
import { type SummarizedFileInfo } from "$lib/modules/filesystem";
|
||||
import { EntryButton, FileThumbnailButton } from "#lib/components/atoms/index.js";
|
||||
import { type SummarizedFileInfo } from "#lib/modules/filesystem/index.js";
|
||||
import { requestFreshMediaFilesRetrieval } from "./service";
|
||||
|
||||
let mediaFiles: SummarizedFileInfo[] = $state([]);
|
||||
@@ -16,7 +16,7 @@
|
||||
<title>홈</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="min-h-full space-y-4 bg-gray-100 px-4 pb-[5.5em] pt-4">
|
||||
<div class="min-h-full space-y-4 bg-gray-100 px-4 pt-4 pb-[5.5em]">
|
||||
<p class="px-2 text-2xl font-bold text-gray-800">ArkVault</p>
|
||||
<div class="rounded-xl bg-white p-2">
|
||||
<EntryButton onclick={() => goto("/gallery")} class="w-full">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getAllFileInfos } from "$lib/indexedDB";
|
||||
import { getAllFileInfos } from "#lib/indexedDB/index.js";
|
||||
|
||||
export const requestFreshMediaFilesRetrieval = async (limit = 8) => {
|
||||
const files = await getAllFileInfos();
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { Component, Snippet } from "svelte";
|
||||
import type { ClassValue, SvelteHTMLElements } from "svelte/elements";
|
||||
import { IconEntryButton } from "$lib/components/molecules";
|
||||
import { IconEntryButton } from "#lib/components/molecules/index.js";
|
||||
|
||||
interface Props {
|
||||
children: Snippet;
|
||||
@@ -17,7 +17,7 @@
|
||||
{icon}
|
||||
{onclick}
|
||||
class="w-full"
|
||||
iconClass={["rounded-lg bg-gray-200 p-1 !text-base", iconColor]}
|
||||
iconClass={["rounded-lg bg-gray-200 p-1 text-base!", iconColor]}
|
||||
>
|
||||
{@render children()}
|
||||
</IconEntryButton>
|
||||
@@ -1 +1 @@
|
||||
export { requestLogout } from "$lib/services/auth";
|
||||
export { requestLogout } from "#lib/services/auth.js";
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { getDownloadingFiles, getUploadingFiles } from "$lib/modules/file";
|
||||
import { getDownloadingFiles, getUploadingFiles } from "#lib/modules/file/index.js";
|
||||
import "../app.css";
|
||||
|
||||
let { children } = $props();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { redirect } from "@sveltejs/kit";
|
||||
import { get } from "svelte/store";
|
||||
import { clientKeyStore, masterKeyStore } from "$lib/stores";
|
||||
import { clientKeyStore, masterKeyStore } from "#lib/stores/index.js";
|
||||
import type { LayoutLoad } from "./$types";
|
||||
|
||||
export const ssr = false;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { error } from "@sveltejs/kit";
|
||||
import { z } from "zod";
|
||||
import { parseRangeHeader, getContentRangeHeader } from "$lib/modules/http";
|
||||
import { authorize } from "$lib/server/modules/auth";
|
||||
import { getFileStream, getFileThumbnailStream } from "$lib/server/services/file";
|
||||
import { parseRangeHeader, getContentRangeHeader } from "#lib/modules/http.js";
|
||||
import { authorize } from "#lib/server/modules/auth.js";
|
||||
import { getFileStream, getFileThumbnailStream } from "#lib/server/services/file.js";
|
||||
import type { RequestHandler, RouteParams } from "./$types";
|
||||
|
||||
const downloadHandler = async (locals: App.Locals, params: RouteParams, request: Request) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
|
||||
import { createContext } from "$trpc/init.server";
|
||||
import { appRouter } from "$trpc/router.server";
|
||||
import { createContext } from "#trpc/init.server.js";
|
||||
import { appRouter } from "#trpc/router.server.js";
|
||||
import type { RequestHandler } from "./$types";
|
||||
|
||||
const trpcHandler: RequestHandler = (event) =>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { error, text } from "@sveltejs/kit";
|
||||
import { error } from "@sveltejs/kit";
|
||||
import { Readable } from "stream";
|
||||
import type { ReadableStream } from "stream/web";
|
||||
import { z } from "zod";
|
||||
import { authorize } from "$lib/server/modules/auth";
|
||||
import { uploadChunk } from "$lib/server/services/upload";
|
||||
import { authorize } from "#lib/server/modules/auth.js";
|
||||
import { uploadChunk } from "#lib/server/services/upload.js";
|
||||
import type { RequestHandler } from "./$types";
|
||||
|
||||
export const POST: RequestHandler = async ({ locals, params, request }) => {
|
||||
@@ -28,5 +28,5 @@ export const POST: RequestHandler = async ({ locals, params, request }) => {
|
||||
chunkIndex,
|
||||
Readable.fromWeb(request.body as ReadableStream),
|
||||
);
|
||||
return text("Chunk uploaded", { headers: { "Content-Type": "text/plain" } });
|
||||
return new Response("Chunk uploaded", { headers: { "Content-Type": "text/plain" } });
|
||||
};
|
||||
Reference in new issue
Block a user