mirror of
https://github.com/kmc7468/arkvault.git
synced 2026-02-04 08:06:56 +00:00
사소한 리팩토링 2
This commit is contained in:
44
src/lib/components/molecules/Categories.svelte
Normal file
44
src/lib/components/molecules/Categories.svelte
Normal 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}
|
||||||
@@ -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}
|
|
||||||
@@ -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>
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export { default } from "./Categories.svelte";
|
|
||||||
export * from "./service";
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import type { DataKey } from "$lib/modules/filesystem";
|
|
||||||
|
|
||||||
export interface SelectedCategory {
|
|
||||||
id: number;
|
|
||||||
dataKey?: DataKey;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
@@ -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";
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
Reference in New Issue
Block a user