From afc1825cf5610a9455d8ab22a946c91f00a6db97 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Thu, 1 Jan 2026 20:04:46 -0600 Subject: wip(app): progress --- packages/app/src/pages/session.tsx | 95 +++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) (limited to 'packages/app/src/pages') diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index bf1d06c1d..23e9a273f 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -15,6 +15,7 @@ import { Tabs } from "@opencode-ai/ui/tabs" import { useCodeComponent } from "@opencode-ai/ui/context/code" import { SessionTurn } from "@opencode-ai/ui/session-turn" import { createAutoScroll } from "@opencode-ai/ui/hooks" +import { SessionReview } from "@opencode-ai/ui/session-review" import { SessionMessageRail } from "@opencode-ai/ui/session-message-rail" import { DragDropProvider, DragDropSensors, DragOverlay, SortableProvider, closestCenter } from "@thisbeyond/solid-dnd" @@ -31,6 +32,7 @@ import { DialogSelectMcp } from "@/components/dialog-select-mcp" import { useCommand } from "@/context/command" import { useNavigate, useParams } from "@solidjs/router" import { UserMessage } from "@opencode-ai/sdk/v2" +import type { FileDiff } from "@opencode-ai/sdk/v2/client" import { useSDK } from "@/context/sdk" import { usePrompt } from "@/context/prompt" import { extractPromptFromParts } from "@/utils/prompt" @@ -40,7 +42,6 @@ import { showToast } from "@opencode-ai/ui/toast" import { SessionHeader, SessionContextTab, - SessionReviewTab, SortableTab, FileVisual, SortableTerminalTab, @@ -53,6 +54,90 @@ function same(a: readonly T[], b: readonly T[]) { return a.every((x, i) => x === b[i]) } +type DiffStyle = "unified" | "split" + +interface SessionReviewTabProps { + diffs: () => FileDiff[] + view: () => ReturnType["view"]> + diffStyle: DiffStyle + onDiffStyleChange?: (style: DiffStyle) => void + classes?: { + root?: string + header?: string + container?: string + } +} + +function SessionReviewTab(props: SessionReviewTabProps) { + let scroll: HTMLDivElement | undefined + let frame: number | undefined + let pending: { x: number; y: number } | undefined + + const restoreScroll = () => { + const el = scroll + if (!el) return + + const s = props.view().scroll("review") + if (!s) return + + if (el.scrollTop !== s.y) el.scrollTop = s.y + if (el.scrollLeft !== s.x) el.scrollLeft = s.x + } + + const handleScroll = (event: Event & { currentTarget: HTMLDivElement }) => { + pending = { + x: event.currentTarget.scrollLeft, + y: event.currentTarget.scrollTop, + } + if (frame !== undefined) return + + frame = requestAnimationFrame(() => { + frame = undefined + + const next = pending + pending = undefined + if (!next) return + + props.view().setScroll("review", next) + }) + } + + createEffect( + on( + () => props.diffs().length, + () => { + requestAnimationFrame(restoreScroll) + }, + { defer: true }, + ), + ) + + onCleanup(() => { + if (frame === undefined) return + cancelAnimationFrame(frame) + }) + + return ( + { + scroll = el + restoreScroll() + }} + onScroll={handleScroll} + open={props.view().review.open()} + onOpenChange={props.view().review.setOpen} + classes={{ + root: props.classes?.root ?? "pb-40", + header: props.classes?.header ?? "px-6", + container: props.classes?.container ?? "px-6", + }} + diffs={props.diffs()} + diffStyle={props.diffStyle} + onDiffStyleChange={props.onDiffStyleChange} + /> + ) +} + export default function Page() { const layout = useLayout() const local = useLocal() @@ -829,6 +914,7 @@ export default function Page() {
- +
-- cgit v1.2.3