summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAdam <[email protected]>2026-03-03 10:59:53 -0600
committerAdam <[email protected]>2026-03-03 11:00:06 -0600
commit9d427c1ef8b9b4111f2930b474e8aaa792a25a8d (patch)
tree5033a874a26605774141aa1f0517c9b401fb8f11
parent70c6fcfbbfd8d87d46f1a6b2d5d32e522ad8ba54 (diff)
downloadopencode-9d427c1ef8b9b4111f2930b474e8aaa792a25a8d.tar.gz
opencode-9d427c1ef8b9b4111f2930b474e8aaa792a25a8d.zip
fix(app): defer diff rendering
-rw-r--r--packages/app/src/pages/session.tsx151
1 files changed, 90 insertions, 61 deletions
diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx
index 2c49489ba..d71914dce 100644
--- a/packages/app/src/pages/session.tsx
+++ b/packages/app/src/pages/session.tsx
@@ -1,4 +1,16 @@
-import { onCleanup, Show, Match, Switch, createMemo, createEffect, on, onMount, untrack } from "solid-js"
+import {
+ onCleanup,
+ Show,
+ Match,
+ Switch,
+ createMemo,
+ createEffect,
+ createComputed,
+ on,
+ onMount,
+ untrack,
+ createSignal,
+} from "solid-js"
import { createMediaQuery } from "@solid-primitives/media"
import { createResizeObserver } from "@solid-primitives/resize-observer"
import { useLocal } from "@/context/local"
@@ -406,6 +418,18 @@ export default function Page() {
newSessionWorktree: "main",
})
+ const [deferRender, setDeferRender] = createSignal(false)
+ createComputed((prev) => {
+ const key = sessionKey()
+ if (key !== prev) {
+ setDeferRender(true)
+ requestAnimationFrame(() => {
+ setTimeout(() => setDeferRender(false), 0)
+ })
+ }
+ return key
+ }, sessionKey())
+
const turnDiffs = createMemo(() => lastUserMessage()?.summary?.diffs ?? [])
const reviewDiffs = createMemo(() => (store.changes === "session" ? diffs() : turnDiffs()))
@@ -712,35 +736,15 @@ export default function Page() {
loadingClass: string
emptyClass: string
}) => (
- <Switch>
- <Match when={store.changes === "turn" && !!params.id}>
- <SessionReviewTab
- title={changesTitle()}
- empty={emptyTurn()}
- diffs={reviewDiffs}
- view={view}
- diffStyle={input.diffStyle}
- onDiffStyleChange={input.onDiffStyleChange}
- onScrollRef={(el) => setTree("reviewScroll", el)}
- focusedFile={tree.activeDiff}
- onLineComment={(comment) => addCommentToContext({ ...comment, origin: "review" })}
- onLineCommentUpdate={updateCommentInContext}
- onLineCommentDelete={removeCommentFromContext}
- lineCommentActions={reviewCommentActions()}
- comments={comments.all()}
- focusedComment={comments.focus()}
- onFocusedCommentChange={comments.setFocus}
- onViewFile={openReviewFile}
- classes={input.classes}
- />
- </Match>
- <Match when={hasReview()}>
- <Show
- when={diffsReady()}
- fallback={<div class={input.loadingClass}>{language.t("session.review.loadingChanges")}</div>}
- >
+ <Show
+ when={!deferRender()}
+ fallback={<div class={input.loadingClass}>{language.t("session.review.loadingChanges")}</div>}
+ >
+ <Switch>
+ <Match when={store.changes === "turn" && !!params.id}>
<SessionReviewTab
title={changesTitle()}
+ empty={emptyTurn()}
diffs={reviewDiffs}
view={view}
diffStyle={input.diffStyle}
@@ -757,39 +761,64 @@ export default function Page() {
onViewFile={openReviewFile}
classes={input.classes}
/>
- </Show>
- </Match>
- <Match when={true}>
- <SessionReviewTab
- title={changesTitle()}
- empty={
- store.changes === "turn" ? (
- emptyTurn()
- ) : (
- <div class={input.emptyClass}>
- <Mark class="w-14 opacity-10" />
- <div class="text-14-regular text-text-weak max-w-56">{language.t(reviewEmptyKey())}</div>
- </div>
- )
- }
- diffs={reviewDiffs}
- view={view}
- diffStyle={input.diffStyle}
- onDiffStyleChange={input.onDiffStyleChange}
- onScrollRef={(el) => setTree("reviewScroll", el)}
- focusedFile={tree.activeDiff}
- onLineComment={(comment) => addCommentToContext({ ...comment, origin: "review" })}
- onLineCommentUpdate={updateCommentInContext}
- onLineCommentDelete={removeCommentFromContext}
- lineCommentActions={reviewCommentActions()}
- comments={comments.all()}
- focusedComment={comments.focus()}
- onFocusedCommentChange={comments.setFocus}
- onViewFile={openReviewFile}
- classes={input.classes}
- />
- </Match>
- </Switch>
+ </Match>
+ <Match when={hasReview()}>
+ <Show
+ when={diffsReady()}
+ fallback={<div class={input.loadingClass}>{language.t("session.review.loadingChanges")}</div>}
+ >
+ <SessionReviewTab
+ title={changesTitle()}
+ diffs={reviewDiffs}
+ view={view}
+ diffStyle={input.diffStyle}
+ onDiffStyleChange={input.onDiffStyleChange}
+ onScrollRef={(el) => setTree("reviewScroll", el)}
+ focusedFile={tree.activeDiff}
+ onLineComment={(comment) => addCommentToContext({ ...comment, origin: "review" })}
+ onLineCommentUpdate={updateCommentInContext}
+ onLineCommentDelete={removeCommentFromContext}
+ lineCommentActions={reviewCommentActions()}
+ comments={comments.all()}
+ focusedComment={comments.focus()}
+ onFocusedCommentChange={comments.setFocus}
+ onViewFile={openReviewFile}
+ classes={input.classes}
+ />
+ </Show>
+ </Match>
+ <Match when={true}>
+ <SessionReviewTab
+ title={changesTitle()}
+ empty={
+ store.changes === "turn" ? (
+ emptyTurn()
+ ) : (
+ <div class={input.emptyClass}>
+ <Mark class="w-14 opacity-10" />
+ <div class="text-14-regular text-text-weak max-w-56">{language.t(reviewEmptyKey())}</div>
+ </div>
+ )
+ }
+ diffs={reviewDiffs}
+ view={view}
+ diffStyle={input.diffStyle}
+ onDiffStyleChange={input.onDiffStyleChange}
+ onScrollRef={(el) => setTree("reviewScroll", el)}
+ focusedFile={tree.activeDiff}
+ onLineComment={(comment) => addCommentToContext({ ...comment, origin: "review" })}
+ onLineCommentUpdate={updateCommentInContext}
+ onLineCommentDelete={removeCommentFromContext}
+ lineCommentActions={reviewCommentActions()}
+ comments={comments.all()}
+ focusedComment={comments.focus()}
+ onFocusedCommentChange={comments.setFocus}
+ onViewFile={openReviewFile}
+ classes={input.classes}
+ />
+ </Match>
+ </Switch>
+ </Show>
)
const reviewPanel = () => (