fix(app): allow toggling file tree closed independently (#12293)
This commit is contained in:
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user