diff options
| author | adamelmore <[email protected]> | 2026-01-28 10:26:55 -0600 |
|---|---|---|
| committer | adamelmore <[email protected]> | 2026-01-28 10:27:01 -0600 |
| commit | f607353be6b6ee70dcb4073c81cc0e0953998dc6 (patch) | |
| tree | 67b1bc8e8c3b42c86573efd1443357ebbd5fbfae /packages | |
| parent | af3c97f192913cd7ddc1f435370077f1f38db12b (diff) | |
| download | opencode-f607353be6b6ee70dcb4073c81cc0e0953998dc6.tar.gz opencode-f607353be6b6ee70dcb4073c81cc0e0953998dc6.zip | |
fix(app): close review pane
Diffstat (limited to 'packages')
| -rw-r--r-- | packages/app/src/components/dialog-select-file.tsx | 3 | ||||
| -rw-r--r-- | packages/app/src/components/prompt-input.tsx | 3 | ||||
| -rw-r--r-- | packages/app/src/components/session-context-usage.tsx | 1 | ||||
| -rw-r--r-- | packages/app/src/components/session/session-header.tsx | 9 | ||||
| -rw-r--r-- | packages/app/src/context/layout.tsx | 13 | ||||
| -rw-r--r-- | packages/app/src/pages/session.tsx | 95 |
6 files changed, 41 insertions, 83 deletions
diff --git a/packages/app/src/components/dialog-select-file.tsx b/packages/app/src/components/dialog-select-file.tsx index 5c58725c7..95478443e 100644 --- a/packages/app/src/components/dialog-select-file.tsx +++ b/packages/app/src/components/dialog-select-file.tsx @@ -44,7 +44,7 @@ export function DialogSelectFile(props: { mode?: DialogSelectFileMode; onOpenFil "session.previous", "session.next", "terminal.toggle", - "fileTree.toggle", + "review.toggle", ] const limit = 5 @@ -162,6 +162,7 @@ export function DialogSelectFile(props: { mode?: DialogSelectFileMode; onOpenFil const value = file.tab(path) tabs().open(value) file.load(path) + layout.fileTree.open() layout.fileTree.setTab("all") props.onOpenFile?.(path) } diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 84a695f3e..4d227f44b 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -189,12 +189,13 @@ export const PromptInput: Component<PromptInputProps> = (props) => { const wantsReview = item.commentOrigin === "review" || (item.commentOrigin !== "file" && commentInReview(item.path)) if (wantsReview) { + layout.fileTree.open() layout.fileTree.setTab("changes") - if (!layout.fileTree.opened()) tabs().open("review") requestAnimationFrame(() => comments.setFocus(focus)) return } + layout.fileTree.open() layout.fileTree.setTab("all") const tab = files.tab(item.path) tabs().open(tab) diff --git a/packages/app/src/components/session-context-usage.tsx b/packages/app/src/components/session-context-usage.tsx index afdb18bb0..1e37d8f6a 100644 --- a/packages/app/src/components/session-context-usage.tsx +++ b/packages/app/src/components/session-context-usage.tsx @@ -57,6 +57,7 @@ export function SessionContextUsage(props: SessionContextUsageProps) { const openContext = () => { if (!params.id) return + layout.fileTree.open() layout.fileTree.setTab("all") tabs().open("context") tabs().setActive("context") diff --git a/packages/app/src/components/session/session-header.tsx b/packages/app/src/components/session/session-header.tsx index 9fddb4507..d794fb5c6 100644 --- a/packages/app/src/components/session/session-header.tsx +++ b/packages/app/src/components/session/session-header.tsx @@ -280,17 +280,14 @@ export function SessionHeader() { </TooltipKeybind> </div> <div class="hidden md:block shrink-0"> - <TooltipKeybind - title={language.t("command.fileTree.toggle")} - keybind={command.keybind("fileTree.toggle")} - > + <TooltipKeybind title={language.t("command.review.toggle")} keybind={command.keybind("review.toggle")}> <Button variant="ghost" class="group/file-tree-toggle size-6 p-0" onClick={() => layout.fileTree.toggle()} - aria-label={language.t("command.fileTree.toggle")} + aria-label={language.t("command.review.toggle")} aria-expanded={layout.fileTree.opened()} - aria-controls="file-tree-panel" + aria-controls="review-panel" > <div class="relative flex items-center justify-center size-4 [&>*]:absolute [&>*]:inset-0"> <Icon diff --git a/packages/app/src/context/layout.tsx b/packages/app/src/context/layout.tsx index 2ea5f0435..d30fd11cf 100644 --- a/packages/app/src/context/layout.tsx +++ b/packages/app/src/context/layout.tsx @@ -624,10 +624,11 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( const tabs = createMemo(() => store.sessionTabs[key()] ?? { all: [] }) return { tabs, - active: createMemo(() => tabs().active), + active: createMemo(() => (tabs().active === "review" ? undefined : tabs().active)), all: createMemo(() => tabs().all.filter((tab) => tab !== "review")), setActive(tab: string | undefined) { const session = key() + if (tab === "review") return if (!store.sessionTabs[session]) { setStore("sessionTabs", session, { all: [], active: tab }) } else { @@ -644,18 +645,10 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( } }, async open(tab: string) { + if (tab === "review") return const session = key() const current = store.sessionTabs[session] ?? { all: [] } - if (tab === "review") { - if (!store.sessionTabs[session]) { - setStore("sessionTabs", session, { all: current.all, active: tab }) - return - } - setStore("sessionTabs", session, "active", tab) - return - } - if (tab === "context") { const all = [tab, ...current.all.filter((x) => x !== tab)] if (!store.sessionTabs[session]) { diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 7b4f31c50..87ebf6db7 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -23,7 +23,6 @@ import { IconButton } from "@opencode-ai/ui/icon-button" import { Button } from "@opencode-ai/ui/button" import { Icon } from "@opencode-ai/ui/icon" import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip" -import { DiffChanges } from "@opencode-ai/ui/diff-changes" import { ResizeHandle } from "@opencode-ai/ui/resize-handle" import { Tabs } from "@opencode-ai/ui/tabs" import { useCodeComponent } from "@opencode-ai/ui/context/code" @@ -325,6 +324,7 @@ export default function Page() { } const isDesktop = createMediaQuery("(min-width: 768px)") + const centered = createMemo(() => isDesktop() && !layout.fileTree.opened()) function normalizeTab(tab: string) { if (!tab.startsWith("file://")) return tab @@ -730,8 +730,8 @@ export default function Page() { onSelect: () => view().terminal.toggle(), }, { - id: "fileTree.toggle", - title: language.t("command.fileTree.toggle"), + id: "review.toggle", + title: language.t("command.review.toggle"), description: "", category: language.t("command.category.view"), keybind: "mod+shift+r", @@ -1097,12 +1097,11 @@ export default function Page() { }, 0) } - const reviewTab = createMemo(() => isDesktop() && !layout.fileTree.opened()) const contextOpen = createMemo(() => tabs().active() === "context" || tabs().all().includes("context")) const openedTabs = createMemo(() => tabs() .all() - .filter((tab) => tab !== "context" && tab !== "review"), + .filter((tab) => tab !== "context"), ) const mobileChanges = createMemo(() => !isDesktop() && store.mobileTab === "changes") @@ -1271,56 +1270,29 @@ export default function Page() { const activeTab = createMemo(() => { const active = tabs().active() if (active === "context") return "context" - if (active === "review" && reviewTab()) return "review" if (active && file.pathFromTab(active)) return normalizeTab(active) const first = openedTabs()[0] if (first) return first if (contextOpen()) return "context" - if (reviewTab() && hasReview()) return "review" return "empty" }) createEffect(() => { if (!layout.ready()) return if (tabs().active()) return - if (openedTabs().length === 0 && !contextOpen() && !(reviewTab() && hasReview())) return + if (openedTabs().length === 0 && !contextOpen()) return const next = activeTab() if (next === "empty") return tabs().setActive(next) }) - createEffect( - on( - () => layout.fileTree.opened(), - (opened, prev) => { - if (prev === undefined) return - if (!isDesktop()) return - - if (opened) { - const active = tabs().active() - const tab = active === "review" || (!active && hasReview()) ? "changes" : "all" - layout.fileTree.setTab(tab) - return - } - - if (fileTreeTab() !== "changes") return - tabs().setActive("review") - }, - { defer: true }, - ), - ) - createEffect(() => { const id = params.id if (!id) return - const wants = isDesktop() - ? layout.fileTree.opened() - ? fileTreeTab() === "changes" - : activeTab() === "review" - : store.mobileTab === "changes" + const wants = isDesktop() ? layout.fileTree.opened() && fileTreeTab() === "changes" : store.mobileTab === "changes" if (!wants) return if (sync.data.session_diff[id] !== undefined) return if (sync.status === "loading") return @@ -1789,10 +1761,11 @@ export default function Page() { <div classList={{ "@container relative shrink-0 flex flex-col min-h-0 h-full bg-background-stronger": true, - "flex-1 md:flex-none pt-6 md:pt-3": true, + "flex-1 pt-6 md:pt-3": true, + "md:flex-none": layout.fileTree.opened(), }} style={{ - width: isDesktop() ? `${layout.session.width()}px` : "100%", + width: isDesktop() && layout.fileTree.opened() ? `${layout.session.width()}px` : "100%", "--prompt-height": store.promptHeight ? `${store.promptHeight}px` : undefined, }} > @@ -1967,6 +1940,7 @@ export default function Page() { "sticky top-0 z-30 bg-background-stronger": true, "w-full": true, "px-4 md:px-6": true, + "md:max-w-200 md:mx-auto": centered(), }} > <div class="h-10 flex items-center gap-1"> @@ -1991,7 +1965,13 @@ export default function Page() { <div ref={autoScroll.contentRef} role="log" - class="flex flex-col gap-32 items-start justify-start w-full mt-0 pb-[calc(var(--prompt-height,8rem)+64px)] md:pb-[calc(var(--prompt-height,10rem)+64px)] transition-[margin]" + class="flex flex-col gap-32 items-start justify-start pb-[calc(var(--prompt-height,8rem)+64px)] md:pb-[calc(var(--prompt-height,10rem)+64px)] transition-[margin]" + classList={{ + "w-full": true, + "md:max-w-200 md:mx-auto": centered(), + "mt-0.5": centered(), + "mt-0": !centered(), + }} > <Show when={store.turnStart > 0}> <div class="w-full flex justify-center"> @@ -2039,7 +2019,10 @@ export default function Page() { <div id={anchor(message.id)} data-message-id={message.id} - class="min-w-0 w-full max-w-full" + classList={{ + "min-w-0 w-full max-w-full": true, + "md:max-w-200": centered(), + }} > <SessionTurn sessionID={params.id!} @@ -2092,7 +2075,12 @@ export default function Page() { ref={(el) => (promptDock = el)} class="absolute inset-x-0 bottom-0 pt-12 pb-4 flex flex-col justify-center items-center z-50 px-4 md:px-0 bg-gradient-to-t from-background-stronger via-background-stronger to-transparent pointer-events-none" > - <div class="w-full px-4 pointer-events-auto"> + <div + classList={{ + "w-full px-4 pointer-events-auto": true, + "md:max-w-200 md:mx-auto": centered(), + }} + > <Show when={request()} keyed> {(perm) => ( <div data-component="tool-part-wrapper" data-permission="true" class="mb-3"> @@ -2163,7 +2151,7 @@ export default function Page() { </div> </div> - <Show when={isDesktop()}> + <Show when={isDesktop() && layout.fileTree.opened()}> <ResizeHandle direction="horizontal" size={layout.session.width()} @@ -2175,7 +2163,7 @@ export default function Page() { </div> {/* Desktop side panel - hidden on mobile */} - <Show when={isDesktop()}> + <Show when={isDesktop() && layout.fileTree.opened()}> <aside id="review-panel" aria-label={language.t("session.panel.reviewAndFiles")} @@ -2183,7 +2171,7 @@ export default function Page() { > <div class="flex-1 min-w-0 h-full"> <Show - when={layout.fileTree.opened() && fileTreeTab() === "changes"} + when={fileTreeTab() === "changes"} fallback={ <DragDropProvider onDragStart={handleDragStart} @@ -2196,23 +2184,6 @@ export default function Page() { <Tabs value={activeTab()} onChange={openTab}> <div class="sticky top-0 shrink-0 flex"> <Tabs.List> - <Show when={reviewTab()}> - <Tabs.Trigger value="review" classes={{ button: "!pl-6" }}> - <div class="flex items-center gap-3"> - <Show when={hasReview() && diffsReady()}> - <DiffChanges changes={diffs()} variant="bars" /> - </Show> - <div class="flex items-center gap-1.5"> - <div>{language.t("session.tab.review")}</div> - <Show when={hasReview()}> - <div class="text-12-medium text-text-strong h-4 px-2 flex flex-col items-center justify-center rounded-full bg-surface-base"> - {reviewCount()} - </div> - </Show> - </div> - </div> - </Tabs.Trigger> - </Show> <Show when={contextOpen()}> <Tabs.Trigger value="context" @@ -2261,12 +2232,6 @@ export default function Page() { </Tabs.List> </div> - <Show when={reviewTab()}> - <Tabs.Content value="review" class="flex flex-col h-full overflow-hidden contain-strict"> - <Show when={activeTab() === "review"}>{reviewPanel()}</Show> - </Tabs.Content> - </Show> - <Tabs.Content value="empty" class="flex flex-col h-full overflow-hidden contain-strict"> <Show when={activeTab() === "empty"}> <div class="relative pt-2 flex-1 min-h-0 overflow-hidden"> |
