mirror of
https://github.com/kmc7468/arkvault.git
synced 2025-12-16 15:08:46 +00:00
카테고리 페이지 구현 (WiP)
아직은 하위 카테고리의 목록만 볼 수 있습니다.
This commit is contained in:
@@ -7,16 +7,20 @@
|
||||
children?: Snippet;
|
||||
onback?: () => void;
|
||||
title?: string;
|
||||
xPadding?: boolean;
|
||||
}
|
||||
|
||||
let { children, onback, title }: Props = $props();
|
||||
let { children, onback, title, xPadding = false }: Props = $props();
|
||||
|
||||
const back = $derived(() => {
|
||||
setTimeout(onback || (() => history.back()), 100);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="sticky top-0 z-10 flex flex-shrink-0 items-center justify-between bg-white py-4">
|
||||
<div
|
||||
class="sticky top-0 z-10 flex flex-shrink-0 items-center justify-between bg-white py-4
|
||||
{xPadding ? 'px-4' : ''}"
|
||||
>
|
||||
<button onclick={back} class="w-[2.3rem] flex-shrink-0 rounded-full p-1 active:bg-gray-100">
|
||||
<IconArrowBack class="text-2xl" />
|
||||
</button>
|
||||
|
||||
@@ -12,7 +12,11 @@ import {
|
||||
type DirectoryId,
|
||||
} from "$lib/indexedDB";
|
||||
import { unwrapDataKey, decryptString } from "$lib/modules/crypto";
|
||||
import type { DirectoryInfoResponse, FileInfoResponse } from "$lib/server/schemas";
|
||||
import type {
|
||||
CategoryInfoResponse,
|
||||
DirectoryInfoResponse,
|
||||
FileInfoResponse,
|
||||
} from "$lib/server/schemas";
|
||||
|
||||
export type DirectoryInfo =
|
||||
| {
|
||||
@@ -43,8 +47,27 @@ export interface FileInfo {
|
||||
lastModifiedAt: Date;
|
||||
}
|
||||
|
||||
type CategoryId = "root" | number;
|
||||
|
||||
export type CategoryInfo =
|
||||
| {
|
||||
id: "root";
|
||||
dataKey?: undefined;
|
||||
dataKeyVersion?: undefined;
|
||||
name?: undefined;
|
||||
subCategoryIds: number[];
|
||||
}
|
||||
| {
|
||||
id: number;
|
||||
dataKey?: CryptoKey;
|
||||
dataKeyVersion?: Date;
|
||||
name: string;
|
||||
subCategoryIds: number[];
|
||||
};
|
||||
|
||||
const directoryInfoStore = new Map<DirectoryId, Writable<DirectoryInfo | null>>();
|
||||
const fileInfoStore = new Map<number, Writable<FileInfo | null>>();
|
||||
const categoryInfoStore = new Map<CategoryId, Writable<CategoryInfo | null>>();
|
||||
|
||||
const fetchDirectoryInfoFromIndexedDB = async (
|
||||
id: DirectoryId,
|
||||
@@ -124,7 +147,7 @@ export const getDirectoryInfo = (id: DirectoryId, masterKey: CryptoKey) => {
|
||||
directoryInfoStore.set(id, info);
|
||||
}
|
||||
|
||||
fetchDirectoryInfo(id, info, masterKey);
|
||||
fetchDirectoryInfo(id, info, masterKey); // Intended
|
||||
return info;
|
||||
};
|
||||
|
||||
@@ -203,6 +226,58 @@ export const getFileInfo = (fileId: number, masterKey: CryptoKey) => {
|
||||
fileInfoStore.set(fileId, info);
|
||||
}
|
||||
|
||||
fetchFileInfo(fileId, info, masterKey);
|
||||
fetchFileInfo(fileId, info, masterKey); // Intended
|
||||
return info;
|
||||
};
|
||||
|
||||
const fetchCategoryInfoFromServer = async (
|
||||
id: CategoryId,
|
||||
info: Writable<CategoryInfo | null>,
|
||||
masterKey: CryptoKey,
|
||||
) => {
|
||||
const res = await callGetApi(`/api/category/${id}`);
|
||||
if (res.status === 404) {
|
||||
info.set(null);
|
||||
return;
|
||||
} else if (!res.ok) {
|
||||
throw new Error("Failed to fetch category information");
|
||||
}
|
||||
|
||||
const { metadata, subCategories }: CategoryInfoResponse = await res.json();
|
||||
|
||||
if (id === "root") {
|
||||
info.set({ id, subCategoryIds: subCategories });
|
||||
} else {
|
||||
const { dataKey } = await unwrapDataKey(metadata!.dek, masterKey);
|
||||
const name = await decryptString(metadata!.name, metadata!.nameIv, dataKey);
|
||||
|
||||
info.set({
|
||||
id,
|
||||
dataKey,
|
||||
dataKeyVersion: new Date(metadata!.dekVersion),
|
||||
name,
|
||||
subCategoryIds: subCategories,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const fetchCategoryInfo = async (
|
||||
id: CategoryId,
|
||||
info: Writable<CategoryInfo | null>,
|
||||
masterKey: CryptoKey,
|
||||
) => {
|
||||
await fetchCategoryInfoFromServer(id, info, masterKey);
|
||||
};
|
||||
|
||||
export const getCategoryInfo = (categoryId: CategoryId, masterKey: CryptoKey) => {
|
||||
// TODO: MEK rotation
|
||||
|
||||
let info = categoryInfoStore.get(categoryId);
|
||||
if (!info) {
|
||||
info = writable(null);
|
||||
categoryInfoStore.set(categoryId, info);
|
||||
}
|
||||
|
||||
fetchCategoryInfo(categoryId, info, masterKey); // Intended
|
||||
return info;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user