feat(search): tag-based page search surface + per-page tags & collections
Add the /search surface (Pages / Chapters / Mangas tabs) backed by per-user page tags and per-page collections: schema (migration 0023), backend endpoints for page tags/collections and tagged-page aggregations (with the OCR text-search param reserved at 501), plus the frontend API clients, library Page-tags tab, collection page sections, page context menu / AddTagsSheet, and reader long-press wiring. Includes the continuous-reader navigation fixes (?page=N handling, chapter-reset timing, back-button pops history) and tag-normalization hardening accumulated on the branch. Bump version 0.60.2 -> 0.62.0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,15 +2,19 @@ import { ApiError } from '$lib/api/client';
|
||||
import { listMyBookmarks } from '$lib/api/bookmarks';
|
||||
import { listMyCollections } from '$lib/api/collections';
|
||||
import { listMyReadProgress } from '$lib/api/read_progress';
|
||||
import {
|
||||
listMyPageTags,
|
||||
listMyDistinctPageTags
|
||||
} from '$lib/api/page_tags';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const ssr = false;
|
||||
|
||||
/**
|
||||
* Loads bookmarks + collections + reading-history in one shot so the
|
||||
* Library segmented control can swap between sub-tabs without firing a
|
||||
* second round trip per tap. 401 → unauthenticated path; the page
|
||||
* surfaces a sign-in prompt and renders empty lists.
|
||||
* Loads bookmarks + collections + history + page-tags in one shot so
|
||||
* the Library segmented control can swap between sub-tabs without
|
||||
* firing a second round trip per tap. 401 → unauthenticated path; the
|
||||
* page surfaces a sign-in prompt and renders empty lists.
|
||||
*/
|
||||
export const load: PageLoad = async () => {
|
||||
const empty = {
|
||||
@@ -18,19 +22,26 @@ export const load: PageLoad = async () => {
|
||||
bookmarks: [] as Awaited<ReturnType<typeof listMyBookmarks>>['items'],
|
||||
collections: [] as Awaited<ReturnType<typeof listMyCollections>>['items'],
|
||||
history: [] as Awaited<ReturnType<typeof listMyReadProgress>>['items'],
|
||||
pageTags: [] as Awaited<ReturnType<typeof listMyPageTags>>['items'],
|
||||
distinctPageTags: [] as Awaited<ReturnType<typeof listMyDistinctPageTags>>,
|
||||
error: null as string | null
|
||||
};
|
||||
try {
|
||||
const [bookmarks, collections, history] = await Promise.all([
|
||||
listMyBookmarks(),
|
||||
listMyCollections({ limit: 200 }),
|
||||
listMyReadProgress({ limit: 100 })
|
||||
]);
|
||||
const [bookmarks, collections, history, pageTags, distinctPageTags] =
|
||||
await Promise.all([
|
||||
listMyBookmarks(),
|
||||
listMyCollections({ limit: 200 }),
|
||||
listMyReadProgress({ limit: 100 }),
|
||||
listMyPageTags({ limit: 100 }),
|
||||
listMyDistinctPageTags(undefined, 100)
|
||||
]);
|
||||
return {
|
||||
...empty,
|
||||
bookmarks: bookmarks.items,
|
||||
collections: collections.items,
|
||||
history: history.items
|
||||
history: history.items,
|
||||
pageTags: pageTags.items,
|
||||
distinctPageTags
|
||||
};
|
||||
} catch (e) {
|
||||
if (e instanceof ApiError && e.status === 401) {
|
||||
|
||||
Reference in New Issue
Block a user