사소한 리팩토링 2

This commit is contained in:
static
2026-01-02 14:55:26 +09:00
parent d1f9018213
commit 280d46b48d
11 changed files with 75 additions and 112 deletions

View File

@@ -0,0 +1,44 @@
<script module lang="ts">
import type { DataKey } from "$lib/modules/filesystem";
export interface SelectedCategory {
id: number;
dataKey?: DataKey;
name: string;
}
</script>
<script lang="ts">
import type { Component } from "svelte";
import type { SvelteHTMLElements } from "svelte/elements";
import { ActionEntryButton } from "$lib/components/atoms";
import { CategoryLabel } from "$lib/components/molecules";
import type { SubCategoryInfo } from "$lib/modules/filesystem";
import { sortEntries } from "$lib/utils";
interface Props {
categories: SubCategoryInfo[];
categoryMenuIcon?: Component<SvelteHTMLElements["svg"]>;
onCategoryClick: (category: SelectedCategory) => void;
onCategoryMenuClick?: (category: SelectedCategory) => void;
}
let { categories, categoryMenuIcon, onCategoryClick, onCategoryMenuClick }: Props = $props();
let categoriesWithName = $derived(sortEntries($state.snapshot(categories)));
</script>
{#if categoriesWithName.length > 0}
<div class="space-y-1">
{#each categoriesWithName as category (category.id)}
<ActionEntryButton
class="h-12"
onclick={() => onCategoryClick(category)}
actionButtonIcon={categoryMenuIcon}
onActionButtonClick={() => onCategoryMenuClick?.(category)}
>
<CategoryLabel name={category.name} />
</ActionEntryButton>
{/each}
</div>
{/if}

View File

@@ -1,33 +0,0 @@
<script lang="ts">
import type { Component } from "svelte";
import type { SvelteHTMLElements } from "svelte/elements";
import type { SubCategoryInfo } from "$lib/modules/filesystem";
import { SortBy, sortEntries } from "$lib/utils";
import Category from "./Category.svelte";
import type { SelectedCategory } from "./service";
interface Props {
categories: SubCategoryInfo[];
categoryMenuIcon?: Component<SvelteHTMLElements["svg"]>;
onCategoryClick: (category: SelectedCategory) => void;
onCategoryMenuClick?: (category: SelectedCategory) => void;
sortBy?: SortBy;
}
let { categories, categoryMenuIcon, onCategoryClick, onCategoryMenuClick }: Props = $props();
let categoriesWithName = $derived(sortEntries(structuredClone($state.snapshot(categories))));
</script>
{#if categoriesWithName.length > 0}
<div class="space-y-1">
{#each categoriesWithName as category}
<Category
info={category}
menuIcon={categoryMenuIcon}
onclick={onCategoryClick}
onMenuClick={onCategoryMenuClick}
/>
{/each}
</div>
{/if}

View File

@@ -1,26 +0,0 @@
<script lang="ts">
import type { Component } from "svelte";
import type { SvelteHTMLElements } from "svelte/elements";
import { ActionEntryButton } from "$lib/components/atoms";
import { CategoryLabel } from "$lib/components/molecules";
import type { SubCategoryInfo } from "$lib/modules/filesystem";
import type { SelectedCategory } from "./service";
interface Props {
info: SubCategoryInfo;
menuIcon?: Component<SvelteHTMLElements["svg"]>;
onclick: (category: SelectedCategory) => void;
onMenuClick?: (category: SelectedCategory) => void;
}
let { info, menuIcon, onclick, onMenuClick }: Props = $props();
</script>
<ActionEntryButton
class="h-12"
onclick={() => onclick(info)}
actionButtonIcon={menuIcon}
onActionButtonClick={() => onMenuClick?.(info)}
>
<CategoryLabel name={info.name} />
</ActionEntryButton>

View File

@@ -1,2 +0,0 @@
export { default } from "./Categories.svelte";
export * from "./service";

View File

@@ -1,7 +0,0 @@
import type { DataKey } from "$lib/modules/filesystem";
export interface SelectedCategory {
id: number;
dataKey?: DataKey;
name: string;
}

View File

@@ -1,7 +1,7 @@
export * from "./ActionModal.svelte"; export * from "./ActionModal.svelte";
export { default as ActionModal } from "./ActionModal.svelte"; export { default as ActionModal } from "./ActionModal.svelte";
export * from "./Categories"; export * from "./Categories.svelte";
export { default as Categories } from "./Categories"; export { default as Categories } from "./Categories.svelte";
export { default as IconEntryButton } from "./IconEntryButton.svelte"; export { default as IconEntryButton } from "./IconEntryButton.svelte";
export * from "./labels"; export * from "./labels";
export { default as SubCategories } from "./SubCategories.svelte"; export { default as SubCategories } from "./SubCategories.svelte";

View File

@@ -62,7 +62,7 @@
<p class="pb-2 text-sm font-medium">{row.label}</p> <p class="pb-2 text-sm font-medium">{row.label}</p>
{:else} {:else}
<div class={["grid grid-cols-4 gap-x-1", row.isLast ? "pb-4" : "pb-1"]}> <div class={["grid grid-cols-4 gap-x-1", row.isLast ? "pb-4" : "pb-1"]}>
{#each row.files as file} {#each row.files as file (file.id)}
<FileThumbnailButton info={file} onclick={onFileClick} /> <FileThumbnailButton info={file} onclick={onFileClick} />
{/each} {/each}
</div> </div>

View File

@@ -15,7 +15,9 @@
} }
let fileCache: FileCache[] | undefined = $state(); let fileCache: FileCache[] | undefined = $state();
let fileCacheTotalSize = $state(0); let fileCacheTotalSize = $derived(
fileCache?.reduce((acc, { index }) => acc + index.size, 0) ?? 0,
);
const deleteFileCache = async (fileId: number) => { const deleteFileCache = async (fileId: number) => {
await doDeleteFileCache(fileId); await doDeleteFileCache(fileId);
@@ -29,18 +31,9 @@
$masterKeyStore?.get(1)?.key!, $masterKeyStore?.get(1)?.key!,
); );
fileCache = indexes fileCache = indexes
.map((index, i) => ({ .map((index) => ({ index, info: infos.get(index.fileId)! }))
index,
info: infos.get(index.fileId)!,
}))
.sort((a, b) => a.index.lastRetrievedAt.getTime() - b.index.lastRetrievedAt.getTime()); .sort((a, b) => a.index.lastRetrievedAt.getTime() - b.index.lastRetrievedAt.getTime());
}); });
$effect(() => {
if (fileCache) {
fileCacheTotalSize = fileCache.reduce((acc, { index }) => acc + index.size, 0);
}
});
</script> </script>
<svelte:head> <svelte:head>
@@ -59,7 +52,7 @@
<p>캐시를 삭제하더라도 원본 파일은 삭제되지 않아요.</p> <p>캐시를 삭제하더라도 원본 파일은 삭제되지 않아요.</p>
</div> </div>
<div class="space-y-2"> <div class="space-y-2">
{#each fileCache as { index, info }} {#each fileCache as { index, info } (info.id)}
<File {index} {info} onDeleteClick={deleteFileCache} /> <File {index} {info} onDeleteClick={deleteFileCache} />
{/each} {/each}
</div> </div>

View File

@@ -7,11 +7,7 @@
import { bulkGetFileInfo } from "$lib/modules/filesystem"; import { bulkGetFileInfo } from "$lib/modules/filesystem";
import { masterKeyStore } from "$lib/stores"; import { masterKeyStore } from "$lib/stores";
import File from "./File.svelte"; import File from "./File.svelte";
import { import { persistentStates, requestThumbnailGeneration } from "./service.svelte";
persistentStates,
getGenerationStatus,
requestThumbnailGeneration,
} from "./service.svelte";
import IconDelete from "~icons/material-symbols/delete"; import IconDelete from "~icons/material-symbols/delete";
@@ -55,7 +51,7 @@
{persistentStates.files.length}개 파일의 썸네일이 존재하지 않아요. {persistentStates.files.length}개 파일의 썸네일이 존재하지 않아요.
</p> </p>
<div class="space-y-2"> <div class="space-y-2">
{#each persistentStates.files as { info, status }} {#each persistentStates.files as { info, status } (info.id)}
{#if info.exists} {#if info.exists}
<File <File
{info} {info}

View File

@@ -46,28 +46,26 @@
</script> </script>
{#if entries.length > 0} {#if entries.length > 0}
<div class="pb-[4.5rem]"> <RowVirtualizer count={entries.length} itemHeight={() => 56} itemGap={4} class="pb-[4.5rem]">
<RowVirtualizer count={entries.length} itemHeight={() => 56} itemGap={4}> {#snippet item(index)}
{#snippet item(index)} {@const entry = entries[index]!}
{@const entry = entries[index]!} {#if entry.type === "parent"}
{#if entry.type === "parent"} <ActionEntryButton class="h-14" onclick={onParentClick}>
<ActionEntryButton class="h-14" onclick={onParentClick}> <DirectoryEntryLabel type="parent-directory" name=".." />
<DirectoryEntryLabel type="parent-directory" name=".." /> </ActionEntryButton>
</ActionEntryButton> {:else if entry.type === "directory"}
{:else if entry.type === "directory"} <SubDirectory
<SubDirectory info={entry.details}
info={entry.details} onclick={onEntryClick}
onclick={onEntryClick} onOpenMenuClick={onEntryMenuClick}
onOpenMenuClick={onEntryMenuClick} />
/> {:else if entry.type === "file"}
{:else if entry.type === "file"} <File info={entry.details} onclick={onEntryClick} onOpenMenuClick={onEntryMenuClick} />
<File info={entry.details} onclick={onEntryClick} onOpenMenuClick={onEntryMenuClick} /> {:else}
{:else} <UploadingFile state={entry.details} />
<UploadingFile state={entry.details} /> {/if}
{/if} {/snippet}
{/snippet} </RowVirtualizer>
</RowVirtualizer>
</div>
{:else} {:else}
<div class="flex flex-grow items-center justify-center"> <div class="flex flex-grow items-center justify-center">
<p class="text-gray-500">폴더가 비어 있어요.</p> <p class="text-gray-500">폴더가 비어 있어요.</p>

View File

@@ -33,7 +33,7 @@
</EntryButton> </EntryButton>
{#if mediaFiles.length > 0} {#if mediaFiles.length > 0}
<div class="grid grid-cols-4 gap-2 p-2"> <div class="grid grid-cols-4 gap-2 p-2">
{#each mediaFiles as file} {#each mediaFiles as file (file.id)}
{#if file.exists} {#if file.exists}
<FileThumbnailButton info={file} onclick={({ id }) => goto(`/file/${id}`)} /> <FileThumbnailButton info={file} onclick={({ id }) => goto(`/file/${id}`)} />
{/if} {/if}