fix(tui): keep closed tabs closed
This commit is contained in:
parent
3f30203b72
commit
74e7137c10
2 changed files with 57 additions and 14 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import { createEffect, createMemo, createSignal, onCleanup } from "solid-js"
|
import { createEffect, createMemo, createSignal, on, onCleanup } from "solid-js"
|
||||||
import { isDeepEqual } from "remeda"
|
import { isDeepEqual } from "remeda"
|
||||||
import { createSimpleContext } from "./helper"
|
import { createSimpleContext } from "./helper"
|
||||||
import { useClient } from "./client"
|
import { useClient } from "./client"
|
||||||
|
|
@ -126,17 +126,18 @@ export const { use: useSessionTabs, provider: SessionTabsProvider } = createSimp
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(
|
||||||
if (!enabled()) return
|
on(
|
||||||
if (route.data.type !== "session" || route.data.sessionID === "dummy") return
|
[
|
||||||
const sessionID = root(route.data.sessionID)
|
() => (enabled() && route.data.type === "session" ? route.data.sessionID : undefined),
|
||||||
|
() => config.tabs?.scope,
|
||||||
|
() => paths.cwd,
|
||||||
|
],
|
||||||
|
([routed]) => {
|
||||||
|
if (!routed || routed === "dummy") return
|
||||||
|
const sessionID = root(routed)
|
||||||
history = recordSessionTabHistory(history, sessionID)
|
history = recordSessionTabHistory(history, sessionID)
|
||||||
const fallback = newTab() ? NEW_SESSION_TAB_TITLE : undefined
|
const fallback = newTab() ? NEW_SESSION_TAB_TITLE : undefined
|
||||||
const tabs = openSessionTab(state().tabs, {
|
|
||||||
sessionID,
|
|
||||||
title: title(sessionID, state().tabs.find((tab) => tab.sessionID === sessionID)?.title, fallback),
|
|
||||||
})
|
|
||||||
if (tabs === state().tabs && !state().unread[sessionID]) return
|
|
||||||
update((draft) => {
|
update((draft) => {
|
||||||
draft.tabs = openSessionTab(draft.tabs, {
|
draft.tabs = openSessionTab(draft.tabs, {
|
||||||
sessionID,
|
sessionID,
|
||||||
|
|
@ -144,6 +145,23 @@ export const { use: useSessionTabs, provider: SessionTabsProvider } = createSimp
|
||||||
})
|
})
|
||||||
delete draft.unread[sessionID]
|
delete draft.unread[sessionID]
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
if (!enabled() || route.data.type !== "session" || route.data.sessionID === "dummy") return
|
||||||
|
const sessionID = root(route.data.sessionID)
|
||||||
|
const tab = state().tabs.find((tab) => tab.sessionID === sessionID)
|
||||||
|
if (!tab) return
|
||||||
|
const nextTitle = title(sessionID, tab.title)
|
||||||
|
if ((!nextTitle || nextTitle === tab.title) && !state().unread[sessionID]) return
|
||||||
|
update((draft) => {
|
||||||
|
const tab = draft.tabs.find((tab) => tab.sessionID === sessionID)
|
||||||
|
if (!tab) return
|
||||||
|
draft.tabs = openSessionTab(draft.tabs, { sessionID, title: title(sessionID, tab.title) })
|
||||||
|
delete draft.unread[sessionID]
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,31 @@ test("concurrent TUIs do not alternate shared tab titles from divergent session
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("closing a tab is not undone by another TUI viewing the same session", async () => {
|
||||||
|
const state = stateDir("opencode-session-tabs-shared-close-")
|
||||||
|
const first = await renderSessionTabs("shared", { state })
|
||||||
|
const second = await renderSessionTabs("shared", { state })
|
||||||
|
|
||||||
|
try {
|
||||||
|
await wait(() => first.tabs.tabs().some((tab) => tab.sessionID === "shared"))
|
||||||
|
await wait(() => second.tabs.tabs().some((tab) => tab.sessionID === "shared"))
|
||||||
|
first.tabs.close()
|
||||||
|
await wait(() => first.route.data.type === "home")
|
||||||
|
await wait(() => !second.tabs.tabs().some((tab) => tab.sessionID === "shared"))
|
||||||
|
await Bun.sleep(50)
|
||||||
|
|
||||||
|
expect(first.tabs.tabs().some((tab) => tab.sessionID === "shared")).toBe(false)
|
||||||
|
|
||||||
|
second.route.navigate({ type: "home" })
|
||||||
|
await wait(() => second.route.data.type === "home")
|
||||||
|
second.route.navigate({ type: "session", sessionID: "shared" })
|
||||||
|
await wait(() => first.tabs.tabs().some((tab) => tab.sessionID === "shared"))
|
||||||
|
} finally {
|
||||||
|
first.destroy()
|
||||||
|
second.destroy()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
test("user prompt admissions pulse an already-busy background tab", async () => {
|
test("user prompt admissions pulse an already-busy background tab", async () => {
|
||||||
const setup = await renderSessionTabs("background")
|
const setup = await renderSessionTabs("background")
|
||||||
const admitted = (sessionID: string, inputID: string): OpenCodeEvent => ({
|
const admitted = (sessionID: string, inputID: string): OpenCodeEvent => ({
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue