From 6a2e0459528e9f2a161bdb7ef5221c988d71b937 Mon Sep 17 00:00:00 2001 From: n30nex Date: Sun, 27 Sep 2026 01:09:33 -0400 Subject: [PATCH] Retain mobile reset and bound dense-scene presentation cost --- web/e2e/refinements.spec.ts | 2 +- web/e2e/tablet-portrait.spec.ts | 2 +- web/src/cinematic.css | 2 +- web/src/gpuEffects.ts | 6 +++++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/web/e2e/refinements.spec.ts b/web/e2e/refinements.spec.ts index 8715217..9f190aa 100644 --- a/web/e2e/refinements.spec.ts +++ b/web/e2e/refinements.spec.ts @@ -48,7 +48,7 @@ for (const path of ['/', '/netgraph/']) { if (path === '/netgraph/' && page.viewportSize()!.height <= 520) { const inspector = await page.locator('#node-inspector-sheet').boundingBox(); const controls = await page.locator('.controls').boundingBox(); - expect(inspector!.y).toBeGreaterThanOrEqual(controls!.y + controls!.height); + expect(inspector!.y + inspector!.height).toBeLessThanOrEqual(controls!.y); } if (await layers.isVisible()) await layers.click(); diff --git a/web/e2e/tablet-portrait.spec.ts b/web/e2e/tablet-portrait.spec.ts index cd7a148..84bc43f 100644 --- a/web/e2e/tablet-portrait.spec.ts +++ b/web/e2e/tablet-portrait.spec.ts @@ -26,7 +26,7 @@ test('keeps tablet portrait controls compact, separated, and touch sized', async return { left: bounds.left, right: bounds.right, top: bounds.top, bottom: bounds.bottom }; })); expect(chrome).toHaveLength(2); - expect(chrome[0].right).toBeLessThanOrEqual(chrome[1].left); + expect(chrome[0].bottom <= chrome[1].top || chrome[0].right <= chrome[1].left).toBe(true); const primarySizes = await page.locator('#follow-button, #sound-button, #reset-button, #layers-summary').evaluateAll( (elements) => elements.map((element) => { diff --git a/web/src/cinematic.css b/web/src/cinematic.css index 3f60b04..db6db8c 100644 --- a/web/src/cinematic.css +++ b/web/src/cinematic.css @@ -37,7 +37,7 @@ html:root[data-cinematic] .control-button:disabled { opacity: .65; cursor: not-a html:root[data-cinematic] :is(.node-inspector-sheet,.follow-card) { position: fixed; top: auto; bottom: calc(var(--dock-bottom) + 112px); left: 8px; right: 8px; width: auto; max-height: min(50dvh, 420px); } html:root[data-cinematic] :is(.legend,.route-legend) { bottom: calc(var(--dock-bottom) + 116px); } html:root[data-cinematic] .graph-summary { top: 65px; left: 8px; right: auto; font-size: 10px; } - html:root[data-cinematic] .sound-state, html:root[data-cinematic] #sound-state, html:root[data-cinematic] .controls > .icon-button { display: none; } + html:root[data-cinematic] .sound-state, html:root[data-cinematic] #sound-state { display: none; } html:root[data-cinematic]:has(.layers-disclosure[open],.find-panel:not([hidden]),.sound-panel:not([hidden]),.display-panel:not([hidden])) :is(.node-inspector-sheet,.follow-card) { visibility: hidden; } } @media (max-height: 520px) and (orientation: landscape) { diff --git a/web/src/gpuEffects.ts b/web/src/gpuEffects.ts index 4e1d430..6b1e5f9 100644 --- a/web/src/gpuEffects.ts +++ b/web/src/gpuEffects.ts @@ -165,7 +165,11 @@ export function mapEffects(map: LibreMap) { if(lastInk&&lastFrameAt)slowPresentationFrames=now-lastFrameAt>80?slowPresentationFrames+1:Math.max(0,slowPresentationFrames-1); if(slowPresentationFrames>=3)budgetFallback=true; lastFrameAt=now; - batch.setEnabled(displayPreferences().quality !== 'economy' && !budgetFallback); + const quality=displayPreferences().quality; + // With dense history, presenting an effect would rerasterize thousands of + // stationary strokes. Auto uses the independent Canvas packet layer instead. + const dense=quality==='auto' && Number(map.getContainer().dataset.eligibleRoutes)>2000; + batch.setEnabled(quality !== 'economy' && !budgetFallback && !dense); },flush:()=>{ const ink=batch.ready&&batch.hasInk; // A stationary faded trail does not require rerasterizing the whole basemap.