fix(reader): harden swipe/long-press coexistence and next-chapter prefetch
- A long-press now cancels any pending swipe, so a hold-then-drag gesture opens the action sheet without also turning the page (regression-tested). - The next-chapter prefetch no longer retries on every page flip when the endpoint fails (guard clears only when the next chapter changes), and it clears a previous chapter's warmed images on navigation so stale hidden <img>s don't linger. - Tap zones set touch-action: pan-y so vertical panning stays native while horizontal swipes reach our handler. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -51,6 +51,36 @@ async function swipe(page: Page, dx: number, dy: number) {
|
||||
);
|
||||
}
|
||||
|
||||
// Dispatch pointerdown, hold (so long-press fires), then swipe+lift.
|
||||
async function holdThenSwipe(page: Page, holdMs: number, dx: number) {
|
||||
await page.evaluate(() => {
|
||||
const el = document.querySelector('[data-testid="reader-tap-center"]');
|
||||
if (!el) throw new Error('tap zone not found');
|
||||
el.dispatchEvent(new PointerEvent('pointerdown', { clientX: 300, clientY: 500, pointerType: 'touch', bubbles: true, cancelable: true }));
|
||||
});
|
||||
await page.waitForTimeout(holdMs);
|
||||
await page.evaluate(({ dx }) => {
|
||||
const el = document.querySelector('[data-testid="reader-tap-center"]');
|
||||
if (!el) throw new Error('tap zone not found');
|
||||
el.dispatchEvent(new PointerEvent('pointermove', { clientX: 300 + dx, clientY: 505, pointerType: 'touch', bubbles: true, cancelable: true }));
|
||||
el.dispatchEvent(new PointerEvent('pointerup', { clientX: 300 + dx, clientY: 505, pointerType: 'touch', bubbles: true, cancelable: true }));
|
||||
}, { dx });
|
||||
}
|
||||
|
||||
test('a long-press then swipe does not also turn the page', async ({ page }) => {
|
||||
await mockReader(page);
|
||||
await page.setViewportSize({ width: 390, height: 844 });
|
||||
await page.goto(`/manga/${MANGA_ID}/chapter/${CHAPTER_ID}`);
|
||||
const img = page.getByTestId('reader-page');
|
||||
await expect(img).toHaveAttribute('src', /k\/1/);
|
||||
|
||||
// Hold past the 450ms long-press threshold, then swipe left before lifting.
|
||||
await holdThenSwipe(page, 550, -200);
|
||||
|
||||
// The long-press consumed the gesture — the page must not have turned.
|
||||
await expect(img).toHaveAttribute('src', /k\/1/);
|
||||
});
|
||||
|
||||
test('horizontal swipe turns the page; vertical drag does not', async ({ page }) => {
|
||||
await mockReader(page);
|
||||
await page.setViewportSize({ width: 390, height: 844 }); // mobile → tap zones render
|
||||
|
||||
Reference in New Issue
Block a user