feat(home): add a Continue-reading shelf with new-chapter badges
Surface a horizontal "Continue reading" shelf at the top of the homepage, fed by the user's read-progress history. Each card jumps back to the exact page they left off (deep-linking `?page=N` past the first) and flags how many chapters have landed since — the personal new_chapters_count from the read-progress list. The shelf is fetched after the catalogue load so the public browse path stays unauthenticated; guests get an empty list (401 swallowed) and the shelf stays hidden. Add new_chapters_count to the frontend ReadProgressSummary type to match the backend. Component unit tests cover href/deep-link, badge visibility, and the no-chapter fallback; e2e covers signed-in (shelf + badge) and anonymous (hidden). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -22,7 +22,12 @@
|
||||
sortLabel as composeSortLabel,
|
||||
sortUrlParams
|
||||
} from '$lib/mangaSort';
|
||||
import {
|
||||
listMyReadProgressOrEmpty,
|
||||
type ReadProgressSummary
|
||||
} from '$lib/api/read_progress';
|
||||
import Chip from '$lib/components/Chip.svelte';
|
||||
import ContinueReadingShelf from '$lib/components/ContinueReadingShelf.svelte';
|
||||
import MangaCard from '$lib/components/MangaCard.svelte';
|
||||
import Pager from '$lib/components/Pager.svelte';
|
||||
import SegmentedControl from '$lib/components/SegmentedControl.svelte';
|
||||
@@ -37,6 +42,7 @@
|
||||
const PAGE_SIZE = 50;
|
||||
|
||||
let mangas: MangaCardData[] = $state([]);
|
||||
let continueEntries = $state<ReadProgressSummary[]>([]);
|
||||
let search = $state('');
|
||||
let sort = $state<MangaSort>(DEFAULT_SORT);
|
||||
let order = $state<SortOrder>(defaultOrderFor(DEFAULT_SORT));
|
||||
@@ -301,6 +307,16 @@
|
||||
}
|
||||
await hydrateFromUrl();
|
||||
await load();
|
||||
// Fetch the "Continue reading" shelf after the catalogue so the
|
||||
// public browse path stays unauthenticated and unblocked. Returns
|
||||
// empty for guests (401 swallowed), which hides the shelf.
|
||||
try {
|
||||
const progress = await listMyReadProgressOrEmpty();
|
||||
continueEntries = progress.items;
|
||||
} catch {
|
||||
// Never let a history hiccup break the catalogue — leave the
|
||||
// shelf hidden.
|
||||
}
|
||||
});
|
||||
|
||||
// Track viewport in a separate $effect so the listener cleans up on
|
||||
@@ -455,6 +471,10 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{#if continueEntries.length > 0}
|
||||
<ContinueReadingShelf entries={continueEntries} />
|
||||
{/if}
|
||||
|
||||
<form
|
||||
onsubmit={onSubmit}
|
||||
action="javascript:void(0)"
|
||||
|
||||
Reference in New Issue
Block a user