feat: preload the whole current chapter in continuous mode

Eager-load every page of the current chapter rather than a bounded
rolling window, so pages are fetched up front (the browser paces them
over its per-origin connection limit, top-to-bottom = reading order)
instead of filling in as they're scrolled onto. This drops the
scrollLeadIdx/eagerThrough machinery in favour of a plain
`loading="eager"`.

The first few pages of the *next* chapter are already warmed when the
reader nears the end of the current one (the next-chapter preloader), so
flipping over stays instant.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-07-07 19:47:48 +02:00
parent c69ff502f7
commit 987d1ba235
6 changed files with 34 additions and 98 deletions

View File

@@ -55,20 +55,22 @@ async function goContinuous(page: Page, path: string) {
await expect(page.getByTestId('reader-continuous')).toBeVisible();
}
test('opening at page 1 eager-loads the leading window but leaves far pages lazy', async ({ page }) => {
test('eager-loads the whole current chapter up front, not just the visible pages', async ({ page }) => {
await mockReader(page);
await goContinuous(page, `/manga/${MANGA_ID}/chapter/${CH1}`);
// The first page is always eager (it's on screen).
await expect(page.getByTestId('reader-page-1')).toHaveAttribute('loading', 'eager');
// A page far past the leading window is not fetched up front.
await expect(page.getByTestId('reader-page-10')).toHaveAttribute('loading', 'lazy');
});
// Every page — including ones far below the fold — is eager, so the
// browser fetches the whole chapter up front instead of on scroll.
for (let n = 1; n <= PAGE_COUNT; n++) {
await expect(page.getByTestId(`reader-page-${n}`)).toHaveAttribute('loading', 'eager');
}
test('opening deep in the chapter eager-loads the pages around that position', async ({ page }) => {
await mockReader(page);
// Deep-link to page 8: the window now covers the tail, so page 10 is eager.
await goContinuous(page, `/manga/${MANGA_ID}/chapter/${CH1}?page=8`);
await expect(page.getByTestId('reader-page-10')).toHaveAttribute('loading', 'eager');
// ... and a page well below the fold actually finishes loading without
// ever scrolling to it — the observable payoff of preloading.
const lastPage = page.getByTestId(`reader-page-${PAGE_COUNT}`);
await expect(async () => {
const loaded = await lastPage.evaluate((img: HTMLImageElement) => img.complete && img.naturalWidth > 0);
expect(loaded).toBe(true);
}).toPass();
expect(await page.evaluate(() => window.scrollY)).toBe(0);
});