yiekheng 43a2a6d3f8 Rewrite reader around known-dimension page placeholders
Replaces the prepend/flushSync/scrollBy gymnastics with placeholder divs
sized by each page's width/height. Document height is correct from the
first paint, so resume + backward scroll just work — no scroll
compensation, no gesture fights, no forced aspect ratio distorting images.

- New /api/chapters/[id]/meta returns the dim skeleton for any chapter.
- Chapter page pre-fetches the starting chapter's meta server-side and
  parallelizes the two Prisma queries via Promise.all.
- Reader renders placeholders with aspectRatio: w/h, lazy-loads image
  URLs in batches via IntersectionObserver, and prefetches the next
  chapter's meta ~3 pages from the end.
- Scroll tracker walks only the intersecting-pages set (~3–5 elements)
  instead of every loaded page per rAF.
- scroll={false} on all Links into the reader + { scroll: false } on
  double-tap router.push, plus a belt-and-suspenders rAF re-scroll, so
  resume survives soft navigation and browser scroll-restoration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 13:01:41 +08:00

20 lines
550 B
TypeScript

import { prisma } from "@/lib/db";
type Params = { params: Promise<{ chapterId: string }> };
export async function GET(_request: Request, { params }: Params) {
const { chapterId: raw } = await params;
const chapterId = parseInt(raw, 10);
if (isNaN(chapterId)) {
return Response.json({ error: "Invalid chapterId" }, { status: 400 });
}
const pages = await prisma.page.findMany({
where: { chapterId },
orderBy: { number: "asc" },
select: { number: true, width: true, height: true },
});
return Response.json(pages);
}