fix(app): store terminal and review pane visibility per session
This commit is contained in:
@@ -15,6 +15,7 @@ export function DialogSelectFile() {
|
|||||||
const params = useParams()
|
const params = useParams()
|
||||||
const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`)
|
const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`)
|
||||||
const tabs = createMemo(() => layout.tabs(sessionKey()))
|
const tabs = createMemo(() => layout.tabs(sessionKey()))
|
||||||
|
const view = createMemo(() => layout.view(sessionKey()))
|
||||||
return (
|
return (
|
||||||
<Dialog title="Select file">
|
<Dialog title="Select file">
|
||||||
<List
|
<List
|
||||||
@@ -27,7 +28,7 @@ export function DialogSelectFile() {
|
|||||||
const value = file.tab(path)
|
const value = file.tab(path)
|
||||||
tabs().open(value)
|
tabs().open(value)
|
||||||
file.load(path)
|
file.load(path)
|
||||||
layout.review.open()
|
view().reviewPanel.open()
|
||||||
}
|
}
|
||||||
dialog.close()
|
dialog.close()
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export function SessionContextUsage(props: SessionContextUsageProps) {
|
|||||||
const variant = createMemo(() => props.variant ?? "button")
|
const variant = createMemo(() => props.variant ?? "button")
|
||||||
const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`)
|
const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`)
|
||||||
const tabs = createMemo(() => layout.tabs(sessionKey()))
|
const tabs = createMemo(() => layout.tabs(sessionKey()))
|
||||||
|
const view = createMemo(() => layout.view(sessionKey()))
|
||||||
const messages = createMemo(() => (params.id ? (sync.data.message[params.id] ?? []) : []))
|
const messages = createMemo(() => (params.id ? (sync.data.message[params.id] ?? []) : []))
|
||||||
|
|
||||||
const cost = createMemo(() => {
|
const cost = createMemo(() => {
|
||||||
@@ -48,7 +49,7 @@ export function SessionContextUsage(props: SessionContextUsageProps) {
|
|||||||
|
|
||||||
const openContext = () => {
|
const openContext = () => {
|
||||||
if (!params.id) return
|
if (!params.id) return
|
||||||
layout.review.open()
|
view().reviewPanel.open()
|
||||||
tabs().open("context")
|
tabs().open("context")
|
||||||
tabs().setActive("context")
|
tabs().setActive("context")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ export function SessionHeader() {
|
|||||||
})
|
})
|
||||||
const shareEnabled = createMemo(() => sync.data.config.share !== "disabled")
|
const shareEnabled = createMemo(() => sync.data.config.share !== "disabled")
|
||||||
const worktrees = createMemo(() => layout.projects.list().map((p) => p.worktree), [], { equals: same })
|
const worktrees = createMemo(() => layout.projects.list().map((p) => p.worktree), [], { equals: same })
|
||||||
|
const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`)
|
||||||
|
const view = createMemo(() => layout.view(sessionKey()))
|
||||||
|
|
||||||
function navigateToProject(directory: string) {
|
function navigateToProject(directory: string) {
|
||||||
navigate(`/${base64Encode(directory)}`)
|
navigate(`/${base64Encode(directory)}`)
|
||||||
@@ -171,20 +173,24 @@ export function SessionHeader() {
|
|||||||
title="Toggle review"
|
title="Toggle review"
|
||||||
keybind={command.keybind("review.toggle")}
|
keybind={command.keybind("review.toggle")}
|
||||||
>
|
>
|
||||||
<Button variant="ghost" class="group/review-toggle size-6 p-0" onClick={layout.review.toggle}>
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
class="group/review-toggle size-6 p-0"
|
||||||
|
onClick={() => view().reviewPanel.toggle()}
|
||||||
|
>
|
||||||
<div class="relative flex items-center justify-center size-4 [&>*]:absolute [&>*]:inset-0">
|
<div class="relative flex items-center justify-center size-4 [&>*]:absolute [&>*]:inset-0">
|
||||||
<Icon
|
<Icon
|
||||||
name={layout.review.opened() ? "layout-right" : "layout-left"}
|
name={view().reviewPanel.opened() ? "layout-right" : "layout-left"}
|
||||||
size="small"
|
size="small"
|
||||||
class="group-hover/review-toggle:hidden"
|
class="group-hover/review-toggle:hidden"
|
||||||
/>
|
/>
|
||||||
<Icon
|
<Icon
|
||||||
name={layout.review.opened() ? "layout-right-partial" : "layout-left-partial"}
|
name={view().reviewPanel.opened() ? "layout-right-partial" : "layout-left-partial"}
|
||||||
size="small"
|
size="small"
|
||||||
class="hidden group-hover/review-toggle:inline-block"
|
class="hidden group-hover/review-toggle:inline-block"
|
||||||
/>
|
/>
|
||||||
<Icon
|
<Icon
|
||||||
name={layout.review.opened() ? "layout-right-full" : "layout-left-full"}
|
name={view().reviewPanel.opened() ? "layout-right-full" : "layout-left-full"}
|
||||||
size="small"
|
size="small"
|
||||||
class="hidden group-active/review-toggle:inline-block"
|
class="hidden group-active/review-toggle:inline-block"
|
||||||
/>
|
/>
|
||||||
@@ -197,11 +203,11 @@ export function SessionHeader() {
|
|||||||
title="Toggle terminal"
|
title="Toggle terminal"
|
||||||
keybind={command.keybind("terminal.toggle")}
|
keybind={command.keybind("terminal.toggle")}
|
||||||
>
|
>
|
||||||
<Button variant="ghost" class="group/terminal-toggle size-6 p-0" onClick={layout.terminal.toggle}>
|
<Button variant="ghost" class="group/terminal-toggle size-6 p-0" onClick={() => view().terminal.toggle()}>
|
||||||
<div class="relative flex items-center justify-center size-4 [&>*]:absolute [&>*]:inset-0">
|
<div class="relative flex items-center justify-center size-4 [&>*]:absolute [&>*]:inset-0">
|
||||||
<Icon
|
<Icon
|
||||||
size="small"
|
size="small"
|
||||||
name={layout.terminal.opened() ? "layout-bottom-full" : "layout-bottom"}
|
name={view().terminal.opened() ? "layout-bottom-full" : "layout-bottom"}
|
||||||
class="group-hover/terminal-toggle:hidden"
|
class="group-hover/terminal-toggle:hidden"
|
||||||
/>
|
/>
|
||||||
<Icon
|
<Icon
|
||||||
@@ -211,7 +217,7 @@ export function SessionHeader() {
|
|||||||
/>
|
/>
|
||||||
<Icon
|
<Icon
|
||||||
size="small"
|
size="small"
|
||||||
name={layout.terminal.opened() ? "layout-bottom" : "layout-bottom-full"}
|
name={view().terminal.opened() ? "layout-bottom" : "layout-bottom-full"}
|
||||||
class="hidden group-active/terminal-toggle:inline-block"
|
class="hidden group-active/terminal-toggle:inline-block"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ type SessionTabs = {
|
|||||||
type SessionView = {
|
type SessionView = {
|
||||||
scroll: Record<string, SessionScroll>
|
scroll: Record<string, SessionScroll>
|
||||||
reviewOpen?: string[]
|
reviewOpen?: string[]
|
||||||
|
terminalOpened?: boolean
|
||||||
|
reviewPanelOpened?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type LocalProject = Partial<Project> & { worktree: string; expanded: boolean }
|
export type LocalProject = Partial<Project> & { worktree: string; expanded: boolean }
|
||||||
@@ -53,11 +55,9 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
|
|||||||
width: 280,
|
width: 280,
|
||||||
},
|
},
|
||||||
terminal: {
|
terminal: {
|
||||||
opened: false,
|
|
||||||
height: 280,
|
height: 280,
|
||||||
},
|
},
|
||||||
review: {
|
review: {
|
||||||
opened: true,
|
|
||||||
diffStyle: "split" as ReviewDiffStyle,
|
diffStyle: "split" as ReviewDiffStyle,
|
||||||
},
|
},
|
||||||
session: {
|
session: {
|
||||||
@@ -150,7 +150,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
|
|||||||
const current = store.sessionView[sessionKey]
|
const current = store.sessionView[sessionKey]
|
||||||
const keep = meta.active ?? sessionKey
|
const keep = meta.active ?? sessionKey
|
||||||
if (!current) {
|
if (!current) {
|
||||||
setStore("sessionView", sessionKey, { scroll: next })
|
setStore("sessionView", sessionKey, { scroll: next, terminalOpened: false, reviewPanelOpened: true })
|
||||||
prune(keep)
|
prune(keep)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -306,40 +306,20 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
terminal: {
|
terminal: {
|
||||||
opened: createMemo(() => store.terminal.opened),
|
|
||||||
open() {
|
|
||||||
setStore("terminal", "opened", true)
|
|
||||||
},
|
|
||||||
close() {
|
|
||||||
setStore("terminal", "opened", false)
|
|
||||||
},
|
|
||||||
toggle() {
|
|
||||||
setStore("terminal", "opened", (x) => !x)
|
|
||||||
},
|
|
||||||
height: createMemo(() => store.terminal.height),
|
height: createMemo(() => store.terminal.height),
|
||||||
resize(height: number) {
|
resize(height: number) {
|
||||||
setStore("terminal", "height", height)
|
setStore("terminal", "height", height)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
review: {
|
review: {
|
||||||
opened: createMemo(() => store.review?.opened ?? true),
|
|
||||||
diffStyle: createMemo(() => store.review?.diffStyle ?? "split"),
|
diffStyle: createMemo(() => store.review?.diffStyle ?? "split"),
|
||||||
setDiffStyle(diffStyle: ReviewDiffStyle) {
|
setDiffStyle(diffStyle: ReviewDiffStyle) {
|
||||||
if (!store.review) {
|
if (!store.review) {
|
||||||
setStore("review", { opened: true, diffStyle })
|
setStore("review", { diffStyle })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setStore("review", "diffStyle", diffStyle)
|
setStore("review", "diffStyle", diffStyle)
|
||||||
},
|
},
|
||||||
open() {
|
|
||||||
setStore("review", "opened", true)
|
|
||||||
},
|
|
||||||
close() {
|
|
||||||
setStore("review", "opened", false)
|
|
||||||
},
|
|
||||||
toggle() {
|
|
||||||
setStore("review", "opened", (x) => !x)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
session: {
|
session: {
|
||||||
width: createMemo(() => store.session?.width ?? 600),
|
width: createMemo(() => store.session?.width ?? 600),
|
||||||
@@ -367,6 +347,33 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
|
|||||||
touch(sessionKey)
|
touch(sessionKey)
|
||||||
scroll.seed(sessionKey)
|
scroll.seed(sessionKey)
|
||||||
const s = createMemo(() => store.sessionView[sessionKey] ?? { scroll: {} })
|
const s = createMemo(() => store.sessionView[sessionKey] ?? { scroll: {} })
|
||||||
|
const terminalOpened = createMemo(() => s().terminalOpened ?? false)
|
||||||
|
const reviewPanelOpened = createMemo(() => s().reviewPanelOpened ?? true)
|
||||||
|
|
||||||
|
function setTerminalOpened(next: boolean) {
|
||||||
|
const current = store.sessionView[sessionKey]
|
||||||
|
if (!current) {
|
||||||
|
setStore("sessionView", sessionKey, { scroll: {}, terminalOpened: next, reviewPanelOpened: true })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = current.terminalOpened ?? false
|
||||||
|
if (value === next) return
|
||||||
|
setStore("sessionView", sessionKey, "terminalOpened", next)
|
||||||
|
}
|
||||||
|
|
||||||
|
function setReviewPanelOpened(next: boolean) {
|
||||||
|
const current = store.sessionView[sessionKey]
|
||||||
|
if (!current) {
|
||||||
|
setStore("sessionView", sessionKey, { scroll: {}, terminalOpened: false, reviewPanelOpened: next })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = current.reviewPanelOpened ?? true
|
||||||
|
if (value === next) return
|
||||||
|
setStore("sessionView", sessionKey, "reviewPanelOpened", next)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
scroll(tab: string) {
|
scroll(tab: string) {
|
||||||
return scroll.scroll(sessionKey, tab)
|
return scroll.scroll(sessionKey, tab)
|
||||||
@@ -374,12 +381,41 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
|
|||||||
setScroll(tab: string, pos: SessionScroll) {
|
setScroll(tab: string, pos: SessionScroll) {
|
||||||
scroll.setScroll(sessionKey, tab, pos)
|
scroll.setScroll(sessionKey, tab, pos)
|
||||||
},
|
},
|
||||||
|
terminal: {
|
||||||
|
opened: terminalOpened,
|
||||||
|
open() {
|
||||||
|
setTerminalOpened(true)
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
setTerminalOpened(false)
|
||||||
|
},
|
||||||
|
toggle() {
|
||||||
|
setTerminalOpened(!terminalOpened())
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reviewPanel: {
|
||||||
|
opened: reviewPanelOpened,
|
||||||
|
open() {
|
||||||
|
setReviewPanelOpened(true)
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
setReviewPanelOpened(false)
|
||||||
|
},
|
||||||
|
toggle() {
|
||||||
|
setReviewPanelOpened(!reviewPanelOpened())
|
||||||
|
},
|
||||||
|
},
|
||||||
review: {
|
review: {
|
||||||
open: createMemo(() => s().reviewOpen),
|
open: createMemo(() => s().reviewOpen),
|
||||||
setOpen(open: string[]) {
|
setOpen(open: string[]) {
|
||||||
const current = store.sessionView[sessionKey]
|
const current = store.sessionView[sessionKey]
|
||||||
if (!current) {
|
if (!current) {
|
||||||
setStore("sessionView", sessionKey, { scroll: {}, reviewOpen: open })
|
setStore("sessionView", sessionKey, {
|
||||||
|
scroll: {},
|
||||||
|
terminalOpened: false,
|
||||||
|
reviewPanelOpened: true,
|
||||||
|
reviewOpen: open,
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -377,7 +377,7 @@ export default function Page() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
if (!layout.terminal.opened()) return
|
if (!view().terminal.opened()) return
|
||||||
if (!terminal.ready()) return
|
if (!terminal.ready()) return
|
||||||
if (terminal.all().length !== 0) return
|
if (terminal.all().length !== 0) return
|
||||||
terminal.new()
|
terminal.new()
|
||||||
@@ -440,7 +440,7 @@ export default function Page() {
|
|||||||
category: "View",
|
category: "View",
|
||||||
keybind: "ctrl+`",
|
keybind: "ctrl+`",
|
||||||
slash: "terminal",
|
slash: "terminal",
|
||||||
onSelect: () => layout.terminal.toggle(),
|
onSelect: () => view().terminal.toggle(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "review.toggle",
|
id: "review.toggle",
|
||||||
@@ -448,7 +448,7 @@ export default function Page() {
|
|||||||
description: "Show or hide the review panel",
|
description: "Show or hide the review panel",
|
||||||
category: "View",
|
category: "View",
|
||||||
keybind: "mod+shift+r",
|
keybind: "mod+shift+r",
|
||||||
onSelect: () => layout.review.toggle(),
|
onSelect: () => view().reviewPanel.toggle(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "terminal.new",
|
id: "terminal.new",
|
||||||
@@ -720,7 +720,9 @@ export default function Page() {
|
|||||||
const reviewTab = createMemo(() => hasReview() || tabs().active() === "review")
|
const reviewTab = createMemo(() => hasReview() || tabs().active() === "review")
|
||||||
const mobileReview = createMemo(() => !isDesktop() && hasReview() && store.mobileTab === "review")
|
const mobileReview = createMemo(() => !isDesktop() && hasReview() && store.mobileTab === "review")
|
||||||
|
|
||||||
const showTabs = createMemo(() => layout.review.opened() && (hasReview() || tabs().all().length > 0 || contextOpen()))
|
const showTabs = createMemo(
|
||||||
|
() => view().reviewPanel.opened() && (hasReview() || tabs().all().length > 0 || contextOpen()),
|
||||||
|
)
|
||||||
|
|
||||||
const activeTab = createMemo(() => {
|
const activeTab = createMemo(() => {
|
||||||
const active = tabs().active()
|
const active = tabs().active()
|
||||||
@@ -745,7 +747,7 @@ export default function Page() {
|
|||||||
if (!id) return
|
if (!id) return
|
||||||
if (!hasReview()) return
|
if (!hasReview()) return
|
||||||
|
|
||||||
const wants = isDesktop() ? layout.review.opened() && activeTab() === "review" : store.mobileTab === "review"
|
const wants = isDesktop() ? view().reviewPanel.opened() && activeTab() === "review" : store.mobileTab === "review"
|
||||||
if (!wants) return
|
if (!wants) return
|
||||||
if (diffsReady()) return
|
if (diffsReady()) return
|
||||||
|
|
||||||
@@ -1600,7 +1602,7 @@ export default function Page() {
|
|||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Show when={isDesktop() && layout.terminal.opened()}>
|
<Show when={isDesktop() && view().terminal.opened()}>
|
||||||
<div
|
<div
|
||||||
class="relative w-full flex-col shrink-0 border-t border-border-weak-base"
|
class="relative w-full flex-col shrink-0 border-t border-border-weak-base"
|
||||||
style={{ height: `${layout.terminal.height()}px` }}
|
style={{ height: `${layout.terminal.height()}px` }}
|
||||||
@@ -1612,7 +1614,7 @@ export default function Page() {
|
|||||||
max={window.innerHeight * 0.6}
|
max={window.innerHeight * 0.6}
|
||||||
collapseThreshold={50}
|
collapseThreshold={50}
|
||||||
onResize={layout.terminal.resize}
|
onResize={layout.terminal.resize}
|
||||||
onCollapse={layout.terminal.close}
|
onCollapse={view().terminal.close}
|
||||||
/>
|
/>
|
||||||
<Show
|
<Show
|
||||||
when={terminal.ready()}
|
when={terminal.ready()}
|
||||||
|
|||||||
Reference in New Issue
Block a user