fix(tui): smooth new session tab handoff (#39745)
This commit is contained in:
parent
9abd9594de
commit
16b247f756
4 changed files with 21 additions and 3 deletions
|
|
@ -6,6 +6,7 @@ import { useSessionTabs } from "../context/session-tabs"
|
|||
import { useTheme, useThemes } from "../context/theme"
|
||||
import {
|
||||
adaptiveSessionTabLayout,
|
||||
NEW_SESSION_TAB_TITLE,
|
||||
sessionTabComplete,
|
||||
seedSessionTabMotion,
|
||||
sessionTabOverflowWidth,
|
||||
|
|
@ -36,7 +37,7 @@ export type SessionTabsController = Pick<ContextController, "tabs" | "current" |
|
|||
status(sessionID: string): SessionTabsStatus
|
||||
}
|
||||
|
||||
const NEW_SESSION_TAB: SessionTab = { sessionID: "new", title: "New session" }
|
||||
const NEW_SESSION_TAB: SessionTab = { sessionID: "new", title: NEW_SESSION_TAB_TITLE }
|
||||
|
||||
export function SessionTabs(props: { controller?: SessionTabsController; animations?: boolean } = {}) {
|
||||
const tabs = props.controller ?? useSessionTabs()
|
||||
|
|
@ -209,6 +210,11 @@ export function SessionTabs(props: { controller?: SessionTabsController; animati
|
|||
createEffect((previous: string) => {
|
||||
const next = title()
|
||||
if (next === previous) return next
|
||||
if (previous === NEW_SESSION_TAB_TITLE) {
|
||||
setOutgoingTitle(undefined)
|
||||
wipe.jump({ front: 1 })
|
||||
return next
|
||||
}
|
||||
setOutgoingTitle(previous)
|
||||
wipe.jump({ front: 0 })
|
||||
wipe.animate({ front: 1 })
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ export type SessionTab = {
|
|||
|
||||
export type SessionTabUnread = "activity" | "error"
|
||||
|
||||
export const NEW_SESSION_TAB_TITLE = "New session"
|
||||
|
||||
export type SessionTabHistory = {
|
||||
entries: readonly string[]
|
||||
index: number
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {
|
|||
cycleSessionTab,
|
||||
moveSessionTab,
|
||||
moveSessionTabHistory,
|
||||
NEW_SESSION_TAB_TITLE,
|
||||
openSessionTab,
|
||||
recordClosedSessionTab,
|
||||
recordSessionTabHistory,
|
||||
|
|
@ -77,6 +78,12 @@ export const { use: useSessionTabs, provider: SessionTabsProvider } = createSimp
|
|||
|
||||
const root = (sessionID: string) => data.session.root(sessionID)
|
||||
const current = () => (route.data.type === "session" ? root(route.data.sessionID) : undefined)
|
||||
const newTab = createMemo((open = false) => {
|
||||
if (route.data.type === "home") return true
|
||||
if (!open) return false
|
||||
const sessionID = current()
|
||||
return sessionID !== undefined && !state().tabs.some((tab) => tab.sessionID === sessionID)
|
||||
}, false)
|
||||
const status = (sessionID: string) => {
|
||||
const session = root(sessionID)
|
||||
const members = data.session.family(session)
|
||||
|
|
@ -107,7 +114,7 @@ export const { use: useSessionTabs, provider: SessionTabsProvider } = createSimp
|
|||
if (route.data.type !== "session" || route.data.sessionID === "dummy") return
|
||||
const sessionID = root(route.data.sessionID)
|
||||
history = recordSessionTabHistory(history, sessionID)
|
||||
const title = data.session.get(sessionID)?.title
|
||||
const title = data.session.get(sessionID)?.title ?? (newTab() ? NEW_SESSION_TAB_TITLE : undefined)
|
||||
const tabs = openSessionTab(state().tabs, { sessionID, title })
|
||||
if (tabs === state().tabs && !state().unread[sessionID]) return
|
||||
update((draft) => {
|
||||
|
|
@ -233,7 +240,7 @@ export const { use: useSessionTabs, provider: SessionTabsProvider } = createSimp
|
|||
return state().tabs
|
||||
},
|
||||
newTab() {
|
||||
return route.data.type === "home"
|
||||
return newTab()
|
||||
},
|
||||
current,
|
||||
status,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { DataProvider } from "../../src/context/data"
|
|||
import { RouteProvider, useRoute } from "../../src/context/route"
|
||||
import { TuiAppProvider } from "../../src/context/runtime"
|
||||
import { SessionTabsProvider, useSessionTabs } from "../../src/context/session-tabs"
|
||||
import { NEW_SESSION_TAB_TITLE } from "../../src/context/session-tabs-model"
|
||||
import { StorageProvider } from "../../src/context/storage"
|
||||
import { createApi, createEventStream, createFetch, directory } from "../fixture/tui-client"
|
||||
import { TestTuiContexts } from "../fixture/tui-environment"
|
||||
|
|
@ -142,11 +143,13 @@ test("tracks a temporary new session tab across close and creation", async () =>
|
|||
setup.route.navigate({ type: "home" })
|
||||
await wait(() => setup.tabs.newTab())
|
||||
setup.route.navigate({ type: "session", sessionID: "third" })
|
||||
expect(setup.tabs.newTab()).toBe(true)
|
||||
await wait(
|
||||
() => setup.tabs.current() === "third" && setup.tabs.tabs().some((tab) => tab.sessionID === "third"),
|
||||
)
|
||||
|
||||
expect(setup.tabs.newTab()).toBe(false)
|
||||
expect(setup.tabs.tabs().find((tab) => tab.sessionID === "third")?.title).toBe(NEW_SESSION_TAB_TITLE)
|
||||
} finally {
|
||||
setup.destroy()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue