mirror of
https://github.com/kmc7468/arkvault.git
synced 2026-02-05 00:26:54 +00:00
불필요하게 분리된 컴포넌트 삭제
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
<script lang="ts">
|
||||
import { goto } from "$app/navigation";
|
||||
import { TopBar } from "$lib/components/molecules";
|
||||
import { Category, CategoryCreateModal } from "$lib/components/organisms";
|
||||
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 } from "$lib/utils";
|
||||
import { HybridPromise, sortEntries } from "$lib/utils";
|
||||
import CategoryDeleteModal from "./CategoryDeleteModal.svelte";
|
||||
import CategoryMenuBottomSheet from "./CategoryMenuBottomSheet.svelte";
|
||||
import CategoryRenameModal from "./CategoryRenameModal.svelte";
|
||||
import File from "./File.svelte";
|
||||
import {
|
||||
createContext,
|
||||
requestCategoryCreation,
|
||||
@@ -16,6 +19,8 @@
|
||||
requestCategoryDeletion,
|
||||
} from "./service.svelte";
|
||||
|
||||
import IconMoreVert from "~icons/material-symbols/more-vert";
|
||||
|
||||
let { data } = $props();
|
||||
let context = createContext();
|
||||
|
||||
@@ -26,6 +31,30 @@
|
||||
let isCategoryRenameModalOpen = $state(false);
|
||||
let isCategoryDeleteModalOpen = $state(false);
|
||||
|
||||
let lastCategoryId: CategoryId | undefined = $state();
|
||||
let lastIsFileRecursive: boolean | undefined = $state();
|
||||
|
||||
let files = $derived(
|
||||
sortEntries(
|
||||
info?.files
|
||||
?.map((file) => ({ name: file.name, details: file }))
|
||||
.filter(({ details }) => info?.isFileRecursive || !details.isRecursive) ?? [],
|
||||
),
|
||||
);
|
||||
|
||||
$effect(() => {
|
||||
if (!info || info.id === "root" || info.isFileRecursive === undefined) return;
|
||||
if (lastCategoryId !== info.id) {
|
||||
lastCategoryId = info.id;
|
||||
lastIsFileRecursive = info.isFileRecursive;
|
||||
return;
|
||||
}
|
||||
if (lastIsFileRecursive === info.isFileRecursive) return;
|
||||
|
||||
lastIsFileRecursive = info.isFileRecursive;
|
||||
void updateCategoryInfo(info.id, { isFileRecursive: info.isFileRecursive });
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
HybridPromise.resolve(getCategoryInfo(data.id, $masterKeyStore?.get(1)?.key!)).then(
|
||||
(result) => {
|
||||
@@ -41,28 +70,58 @@
|
||||
<title>카테고리</title>
|
||||
</svelte:head>
|
||||
|
||||
{#if info?.exists}
|
||||
{#if info.id !== "root"}
|
||||
<TopBar title={info.name} />
|
||||
{/if}
|
||||
<div class="min-h-full bg-gray-100 pb-[5.5em]">
|
||||
<Category
|
||||
bind:isFileRecursive={info.isFileRecursive}
|
||||
{info}
|
||||
onFileClick={({ id }) => goto(`/file/${id}?from=category`)}
|
||||
onFileRemoveClick={async ({ id }) => {
|
||||
await requestFileRemovalFromCategory(id, data.id as number);
|
||||
void getCategoryInfo(data.id, $masterKeyStore?.get(1)?.key!); // TODO: FIXME
|
||||
}}
|
||||
onSubCategoryClick={({ id }) => goto(`/category/${id}`)}
|
||||
onSubCategoryCreateClick={() => (isCategoryCreateModalOpen = true)}
|
||||
onSubCategoryMenuClick={(subCategory) => {
|
||||
context.selectedCategory = subCategory;
|
||||
isCategoryMenuBottomSheetOpen = true;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{#if info?.id !== "root"}
|
||||
<TopBar title={info?.name} />
|
||||
{/if}
|
||||
<div class="min-h-full bg-gray-100 pb-[5.5em]">
|
||||
{#if info?.exists}
|
||||
<div class="space-y-4">
|
||||
<div class="space-y-4 bg-white p-4">
|
||||
{#if info.id !== "root"}
|
||||
<p class="text-lg font-bold text-gray-800">하위 카테고리</p>
|
||||
{/if}
|
||||
<SubCategories
|
||||
{info}
|
||||
onSubCategoryClick={({ id }) => goto(`/category/${id}`)}
|
||||
onSubCategoryCreateClick={() => (isCategoryCreateModalOpen = true)}
|
||||
onSubCategoryMenuClick={(subCategory) => {
|
||||
context.selectedCategory = subCategory;
|
||||
isCategoryMenuBottomSheetOpen = true;
|
||||
}}
|
||||
subCategoryMenuIcon={IconMoreVert}
|
||||
/>
|
||||
</div>
|
||||
{#if info.id !== "root"}
|
||||
<div class="space-y-4 bg-white p-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<p class="text-lg font-bold text-gray-800">파일</p>
|
||||
<CheckBox bind:checked={info.isFileRecursive}>
|
||||
<p class="font-medium">하위 카테고리의 파일</p>
|
||||
</CheckBox>
|
||||
</div>
|
||||
<RowVirtualizer count={files.length} itemHeight={() => 48} itemGap={4}>
|
||||
{#snippet item(index)}
|
||||
{@const { details } = files[index]!}
|
||||
<File
|
||||
info={details}
|
||||
onclick={({ id }) => goto(`/file/${id}?from=category`)}
|
||||
onRemoveClick={!details.isRecursive
|
||||
? async ({ id }) => {
|
||||
await requestFileRemovalFromCategory(id, data.id as number);
|
||||
void getCategoryInfo(data.id, $masterKeyStore?.get(1)?.key!); // TODO: FIXME
|
||||
}
|
||||
: undefined}
|
||||
/>
|
||||
{/snippet}
|
||||
{#snippet placeholder()}
|
||||
<p class="text-center text-gray-500">이 카테고리에 추가된 파일이 없어요.</p>
|
||||
{/snippet}
|
||||
</RowVirtualizer>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<CategoryCreateModal
|
||||
bind:isOpen={isCategoryCreateModalOpen}
|
||||
|
||||
28
src/routes/(main)/category/[[id]]/File.svelte
Normal file
28
src/routes/(main)/category/[[id]]/File.svelte
Normal file
@@ -0,0 +1,28 @@
|
||||
<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 type { SelectedFile } from "./service.svelte";
|
||||
|
||||
import IconClose from "~icons/material-symbols/close";
|
||||
|
||||
interface Props {
|
||||
info: CategoryFileInfo;
|
||||
onclick: (file: SelectedFile) => void;
|
||||
onRemoveClick?: (file: SelectedFile) => void;
|
||||
}
|
||||
|
||||
let { info, onclick, onRemoveClick }: Props = $props();
|
||||
|
||||
let thumbnail = $derived(getFileThumbnail(info));
|
||||
</script>
|
||||
|
||||
<ActionEntryButton
|
||||
class="h-12"
|
||||
onclick={() => onclick(info)}
|
||||
actionButtonIcon={onRemoveClick && IconClose}
|
||||
onActionButtonClick={() => onRemoveClick?.(info)}
|
||||
>
|
||||
<DirectoryEntryLabel type="file" thumbnail={$thumbnail} name={info.name} />
|
||||
</ActionEntryButton>
|
||||
@@ -5,6 +5,11 @@ import { trpc } from "$trpc/client";
|
||||
|
||||
export { requestCategoryCreation, requestFileRemovalFromCategory } from "$lib/services/category";
|
||||
|
||||
export interface SelectedFile {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export const createContext = () => {
|
||||
const context = $state({
|
||||
selectedCategory: undefined as SelectedCategory | undefined,
|
||||
|
||||
Reference in New Issue
Block a user