검색 필터에 즐겨찾기 여부 추가

This commit is contained in:
static
2026-01-18 13:29:06 +09:00
parent 63163d6279
commit 72babc532f
7 changed files with 57 additions and 11 deletions

View File

@@ -20,7 +20,12 @@ export const getFileCacheIndex = async () => {
};
export const storeFileCacheIndex = async (fileCacheIndex: FileCacheIndex) => {
await cacheIndex.fileCache.put(fileCacheIndex);
await cacheIndex.fileCache.put({
fileId: fileCacheIndex.fileId,
cachedAt: fileCacheIndex.cachedAt,
lastRetrievedAt: fileCacheIndex.lastRetrievedAt,
size: fileCacheIndex.size,
});
};
export const deleteFileCacheIndex = async (fileId: number) => {

View File

@@ -74,7 +74,11 @@ export const getDirectoryInfo = async (id: number) => {
};
export const storeDirectoryInfo = async (directoryInfo: DirectoryInfo) => {
await filesystem.directory.upsert(directoryInfo.id, { ...directoryInfo });
await filesystem.directory.upsert(directoryInfo.id, {
parentId: directoryInfo.parentId,
name: directoryInfo.name,
isFavorite: directoryInfo.isFavorite,
});
};
export const deleteDirectoryInfo = async (id: number) => {
@@ -108,7 +112,15 @@ export const bulkGetFileInfos = async (ids: number[]) => {
};
export const storeFileInfo = async (fileInfo: FileInfo) => {
await filesystem.file.upsert(fileInfo.id, { ...fileInfo });
await filesystem.file.upsert(fileInfo.id, {
parentId: fileInfo.parentId,
name: fileInfo.name,
contentType: fileInfo.contentType,
createdAt: fileInfo.createdAt,
lastModifiedAt: fileInfo.lastModifiedAt,
categoryIds: fileInfo.categoryIds,
isFavorite: fileInfo.isFavorite,
});
};
export const deleteFileInfo = async (id: number) => {
@@ -135,7 +147,12 @@ export const getCategoryInfo = async (id: number) => {
};
export const storeCategoryInfo = async (categoryInfo: CategoryInfo) => {
await filesystem.category.upsert(categoryInfo.id, { ...categoryInfo });
await filesystem.category.upsert(categoryInfo.id, {
parentId: categoryInfo.parentId,
name: categoryInfo.name,
files: categoryInfo.files,
isFileRecursive: categoryInfo.isFileRecursive,
});
};
export const updateCategoryInfo = async (id: number, changes: { isFileRecursive?: boolean }) => {

View File

@@ -25,6 +25,7 @@
includeImages: boolean;
includeVideos: boolean;
includeDirectories: boolean;
searchInFavorites: boolean;
searchInDirectory: boolean;
categories: SearchFilter["categories"];
}
@@ -36,6 +37,7 @@
includeImages: false,
includeVideos: false,
includeDirectories: false,
searchInFavorites: false,
searchInDirectory: false,
categories: [],
});
@@ -45,6 +47,7 @@
filters.includeImages ||
filters.includeVideos ||
filters.includeDirectories ||
filters.searchInFavorites ||
filters.name.trim().length > 0,
);
@@ -81,7 +84,9 @@
return sortEntries(
[...directories, ...files].filter(
({ name }) => !nameFilter || searchString(name, nameFilter),
(entry) =>
(!nameFilter || searchString(entry.name, nameFilter)) &&
(!filters.searchInFavorites || entry.isFavorite),
),
);
});
@@ -118,7 +123,7 @@
},
};
$effect(() => {
$effect.pre(() => {
if (data.directoryId) {
HybridPromise.resolve(getDirectoryInfo(data.directoryId, $masterKeyStore?.get(1)?.key!)).then(
(res) => {
@@ -132,6 +137,10 @@
}
});
$effect.pre(() => {
filters.searchInFavorites = data.fromFavorites;
});
$effect(() => {
// Svelte sucks
hasAnyFilter;
@@ -172,6 +181,7 @@
{#if !hasCategoryFilter}
<Chip bind:selected={filters.includeDirectories}>폴더</Chip>
{/if}
<Chip bind:selected={filters.searchInFavorites}>즐겨찾기</Chip>
{#if directoryInfo?.exists}
<Chip bind:selected={filters.searchInDirectory}>
위치: {directoryInfo.name}

View File

@@ -4,15 +4,18 @@ import type { PageLoad } from "./$types";
export const load: PageLoad = ({ url }) => {
const directoryId = url.searchParams.get("directoryId");
const from = url.searchParams.get("from");
const zodRes = z
.object({
directoryId: z.coerce.number().int().positive().nullable(),
from: z.enum(["favorites"]).nullable(),
})
.safeParse({ directoryId });
.safeParse({ directoryId, from });
if (!zodRes.success) error(400, "Invalid query parameters");
return {
directoryId: zodRes.data.directoryId,
fromFavorites: zodRes.data.from === "favorites",
};
};

View File

@@ -2,11 +2,14 @@
import { onMount } from "svelte";
import { goto } from "$app/navigation";
import { RowVirtualizer } from "$lib/components/atoms";
import { TopBar } from "$lib/components/molecules";
import { masterKeyStore } from "$lib/stores";
import Directory from "./Directory.svelte";
import File from "./File.svelte";
import { requestFavoriteEntries, requestRemoveFavorite, type FavoriteEntry } from "./service";
import IconSearch from "~icons/material-symbols/search";
let { data } = $props();
let entries: FavoriteEntry[] = $state([]);
@@ -41,14 +44,22 @@
<title>즐겨찾기</title>
</svelte:head>
<div class="flex h-full flex-col p-4">
<TopBar title="즐겨찾기" showBackButton={false}>
<button
onclick={() => goto("/search?from=favorites")}
class="w-full rounded-full p-1 text-2xl active:bg-black active:bg-opacity-[0.04]"
>
<IconSearch />
</button>
</TopBar>
<div class="flex h-full flex-col p-4 !pt-0">
{#if isLoading}
<div class="flex flex-grow items-center justify-center">
<p class="text-gray-500">
{#if data.favorites.files.length === 0 && data.favorites.directories.length === 0}
즐겨찾기한 항목이 없어요.
{:else}
로딩 중...
즐겨찾기 목록을 불러오고 있어요.
{/if}
</p>
</div>

View File

@@ -20,5 +20,5 @@
actionButtonIcon={IconClose}
onActionButtonClick={onRemoveClick}
>
<DirectoryEntryLabel type="directory" name={info.name} />
<DirectoryEntryLabel type="directory" name={info.name} isFavorite />
</ActionEntryButton>

View File

@@ -23,5 +23,5 @@
actionButtonIcon={IconClose}
onActionButtonClick={onRemoveClick}
>
<DirectoryEntryLabel type="file" thumbnail={$thumbnail} name={info.name} />
<DirectoryEntryLabel type="file" thumbnail={$thumbnail} name={info.name} isFavorite />
</ActionEntryButton>