feat(ui): cross-screen caches + invitation delta channel + hint recenter on a zoomed board #56

Merged
developer merged 5 commits from feature/lobby-cache-any-screen-invitation-delta into development 2026-06-14 10:57:37 +00:00
Showing only changes of commit 553152e195 - Show all commits
+12 -6
View File
@@ -69,12 +69,16 @@
// toggle or an explicit recenter request (the hint) moves it. A recenter with no zoom change // toggle or an explicit recenter request (the hint) moves it. A recenter with no zoom change
// pans straight to `focus`, since the board width is stable and the width-driven tween below // pans straight to `focus`, since the board width is stable and the width-driven tween below
// has nothing to ride (the case the owner hit: a hint taken while already zoomed in). // has nothing to ride (the case the owner hit: a hint taken while already zoomed in).
// The previous zoom state, to tell a zoom toggle from a recenter request. The board always mounts // prevZoom/prevRecenter let the effect tell a zoom toggle from a recenter request. The board
// zoomed-out, so it starts false and is updated to the live zoom on each effect run. // always mounts zoomed-out, so prevZoom starts false; both are updated on each effect run.
let prevZoom = false; let prevZoom = false;
let prevRecenter = 0;
$effect(() => { $effect(() => {
const on = zoomed; const on = zoomed;
void recenter; // re-run on an explicit recenter request even when the zoom state is unchanged // An explicit "scroll to focus now" request (the hint). Read into a variable that is USED below,
// so the reactive dependency survives minification (a bare `void recenter` could be dropped) and
// an incidental re-run never pans on its own.
const rc = recenter;
const vp = viewport; const vp = viewport;
if (!vp) return; if (!vp) return;
const f = untrack(() => focus); const f = untrack(() => focus);
@@ -91,11 +95,13 @@
finalST = Math.max(0, Math.min((f.row + 0.5) * cell - clientH / 2, fullW - clientH)); finalST = Math.max(0, Math.min((f.row + 0.5) * cell - clientH / 2, fullW - clientH));
} }
const toggled = on !== prevZoom; const toggled = on !== prevZoom;
const recentered = rc !== prevRecenter;
prevZoom = on; prevZoom = on;
prevRecenter = rc;
if (!toggled) { if (!toggled) {
// No zoom change: an explicit recenter (the hint) pans straight to the focused word; a stale // No zoom change: pan straight to the focused word only on an explicit recenter request (the
// run with nothing focused leaves the scroll alone. // hint), never on an incidental re-run such as a viewport resize.
if (on && f) { if (recentered && on && f) {
vp.scrollLeft = finalSL; vp.scrollLeft = finalSL;
vp.scrollTop = finalST; vp.scrollTop = finalST;
} }