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:
@@ -18,6 +18,7 @@
|
||||
import Search from '@lucide/svelte/icons/search';
|
||||
import SlidersHorizontal from '@lucide/svelte/icons/sliders-horizontal';
|
||||
import ArrowUpDown from '@lucide/svelte/icons/arrow-up-down';
|
||||
import ArrowRight from '@lucide/svelte/icons/arrow-right';
|
||||
import Plus from '@lucide/svelte/icons/plus';
|
||||
|
||||
const PAGE_SIZE = 50;
|
||||
@@ -402,7 +403,22 @@
|
||||
{/if}
|
||||
{/snippet}
|
||||
|
||||
<h1>Mangas</h1>
|
||||
<div class="heading-row">
|
||||
<h1>Mangas</h1>
|
||||
<!--
|
||||
Secondary entry point into the per-page search at /search,
|
||||
which is headed "Page search". Label matches the destination's
|
||||
title so the two read as one feature. It filters the user's
|
||||
tagged pages and pivots between Pages / Chapters / Mangas;
|
||||
title-search above stays the primary action. The name is also
|
||||
forward-compatible with the planned OCR text search (which
|
||||
searches page content, not just tags).
|
||||
-->
|
||||
<a class="alt-search" href="/search" data-testid="nav-page-search">
|
||||
<span>Page search</span>
|
||||
<ArrowRight size={14} aria-hidden="true" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<form
|
||||
onsubmit={onSubmit}
|
||||
@@ -562,11 +578,38 @@
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.heading-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-3);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.heading-row h1 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.alt-search {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
color: var(--text-muted);
|
||||
font-size: var(--font-sm);
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.alt-search:hover {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-3);
|
||||
margin-bottom: var(--space-4);
|
||||
margin-top: var(--space-3);
|
||||
}
|
||||
|
||||
.search-row {
|
||||
|
||||
Reference in New Issue
Block a user