From a2cbbd3b36de4ace39feb31760c86ae93a4e150e Mon Sep 17 00:00:00 2001 From: Aarav Sareen <96787824+arvsrn@users.noreply.github.com> Date: Mon, 13 Jul 2026 22:52:19 +0530 Subject: [PATCH 1/2] review panel improvements --- packages/app/src/pages/session.tsx | 7 +- packages/app/src/pages/session/file-tabs.tsx | 135 ++++++++++++++---- .../src/pages/session/session-side-panel.tsx | 22 ++- .../session/v2/session-file-browser-tab.tsx | 15 +- .../src/v2/components/session-review-v2.css | 10 +- 5 files changed, 146 insertions(+), 43 deletions(-) diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 7ce4627135ec..bdc9c9fc7c8c 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -653,7 +653,7 @@ export default function Page() { const mobileChanges = createMemo(() => !isDesktop() && store.mobileTab === "changes") const wantsReview = createMemo(() => isDesktop() - ? desktopFileTreeOpen() || (desktopReviewOpen() && activeTab() === "review") + ? desktopFileTreeOpen() || (desktopReviewOpen() && (activeTab() === "review" || !!activeFileTab())) : store.mobileTab === "changes", ) const vcsMode = createMemo(() => { @@ -2281,6 +2281,8 @@ export default function Page() { reviewHasFocusableContent={hasReview} reviewCount={reviewCount} reviewPanel={reviewPanel} + diffVersion={vcsQuery.dataUpdatedAt} + loadDiff={loadReviewDiff} activeDiff={activeReviewFile()} focusReviewDiff={focusReviewDiff} reviewSnap={ui.reviewSnap} @@ -2301,6 +2303,9 @@ export default function Page() { reviewHasFocusableContent={() => hasReview() || reviewV2State.sidebarOpened()} reviewCount={reviewCount} reviewPanel={reviewPanelV2} + diffVersion={vcsQuery.dataUpdatedAt} + loadDiff={loadReviewDiff} + expandUnchanged={reviewV2State.expandMode() === "expand"} reviewSidebarToggle={(disabled) => ( Promise + expandUnchanged?: boolean +} + +const selectionSide = (range: SelectedLineRange) => range.endSide ?? range.side ?? "additions" function FileCommentMenu(props: { moreLabel: string @@ -199,28 +212,52 @@ function createScrollSync(input: { tab: () => string; view: ReturnType - + ) } -export function SessionFileView(props: { tab: string }) { +export function SessionFileView(props: SessionFileViewProps) { const settings = useSettings() + const detailSource = createMemo(() => { + if (!props.diff || !props.loadDiff || !reviewDiffNeedsLoad(props.diff)) return + return { diff: props.diff, load: props.loadDiff, version: props.diffVersion } + }) + const [loadedDiff] = createResource(detailSource, async ({ diff, load, version }) => { + const value = await load(diff.file, version) + if (value?.file !== diff.file) return + return { source: diff, version, value } + }) + const diff = createMemo(() => { + const source = props.diff + if (!source) return + const loaded = loadedDiff() + return normalize(loaded?.source === source && loaded.version === props.diffVersion ? loaded.value : source) + }) + return ( - }> - + } + > + ) } -function SessionFileViewV1(props: { tab: string }) { +function SessionFileViewV1(props: { + tab: string + diff?: ReturnType + expandUnchanged?: boolean +}) { const file = useFile() const comments = useComments() const language = useLanguage() const prompt = usePrompt() + const layout = useLayout() const fileComponent = useFileComponent() const { sessionKey, tabs, view } = useSessionLayout() const activeFileTab = createSessionTabs({ @@ -263,10 +300,15 @@ function SessionFileViewV1(props: { tab: string }) { }) } - const buildPreview = (filePath: string, selection: FileSelection) => { - const source = filePath === path() ? contents() : file.get(filePath)?.content?.content + const buildPreview = (filePath: string, lines: SelectedLineRange) => { + const source = + filePath === path() + ? props.diff + ? text(props.diff, selectionSide(lines)) + : contents() + : file.get(filePath)?.content?.content if (!source) return undefined - return selectionPreview(source, selection) + return selectionPreview(source, selectionFromLines(lines)) } const addCommentToContext = (input: { @@ -277,7 +319,7 @@ function SessionFileViewV1(props: { tab: string }) { origin?: "review" | "file" }) => { const selection = selectionFromLines(input.selection) - const preview = input.preview ?? buildPreview(input.file, selection) + const preview = input.preview ?? buildPreview(input.file, input.selection) const saved = comments.add({ file: input.file, @@ -302,7 +344,7 @@ function SessionFileViewV1(props: { tab: string }) { comment: string }) => { comments.update(input.file, input.id, input.comment) - const preview = input.file === path() ? buildPreview(input.file, selectionFromLines(input.selection)) : undefined + const preview = input.file === path() ? buildPreview(input.file, input.selection) : undefined prompt.context.updateComment(input.file, input.id, { comment: input.comment, ...(preview ? { preview } : {}), @@ -343,6 +385,7 @@ function SessionFileViewV1(props: { tab: string }) { mention: { items: file.searchFilesAndDirectories, }, + getSide: selectionSide, state: { opened: () => note.openedComment, setOpened: (id) => setNote("openedComment", id), @@ -443,12 +486,21 @@ function SessionFileViewV1(props: { tab: string }) {
+ {renderFile(contents())} {renderFile(contents())}
{language.t("common.loading")}...
@@ -501,11 +554,16 @@ function SessionFileViewV1(props: { tab: string }) { return content() } -function SessionFileViewV2(props: { tab: string }) { +function SessionFileViewV2(props: { + tab: string + diff?: ReturnType + expandUnchanged?: boolean +}) { const file = useFile() const comments = useComments() const language = useLanguage() const prompt = usePrompt() + const layout = useLayout() const fileComponent = useFileComponent() const { sessionKey, tabs, view } = useSessionLayout() const activeFileTab = createSessionTabs({ @@ -548,10 +606,15 @@ function SessionFileViewV2(props: { tab: string }) { }) } - const buildPreview = (filePath: string, selection: FileSelection) => { - const source = filePath === path() ? contents() : file.get(filePath)?.content?.content + const buildPreview = (filePath: string, lines: SelectedLineRange) => { + const source = + filePath === path() + ? props.diff + ? text(props.diff, selectionSide(lines)) + : contents() + : file.get(filePath)?.content?.content if (!source) return undefined - return selectionPreview(source, selection) + return selectionPreview(source, selectionFromLines(lines)) } const addCommentToContext = (input: { @@ -562,7 +625,7 @@ function SessionFileViewV2(props: { tab: string }) { origin?: "review" | "file" }) => { const selection = selectionFromLines(input.selection) - const preview = input.preview ?? buildPreview(input.file, selection) + const preview = input.preview ?? buildPreview(input.file, input.selection) const saved = comments.add({ file: input.file, @@ -587,7 +650,7 @@ function SessionFileViewV2(props: { tab: string }) { comment: string }) => { comments.update(input.file, input.id, input.comment) - const preview = input.file === path() ? buildPreview(input.file, selectionFromLines(input.selection)) : undefined + const preview = input.file === path() ? buildPreview(input.file, input.selection) : undefined prompt.context.updateComment(input.file, input.id, { comment: input.comment, ...(preview ? { preview } : {}), @@ -628,7 +691,7 @@ function SessionFileViewV2(props: { tab: string }) { mention: { items: file.searchFilesAndDirectories, }, - getSide: (range) => range.endSide ?? range.side ?? "additions", + getSide: selectionSide, state: { opened: () => note.openedComment, setOpened: (id) => setNote("openedComment", id), @@ -726,12 +789,21 @@ function SessionFileViewV2(props: { tab: string }) {
+ {renderFile(contents())} {renderFile(contents())}
{language.t("common.loading")}...
diff --git a/packages/app/src/pages/session/session-side-panel.tsx b/packages/app/src/pages/session/session-side-panel.tsx index 184fa684ecc5..10916c8b119e 100644 --- a/packages/app/src/pages/session/session-side-panel.tsx +++ b/packages/app/src/pages/session/session-side-panel.tsx @@ -71,6 +71,9 @@ export function SessionSidePanel(props: { reviewHasFocusableContent: () => boolean reviewCount: () => number reviewPanel: () => JSX.Element + diffVersion?: number + loadDiff?: (path: string, version?: number) => Promise + expandUnchanged?: boolean reviewSidebarToggle?: (disabled: boolean) => JSX.Element fileBrowserState?: SessionFileBrowserState activeDiff?: string @@ -88,6 +91,11 @@ export function SessionSidePanel(props: { const sdk = useSDK() const { sessionKey, tabs, view, params } = useSessionLayout() const projectDirectory = createMemo(() => sdk().directory) + const diffForTab = (tab: string) => { + const path = file.pathFromTab(tab) + if (!path) return + return props.diffs().find((diff): diff is RenderDiff => renderDiff(diff) && diff.file === path) + } const isDesktop = createMediaQuery("(min-width: 768px)") const shown = settings.visibility.fileTree @@ -494,7 +502,15 @@ export function SessionSidePanel(props: { - {(tab) => } + {(tab) => ( + + )} @@ -726,6 +742,10 @@ export function SessionSidePanel(props: { active={file.pathFromTab(browserTab() ?? activeFileTab() ?? "")} kinds={kinds()} state={props.fileBrowserState!} + diff={diffForTab(browserTab() ?? activeFileTab() ?? "")} + diffVersion={props.diffVersion} + loadDiff={props.loadDiff} + expandUnchanged={props.expandUnchanged} onSelect={(path) => previewTab(file.tab(path))} onSelectPermanent={(path) => openTab(file.tab(path))} filterRef={(element) => (fileFilter = element)} diff --git a/packages/app/src/pages/session/v2/session-file-browser-tab.tsx b/packages/app/src/pages/session/v2/session-file-browser-tab.tsx index 04ad1e3c8253..64b626cba893 100644 --- a/packages/app/src/pages/session/v2/session-file-browser-tab.tsx +++ b/packages/app/src/pages/session/v2/session-file-browser-tab.tsx @@ -11,6 +11,7 @@ import { useSDK } from "@/context/sdk" import { displayName } from "@/pages/layout/helpers" import { useSessionLayout } from "@/pages/session/session-layout" import { SessionFileView } from "@/pages/session/file-tabs" +import type { RenderDiff } from "@/pages/session/v2/review-diff-kinds" import { applyFileListKeyDown, SessionFileListV2 } from "@/pages/session/v2/session-file-list-v2" import { pathKey } from "@/utils/path-key" @@ -29,6 +30,10 @@ export function SessionFileBrowserTab(props: { active?: string kinds: ReadonlyMap state: SessionFileBrowserState + diff?: RenderDiff + diffVersion?: number + loadDiff?: (path: string, version?: number) => Promise + expandUnchanged?: boolean onSelect: (path: string) => void onSelectPermanent: (path: string) => void filterRef?: (element: HTMLInputElement) => void @@ -170,7 +175,15 @@ export function SessionFileBrowserTab(props: { >
- {(tab) => } + {(tab) => ( + + )}
diff --git a/packages/session-ui/src/v2/components/session-review-v2.css b/packages/session-ui/src/v2/components/session-review-v2.css index 9db2ba580c33..64f5ca5ece37 100644 --- a/packages/session-ui/src/v2/components/session-review-v2.css +++ b/packages/session-ui/src/v2/components/session-review-v2.css @@ -242,15 +242,7 @@ color: var(--v2-icon-icon-base); } -[data-component="icon-button-v2"][data-variant="ghost"].session-review-v2-sidebar-toggle[aria-expanded="true"]:not( - :disabled - ), -[data-component="icon-button-v2"][data-variant="ghost"].session-review-v2-sidebar-toggle[aria-expanded="true"]:is( - :hover, - [data-state="hover"], - :active, - [data-state="pressed"] - ):not(:disabled) { +[data-component="icon-button-v2"][data-variant="ghost"].session-review-v2-sidebar-toggle[aria-expanded="true"] { background-color: var(--v2-overlay-simple-overlay-pressed); } From fb445704b101510b3f06345058b288b41ea759c0 Mon Sep 17 00:00:00 2001 From: Aarav Sareen <96787824+arvsrn@users.noreply.github.com> Date: Mon, 13 Jul 2026 23:01:51 +0530 Subject: [PATCH 2/2] cleanup --- packages/app/src/pages/session.tsx | 5 +- packages/app/src/pages/session/file-tabs.tsx | 54 ++++++------------- .../src/pages/session/session-side-panel.tsx | 10 +--- 3 files changed, 18 insertions(+), 51 deletions(-) diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index bdc9c9fc7c8c..e917450e5d18 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -653,7 +653,8 @@ export default function Page() { const mobileChanges = createMemo(() => !isDesktop() && store.mobileTab === "changes") const wantsReview = createMemo(() => isDesktop() - ? desktopFileTreeOpen() || (desktopReviewOpen() && (activeTab() === "review" || !!activeFileTab())) + ? desktopFileTreeOpen() || + (desktopReviewOpen() && (activeTab() === "review" || (newSessionDesign() && !!activeFileTab()))) : store.mobileTab === "changes", ) const vcsMode = createMemo(() => { @@ -2281,8 +2282,6 @@ export default function Page() { reviewHasFocusableContent={hasReview} reviewCount={reviewCount} reviewPanel={reviewPanel} - diffVersion={vcsQuery.dataUpdatedAt} - loadDiff={loadReviewDiff} activeDiff={activeReviewFile()} focusReviewDiff={focusReviewDiff} reviewSnap={ui.reviewSnap} diff --git a/packages/app/src/pages/session/file-tabs.tsx b/packages/app/src/pages/session/file-tabs.tsx index 13a46d5d4a33..c3cc4301ee47 100644 --- a/packages/app/src/pages/session/file-tabs.tsx +++ b/packages/app/src/pages/session/file-tabs.tsx @@ -212,10 +212,10 @@ function createScrollSync(input: { tab: () => string; view: ReturnType - + ) } @@ -239,25 +239,17 @@ export function SessionFileView(props: SessionFileViewProps) { }) return ( - } - > + }> ) } -function SessionFileViewV1(props: { - tab: string - diff?: ReturnType - expandUnchanged?: boolean -}) { +function SessionFileViewV1(props: { tab: string }) { const file = useFile() const comments = useComments() const language = useLanguage() const prompt = usePrompt() - const layout = useLayout() const fileComponent = useFileComponent() const { sessionKey, tabs, view } = useSessionLayout() const activeFileTab = createSessionTabs({ @@ -300,15 +292,10 @@ function SessionFileViewV1(props: { }) } - const buildPreview = (filePath: string, lines: SelectedLineRange) => { - const source = - filePath === path() - ? props.diff - ? text(props.diff, selectionSide(lines)) - : contents() - : file.get(filePath)?.content?.content + const buildPreview = (filePath: string, selection: FileSelection) => { + const source = filePath === path() ? contents() : file.get(filePath)?.content?.content if (!source) return undefined - return selectionPreview(source, selectionFromLines(lines)) + return selectionPreview(source, selection) } const addCommentToContext = (input: { @@ -319,7 +306,7 @@ function SessionFileViewV1(props: { origin?: "review" | "file" }) => { const selection = selectionFromLines(input.selection) - const preview = input.preview ?? buildPreview(input.file, input.selection) + const preview = input.preview ?? buildPreview(input.file, selection) const saved = comments.add({ file: input.file, @@ -344,7 +331,7 @@ function SessionFileViewV1(props: { comment: string }) => { comments.update(input.file, input.id, input.comment) - const preview = input.file === path() ? buildPreview(input.file, input.selection) : undefined + const preview = input.file === path() ? buildPreview(input.file, selectionFromLines(input.selection)) : undefined prompt.context.updateComment(input.file, input.id, { comment: input.comment, ...(preview ? { preview } : {}), @@ -385,7 +372,6 @@ function SessionFileViewV1(props: { mention: { items: file.searchFilesAndDirectories, }, - getSide: selectionSide, state: { opened: () => note.openedComment, setOpened: (id) => setNote("openedComment", id), @@ -486,21 +472,12 @@ function SessionFileViewV1(props: {
- {renderFile(contents())} {renderFile(contents())}
{language.t("common.loading")}...
diff --git a/packages/app/src/pages/session/session-side-panel.tsx b/packages/app/src/pages/session/session-side-panel.tsx index 10916c8b119e..8d745e751c02 100644 --- a/packages/app/src/pages/session/session-side-panel.tsx +++ b/packages/app/src/pages/session/session-side-panel.tsx @@ -502,15 +502,7 @@ export function SessionSidePanel(props: { - {(tab) => ( - - )} + {(tab) => }