From a276a5d64d24eae8e02ade1823377467841e23e8 Mon Sep 17 00:00:00 2001 From: ciregenz Date: Fri, 7 Aug 2026 19:28:17 -0700 Subject: [PATCH] [eric] canvas: a browser leaving the rail lands on its snapshot and attaches the guest after the motion, killing the browser-only jank --- .../hooks/interaction/useWebviewSuspend.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/pages/Dashboard/hooks/interaction/useWebviewSuspend.ts b/frontend/src/app/pages/Dashboard/hooks/interaction/useWebviewSuspend.ts index 05fc01af..75c6d674 100644 --- a/frontend/src/app/pages/Dashboard/hooks/interaction/useWebviewSuspend.ts +++ b/frontend/src/app/pages/Dashboard/hooks/interaction/useWebviewSuspend.ts @@ -168,7 +168,18 @@ export function useWebviewSuspend( // Un-minimizing is an explicit "give it back", so it wakes the card wherever the camera happens to be pointing. if (wasMinimized[id]) { restoredAt.set(id, Date.now()); - dispatch(resumeBrowserCard(id)); + // Straight into a tile (rail -> fullscreen): attaching the guest is a SYNCHRONOUS 60-290ms + // main-thread IPC, and firing it inside the landing + camera glide is the browser-only jank + // (DOM windows never pay it). The snapshot is pixel-identical, so let it do the landing and + // attach once the motion is over; re-minimized in the gap means never attach at all. + if (store.getState().dashboardLayout.tiledCards[id]) { + window.setTimeout(() => { + const dl = store.getState().dashboardLayout; + if (!dl.minimizedCards[id] && dl.suspendedBrowserCards[id]) dispatch(resumeBrowserCard(id)); + }, 600); + } else { + dispatch(resumeBrowserCard(id)); + } budget--; continue; }