From 24b91b023b6a20e920d040554e93af4ee36be5cc Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Mon, 8 Jun 2026 17:28:18 +0000 Subject: [PATCH] =?UTF-8?q?fix(app):=20eliminate=20session=20switch=20late?= =?UTF-8?q?ncy=20=E2=80=94=20remove=20deferRender,=20Suspense=20flash,=20a?= =?UTF-8?q?nd=20instant=20rendering?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove three compounding session-switch responsiveness issues: 1. Remove deferRender mechanism — eliminates the rAF + setTimeout chain in session.tsx that blanked the review panel and gated the composer on every session switch, causing a ~170ms gap where UI was invisible. 2. Remove sessionSync() JSX read — the createResource was read in JSX ({sessionSync() ?? ""}), triggering the nearest Suspense boundary (the app-level splash screen) on every session switch while the sync Promise was pending. The resource returns void so the read was a no-op. 3. Widen messagesReady gate — accept when the session exists in the session list even before messages have loaded. This eliminates the blank screen on session switch; the composer and timeline render immediately with cached session data. 4. Remove 140ms artificial setTimeout in session-composer-region — the composer now re-shows after a single rAF yield (~16ms). --- packages/app/src/pages/session.tsx | 64 ++++++++----------- .../composer/session-composer-region.tsx | 6 +- 2 files changed, 26 insertions(+), 44 deletions(-) diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 336fefd5e192..56a6d52fe9c2 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -320,7 +320,8 @@ export default function Page() { const messagesReady = createMemo(() => { const id = params.id if (!id) return true - return sync.data.message[id] !== undefined + // Ready when messages are loaded OR session exists in the list (render immediately with cached data) + return sync.data.message[id] !== undefined || sync.session.get(id) !== undefined }) const historyMore = createMemo(() => { const id = params.id @@ -386,7 +387,6 @@ export default function Page() { mobileTab: "session" as "session" | "changes", changes: "git" as ChangeMode, newSessionWorktree: "main", - deferRender: false, }) const [followup, setFollowup] = persisted( @@ -404,17 +404,6 @@ export default function Page() { }), ) - createComputed((prev) => { - const key = sessionKey() - if (key !== prev) { - setStore("deferRender", true) - requestAnimationFrame(() => { - setTimeout(() => setStore("deferRender", false), 0) - }) - } - return key - }, sessionKey()) - let reviewFrame: number | undefined let refreshFrame: number | undefined let refreshTimer: number | undefined @@ -993,30 +982,28 @@ export default function Page() { loadingClass: string emptyClass: string }) => ( - - setTree("reviewScroll", el)} - focusedFile={tree.activeDiff} - onLineComment={(comment) => addCommentToContext({ ...comment, origin: "review" })} - onLineCommentUpdate={updateCommentInContext} - onLineCommentDelete={removeCommentFromContext} - lineCommentActions={reviewCommentActions()} - commentMentions={{ - items: file.searchFilesAndDirectories, - }} - comments={comments.all()} - focusedComment={comments.focus()} - onFocusedCommentChange={comments.setFocus} - onViewFile={openReviewFile} - classes={input.classes} - /> - + setTree("reviewScroll", el)} + focusedFile={tree.activeDiff} + onLineComment={(comment) => addCommentToContext({ ...comment, origin: "review" })} + onLineCommentUpdate={updateCommentInContext} + onLineCommentDelete={removeCommentFromContext} + lineCommentActions={reviewCommentActions()} + commentMentions={{ + items: file.searchFilesAndDirectories, + }} + comments={comments.all()} + focusedComment={comments.focus()} + onFocusedCommentChange={comments.setFocus} + onViewFile={openReviewFile} + classes={input.classes} + /> ) const reviewPanel = () => ( @@ -1658,7 +1645,7 @@ export default function Page() { const composerRegion = (placement: "dock" | "inline") => ( { @@ -1710,7 +1697,6 @@ export default function Page() { return (
- {sessionSync() ?? ""}
{ route.sessionKey() const ready = props.ready - const delay = 140 clear() setStore("ready", false) @@ -109,10 +108,7 @@ export function SessionComposerRegion(props: { frame = requestAnimationFrame(() => { frame = undefined - timer = window.setTimeout(() => { - setStore("ready", true) - timer = undefined - }, delay) + setStore("ready", true) }) })