mirror of
https://github.com/kmc7468/arkvault.git
synced 2026-02-04 08:06:56 +00:00
네트워크 호출 결과가 IndexedDB에 캐시되지 않던 버그 수정
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { CheckBox, RowVirtualizer } from "$lib/components/atoms";
|
import { CheckBox, RowVirtualizer } from "$lib/components/atoms";
|
||||||
import { SubCategories, type SelectedCategory } from "$lib/components/molecules";
|
import { SubCategories, type SelectedCategory } from "$lib/components/molecules";
|
||||||
|
import { updateCategoryInfo } from "$lib/indexedDB";
|
||||||
import type { CategoryInfo } from "$lib/modules/filesystem";
|
import type { CategoryInfo } from "$lib/modules/filesystem";
|
||||||
import { sortEntries } from "$lib/utils";
|
import { sortEntries } from "$lib/utils";
|
||||||
import File from "./File.svelte";
|
import File from "./File.svelte";
|
||||||
@@ -28,6 +29,9 @@
|
|||||||
isFileRecursive = $bindable(),
|
isFileRecursive = $bindable(),
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
|
let lastCategoryId = $state<CategoryInfo["id"] | undefined>();
|
||||||
|
let lastIsFileRecursive = $state<boolean | undefined>();
|
||||||
|
|
||||||
let files = $derived(
|
let files = $derived(
|
||||||
sortEntries(
|
sortEntries(
|
||||||
info.files
|
info.files
|
||||||
@@ -35,6 +39,19 @@
|
|||||||
.filter(({ details }) => isFileRecursive || !details.isRecursive) ?? [],
|
.filter(({ details }) => isFileRecursive || !details.isRecursive) ?? [],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if (info.id === "root" || isFileRecursive === undefined) return;
|
||||||
|
if (lastCategoryId !== info.id) {
|
||||||
|
lastCategoryId = info.id;
|
||||||
|
lastIsFileRecursive = isFileRecursive;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (lastIsFileRecursive === isFileRecursive) return;
|
||||||
|
|
||||||
|
lastIsFileRecursive = isFileRecursive;
|
||||||
|
void updateCategoryInfo(info.id, { isFileRecursive });
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
|
|||||||
@@ -52,25 +52,76 @@ const fetchFromServer = async (id: CategoryId, masterKey: CryptoKey) => {
|
|||||||
metadata,
|
metadata,
|
||||||
subCategories: subCategoriesRaw,
|
subCategories: subCategoriesRaw,
|
||||||
files: filesRaw,
|
files: filesRaw,
|
||||||
} = await trpc().category.get.query({ id });
|
} = await trpc().category.get.query({ id, recurse: true });
|
||||||
const [subCategories, files] = await Promise.all([
|
const subCategories = await Promise.all(
|
||||||
Promise.all(
|
subCategoriesRaw.map(async (category) => {
|
||||||
subCategoriesRaw.map(async (category) => ({
|
const decrypted = await decryptCategoryMetadata(category, masterKey);
|
||||||
|
const existing = await IndexedDB.getCategoryInfo(category.id);
|
||||||
|
await IndexedDB.storeCategoryInfo({
|
||||||
id: category.id,
|
id: category.id,
|
||||||
...(await decryptCategoryMetadata(category, masterKey)),
|
parentId: id,
|
||||||
})),
|
name: decrypted.name,
|
||||||
),
|
files: existing?.files ?? [],
|
||||||
filesRaw
|
isFileRecursive: existing?.isFileRecursive ?? false,
|
||||||
? Promise.all(
|
});
|
||||||
filesRaw.map(async (file) => ({
|
return {
|
||||||
|
id: category.id,
|
||||||
|
...decrypted,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const existingFiles = filesRaw
|
||||||
|
? await IndexedDB.bulkGetFileInfos(filesRaw.map((file) => file.id))
|
||||||
|
: [];
|
||||||
|
const files = filesRaw
|
||||||
|
? await Promise.all(
|
||||||
|
filesRaw.map(async (file, index) => {
|
||||||
|
const decrypted = await decryptFileMetadata(file, masterKey);
|
||||||
|
const existing = existingFiles[index];
|
||||||
|
if (existing) {
|
||||||
|
const categoryIds = file.isRecursive
|
||||||
|
? existing.categoryIds
|
||||||
|
: Array.from(new Set([...existing.categoryIds, id as number]));
|
||||||
|
await IndexedDB.storeFileInfo({
|
||||||
|
id: file.id,
|
||||||
|
parentId: existing.parentId,
|
||||||
|
contentType: file.contentType,
|
||||||
|
name: decrypted.name,
|
||||||
|
createdAt: decrypted.createdAt,
|
||||||
|
lastModifiedAt: decrypted.lastModifiedAt,
|
||||||
|
categoryIds,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return {
|
||||||
id: file.id,
|
id: file.id,
|
||||||
contentType: file.contentType,
|
contentType: file.contentType,
|
||||||
isRecursive: file.isRecursive,
|
isRecursive: file.isRecursive,
|
||||||
...(await decryptFileMetadata(file, masterKey)),
|
...decrypted,
|
||||||
})),
|
};
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
: undefined,
|
: undefined;
|
||||||
]);
|
|
||||||
|
const decryptedMetadata = metadata
|
||||||
|
? await decryptCategoryMetadata(metadata, masterKey)
|
||||||
|
: undefined;
|
||||||
|
if (id !== "root" && metadata && decryptedMetadata) {
|
||||||
|
const existingCategory = await IndexedDB.getCategoryInfo(id);
|
||||||
|
await IndexedDB.storeCategoryInfo({
|
||||||
|
id: id as number,
|
||||||
|
parentId: metadata.parent,
|
||||||
|
name: decryptedMetadata.name,
|
||||||
|
files:
|
||||||
|
files?.map((file) => ({
|
||||||
|
id: file.id,
|
||||||
|
isRecursive: file.isRecursive,
|
||||||
|
})) ??
|
||||||
|
existingCategory?.files ??
|
||||||
|
[],
|
||||||
|
isFileRecursive: existingCategory?.isFileRecursive ?? false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (id === "root") {
|
if (id === "root") {
|
||||||
return {
|
return {
|
||||||
@@ -84,7 +135,7 @@ const fetchFromServer = async (id: CategoryId, masterKey: CryptoKey) => {
|
|||||||
exists: true as const,
|
exists: true as const,
|
||||||
subCategories,
|
subCategories,
|
||||||
files,
|
files,
|
||||||
...(await decryptCategoryMetadata(metadata!, masterKey)),
|
...decryptedMetadata!,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -39,22 +39,52 @@ const fetchFromServer = async (id: DirectoryId, masterKey: CryptoKey) => {
|
|||||||
subDirectories: subDirectoriesRaw,
|
subDirectories: subDirectoriesRaw,
|
||||||
files: filesRaw,
|
files: filesRaw,
|
||||||
} = await trpc().directory.get.query({ id });
|
} = await trpc().directory.get.query({ id });
|
||||||
const [subDirectories, files] = await Promise.all([
|
const existingFiles = await IndexedDB.bulkGetFileInfos(filesRaw.map((file) => file.id));
|
||||||
|
const [subDirectories, files, decryptedMetadata] = await Promise.all([
|
||||||
Promise.all(
|
Promise.all(
|
||||||
subDirectoriesRaw.map(async (directory) => ({
|
subDirectoriesRaw.map(async (directory) => {
|
||||||
|
const decrypted = await decryptDirectoryMetadata(directory, masterKey);
|
||||||
|
await IndexedDB.storeDirectoryInfo({
|
||||||
id: directory.id,
|
id: directory.id,
|
||||||
...(await decryptDirectoryMetadata(directory, masterKey)),
|
parentId: id,
|
||||||
})),
|
name: decrypted.name,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
id: directory.id,
|
||||||
|
...decrypted,
|
||||||
|
};
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
Promise.all(
|
Promise.all(
|
||||||
filesRaw.map(async (file) => ({
|
filesRaw.map(async (file, index) => {
|
||||||
|
const decrypted = await decryptFileMetadata(file, masterKey);
|
||||||
|
await IndexedDB.storeFileInfo({
|
||||||
|
id: file.id,
|
||||||
|
parentId: id,
|
||||||
|
contentType: file.contentType,
|
||||||
|
name: decrypted.name,
|
||||||
|
createdAt: decrypted.createdAt,
|
||||||
|
lastModifiedAt: decrypted.lastModifiedAt,
|
||||||
|
categoryIds: existingFiles[index]?.categoryIds ?? [],
|
||||||
|
});
|
||||||
|
return {
|
||||||
id: file.id,
|
id: file.id,
|
||||||
contentType: file.contentType,
|
contentType: file.contentType,
|
||||||
...(await decryptFileMetadata(file, masterKey)),
|
...decrypted,
|
||||||
})),
|
};
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
|
metadata ? decryptDirectoryMetadata(metadata, masterKey) : undefined,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (id !== "root" && metadata && decryptedMetadata) {
|
||||||
|
await IndexedDB.storeDirectoryInfo({
|
||||||
|
id,
|
||||||
|
parentId: metadata.parent,
|
||||||
|
name: decryptedMetadata.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (id === "root") {
|
if (id === "root") {
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
@@ -69,7 +99,7 @@ const fetchFromServer = async (id: DirectoryId, masterKey: CryptoKey) => {
|
|||||||
parentId: metadata!.parent,
|
parentId: metadata!.parent,
|
||||||
subDirectories,
|
subDirectories,
|
||||||
files,
|
files,
|
||||||
...(await decryptDirectoryMetadata(metadata!, masterKey)),
|
...decryptedMetadata!,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -66,15 +66,26 @@ const bulkFetchFromIndexedDB = async (ids: number[]) => {
|
|||||||
const fetchFromServer = async (id: number, masterKey: CryptoKey) => {
|
const fetchFromServer = async (id: number, masterKey: CryptoKey) => {
|
||||||
try {
|
try {
|
||||||
const { categories: categoriesRaw, ...metadata } = await trpc().file.get.query({ id });
|
const { categories: categoriesRaw, ...metadata } = await trpc().file.get.query({ id });
|
||||||
const [categories] = await Promise.all([
|
const [categories, decryptedMetadata] = await Promise.all([
|
||||||
Promise.all(
|
Promise.all(
|
||||||
categoriesRaw.map(async (category) => ({
|
categoriesRaw.map(async (category) => ({
|
||||||
id: category.id,
|
id: category.id,
|
||||||
...(await decryptCategoryMetadata(category, masterKey)),
|
...(await decryptCategoryMetadata(category, masterKey)),
|
||||||
})),
|
})),
|
||||||
),
|
),
|
||||||
|
decryptFileMetadata(metadata, masterKey),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
await IndexedDB.storeFileInfo({
|
||||||
|
id,
|
||||||
|
parentId: metadata.parent,
|
||||||
|
contentType: metadata.contentType,
|
||||||
|
name: decryptedMetadata.name,
|
||||||
|
createdAt: decryptedMetadata.createdAt,
|
||||||
|
lastModifiedAt: decryptedMetadata.lastModifiedAt,
|
||||||
|
categoryIds: categories.map((category) => category.id),
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
exists: true as const,
|
exists: true as const,
|
||||||
@@ -82,7 +93,7 @@ const fetchFromServer = async (id: number, masterKey: CryptoKey) => {
|
|||||||
contentType: metadata.contentType,
|
contentType: metadata.contentType,
|
||||||
contentIv: metadata.contentIv,
|
contentIv: metadata.contentIv,
|
||||||
categories,
|
categories,
|
||||||
...(await decryptFileMetadata(metadata, masterKey)),
|
...decryptedMetadata,
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (isTRPCClientError(e) && e.data?.code === "NOT_FOUND") {
|
if (isTRPCClientError(e) && e.data?.code === "NOT_FOUND") {
|
||||||
@@ -97,12 +108,25 @@ const bulkFetchFromServer = async (ids: number[], masterKey: CryptoKey) => {
|
|||||||
const filesRaw = await trpc().file.bulkGet.query({ ids });
|
const filesRaw = await trpc().file.bulkGet.query({ ids });
|
||||||
const files = await Promise.all(
|
const files = await Promise.all(
|
||||||
filesRaw.map(async (file) => {
|
filesRaw.map(async (file) => {
|
||||||
const categories = await Promise.all(
|
const [categories, decryptedMetadata] = await Promise.all([
|
||||||
|
Promise.all(
|
||||||
file.categories.map(async (category) => ({
|
file.categories.map(async (category) => ({
|
||||||
id: category.id,
|
id: category.id,
|
||||||
...(await decryptCategoryMetadata(category, masterKey)),
|
...(await decryptCategoryMetadata(category, masterKey)),
|
||||||
})),
|
})),
|
||||||
);
|
),
|
||||||
|
decryptFileMetadata(file, masterKey),
|
||||||
|
]);
|
||||||
|
|
||||||
|
await IndexedDB.storeFileInfo({
|
||||||
|
id: file.id,
|
||||||
|
parentId: file.parent,
|
||||||
|
contentType: file.contentType,
|
||||||
|
name: decryptedMetadata.name,
|
||||||
|
createdAt: decryptedMetadata.createdAt,
|
||||||
|
lastModifiedAt: decryptedMetadata.lastModifiedAt,
|
||||||
|
categoryIds: categories.map((category) => category.id),
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
id: file.id,
|
id: file.id,
|
||||||
exists: true as const,
|
exists: true as const,
|
||||||
@@ -110,7 +134,7 @@ const bulkFetchFromServer = async (ids: number[], masterKey: CryptoKey) => {
|
|||||||
contentType: file.contentType,
|
contentType: file.contentType,
|
||||||
contentIv: file.contentIv,
|
contentIv: file.contentIv,
|
||||||
categories,
|
categories,
|
||||||
...(await decryptFileMetadata(file, masterKey)),
|
...decryptedMetadata,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user