feat: nav progress bar, chapter list polling, live chapter fallback, and jump to current page
Some checks failed
Deploy / Deploy Production (push) Has been skipped
Deploy / Cleanup Preview (push) Has been skipped
Deploy / Deploy Preview (push) Failing after 1s
CI / Scraper / Lint (pull_request) Successful in 10s
CI / Scraper / Test (pull_request) Successful in 16s
CI / UI / Build (pull_request) Successful in 20s
CI / Scraper / Build (pull_request) Successful in 9s

This commit is contained in:
Admin
2026-03-06 17:39:40 +05:00
parent e723459507
commit 76d616a308
5 changed files with 158 additions and 16 deletions

View File

@@ -0,0 +1,46 @@
import { error } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { env } from '$env/dynamic/private';
import { log } from '$lib/server/logger';
const SCRAPER_URL = env.SCRAPER_API_URL ?? 'http://localhost:8080';
/**
* GET /api/chapter-text-preview/[slug]/[n]
* Proxies to the scraper's /api/chapter-text-preview endpoint.
* Used client-side when the normal chapter path returns no content
* (chapter indexed but not yet scraped to MinIO).
*/
export const GET: RequestHandler = async ({ params, url }) => {
const { slug, n } = params;
const chapter = parseInt(n, 10);
if (!slug || !chapter || chapter < 1) {
error(400, 'Invalid slug or chapter number');
}
// Forward optional query params (chapter_url, title) if present
const qs = new URLSearchParams();
const chapterUrl = url.searchParams.get('chapter_url');
const title = url.searchParams.get('title');
if (chapterUrl) qs.set('chapter_url', chapterUrl);
if (title) qs.set('title', title);
const scraperRes = await fetch(
`${SCRAPER_URL}/api/chapter-text-preview/${encodeURIComponent(slug)}/${chapter}?${qs.toString()}`
).catch((e) => {
log.error('chapter-preview', 'scraper fetch failed', { slug, chapter, err: String(e) });
return null;
});
if (!scraperRes || !scraperRes.ok) {
const status = scraperRes?.status ?? 502;
log.error('chapter-preview', 'scraper returned error', { slug, chapter, status });
error(status as Parameters<typeof error>[0], 'Chapter preview not available');
}
const data = await scraperRes.json();
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' }
});
};