diff options
| author | Adam <[email protected]> | 2026-02-05 13:51:08 -0600 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-02-05 13:51:08 -0600 |
| commit | 83646e0366c47a3bccb5135d40628176a6776f33 (patch) | |
| tree | cd8525d1a684a659e31a4413301577fac3f8fb63 /packages/app/src/pages | |
| parent | c40ce47e92befbe4cb27735e4d870f540e75b646 (diff) | |
| download | opencode-83646e0366c47a3bccb5135d40628176a6776f33.tar.gz opencode-83646e0366c47a3bccb5135d40628176a6776f33.zip | |
fix(app): allow toggling file tree closed independently (#12293)
Diffstat (limited to 'packages/app/src/pages')
| -rw-r--r-- | packages/app/src/pages/session.tsx | 93 |
1 files changed, 83 insertions, 10 deletions
diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 0bdf5f7f3..b0b955ed1 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -395,7 +395,7 @@ export default function Page() { } const isDesktop = createMediaQuery("(min-width: 768px)") - const centered = createMemo(() => isDesktop() && !layout.fileTree.opened()) + const centered = createMemo(() => isDesktop() && !view().reviewPanel.opened()) function normalizeTab(tab: string) { if (!tab.startsWith("file://")) return tab @@ -1043,7 +1043,18 @@ export default function Page() { description: "", category: language.t("command.category.view"), keybind: "mod+shift+r", - onSelect: () => layout.fileTree.toggle(), + onSelect: () => view().reviewPanel.toggle(), + }, + { + id: "fileTree.toggle", + title: language.t("command.fileTree.toggle"), + description: "", + category: language.t("command.category.view"), + onSelect: () => { + const opening = !layout.fileTree.opened() + if (opening && !view().reviewPanel.opened()) view().reviewPanel.open() + layout.fileTree.toggle() + }, }, { id: "terminal.new", @@ -1409,10 +1420,11 @@ export default function Page() { const openedTabs = createMemo(() => tabs() .all() - .filter((tab) => tab !== "context"), + .filter((tab) => tab !== "context" && tab !== "review"), ) const mobileChanges = createMemo(() => !isDesktop() && store.mobileTab === "changes") + const reviewTab = createMemo(() => isDesktop() && !layout.fileTree.opened()) const fileTreeTab = () => layout.fileTree.tab() const setFileTreeTab = (value: "changes" | "all") => layout.fileTree.setTab(value) @@ -1627,29 +1639,71 @@ 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()) return + if (openedTabs().length === 0 && !contextOpen() && !(reviewTab() && hasReview())) 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(() => { + if (!isDesktop()) return + if (!layout.fileTree.opened()) return + if (fileTreeTab() !== "all") return + + const active = tabs().active() + if (active && active !== "review") return + + const first = openedTabs()[0] + if (first) { + tabs().setActive(first) + return + } + + if (contextOpen()) tabs().setActive("context") + }) + createEffect(() => { const id = params.id if (!id) return - const wants = isDesktop() ? layout.fileTree.opened() : store.mobileTab === "changes" + const wants = isDesktop() + ? view().reviewPanel.opened() && (layout.fileTree.opened() || activeTab() === "review") + : store.mobileTab === "changes" if (!wants) return if (sync.data.session_diff[id] !== undefined) return if (sync.status === "loading") return @@ -1661,6 +1715,7 @@ export default function Page() { createEffect(() => { const dir = sdk.directory if (!isDesktop()) return + if (!view().reviewPanel.opened()) return if (!layout.fileTree.opened()) return if (sync.status === "loading") return @@ -2195,10 +2250,10 @@ export default function Page() { classList={{ "@container relative shrink-0 flex flex-col min-h-0 h-full bg-background-stronger": true, "flex-1 pt-2 md:pt-3": true, - "md:flex-none": layout.fileTree.opened(), + "md:flex-none": view().reviewPanel.opened(), }} style={{ - width: isDesktop() && layout.fileTree.opened() ? `${layout.session.width()}px` : "100%", + width: isDesktop() && view().reviewPanel.opened() ? `${layout.session.width()}px` : "100%", "--prompt-height": store.promptHeight ? `${store.promptHeight}px` : undefined, }} > @@ -2711,7 +2766,7 @@ export default function Page() { </div> </div> - <Show when={isDesktop() && layout.fileTree.opened()}> + <Show when={isDesktop() && view().reviewPanel.opened()}> <ResizeHandle direction="horizontal" size={layout.session.width()} @@ -2723,7 +2778,7 @@ export default function Page() { </div> {/* Desktop side panel - hidden on mobile */} - <Show when={isDesktop() && layout.fileTree.opened()}> + <Show when={isDesktop() && view().reviewPanel.opened()}> <aside id="review-panel" aria-label={language.t("session.panel.reviewAndFiles")} @@ -2731,7 +2786,7 @@ export default function Page() { > <div class="flex-1 min-w-0 h-full"> <Show - when={fileTreeTab() === "changes"} + when={layout.fileTree.opened() && fileTreeTab() === "changes"} fallback={ <DragDropProvider onDragStart={handleDragStart} @@ -2799,6 +2854,18 @@ export default function Page() { }) }} > + <Show when={reviewTab()}> + <Tabs.Trigger value="review" classes={{ button: "!pl-6" }}> + <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> + </Tabs.Trigger> + </Show> <Show when={contextOpen()}> <Tabs.Trigger value="context" @@ -2847,6 +2914,12 @@ 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"> |
