Skip to content

Commit 64fd7a2

Browse files
authored
fix(app): persist session tab info (anomalyco#34934)
1 parent ae259d8 commit 64fd7a2

3 files changed

Lines changed: 50 additions & 11 deletions

File tree

packages/app/src/components/titlebar-tab-nav.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,18 +246,21 @@ export function TabNavItem(props: {
246246
}}
247247
class="flex h-full min-w-0 flex-1 flex-row items-center gap-1.5 text-[13px] font-medium text-v2-text-text-faint group-data-[active='true']:text-v2-text-text-base group-data-[editing='true']:text-v2-text-text-base [-webkit-user-drag:none]"
248248
>
249-
<Show when={props.session()}>
250-
{(session) => (
251-
<span data-slot="project-avatar-slot">
249+
<span data-slot="project-avatar-slot" class="flex size-4 shrink-0 items-center justify-center">
250+
<Show
251+
when={props.session()}
252+
fallback={<span class="block size-4 rounded-[3px] border border-v2-border-border-muted" aria-hidden="true" />}
253+
>
254+
{(session) => (
252255
<SessionTabAvatar
253256
project={project()}
254257
directory={session().directory}
255258
sessionId={session().id}
256259
server={props.server}
257260
/>
258-
</span>
259-
)}
260-
</Show>
261+
)}
262+
</Show>
263+
</span>
261264
<span
262265
ref={(el) => {
263266
titleEl = el

packages/app/src/components/titlebar-tab-strip.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ function SessionTabSlot(props: {
4040
let ref!: HTMLDivElement
4141
const sdk = createMemo(() => props.serverCtx()?.sdk ?? null)
4242
const cachedSession = createMemo(() => props.serverCtx()?.sync.session.peek(props.tab.sessionId))
43+
const persisted = createMemo(() => tabs.info[props.id])
4344
const [loadedSession] = createResource(
4445
() => {
4546
const ctx = props.serverCtx()
@@ -71,8 +72,10 @@ function SessionTabSlot(props: {
7172

7273
createEffect(() => {
7374
const value = session()
75+
if (!value) return
76+
tabs.rememberSessionInfo(props.tab, value)
7477
const current = sdk()
75-
if (!value || !current) return
78+
if (!current) return
7679
createTabPromptState(tabs, props.tab, current.scope, {
7780
dir: base64Encode(value.directory),
7881
id: value.id,
@@ -86,7 +89,7 @@ function SessionTabSlot(props: {
8689
data-tab-key={props.id}
8790
data-active={props.active()}
8891
class="relative flex w-56 min-w-7 max-w-56 flex-shrink"
89-
classList={{ hidden: !session() && !missingSession() }}
92+
classList={{ hidden: !session() && !missingSession() && !persisted()?.title }}
9093
>
9194
<TabNavItem
9295
ref={(el) => {
@@ -95,7 +98,7 @@ function SessionTabSlot(props: {
9598
href={tabHref(props.tab)}
9699
server={props.tab.server}
97100
session={session}
98-
fallbackTitle={missingSession() ? language.t("session.tab.unknown") : undefined}
101+
fallbackTitle={persisted()?.title ?? (missingSession() ? language.t("session.tab.unknown") : undefined)}
99102
onTitleChange={(title) => {
100103
const value = session()
101104
const ctx = props.serverCtx()

packages/app/src/context/tabs.tsx

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ export type DraftTab = {
2828

2929
export type Tab = SessionTab | DraftTab
3030

31+
export type TabInfo = {
32+
title?: string
33+
directory?: string
34+
}
35+
3136
type RecentTab = {
3237
key?: string
3338
}
@@ -64,6 +69,7 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({
6469
createStore<Tab[]>([]),
6570
)
6671
const [recent, setRecent, , recentReady] = persisted(Persist.window("tabs.recent"), createStore<RecentTab>({}))
72+
const [info, setInfo] = persisted(Persist.window("tabs.info"), createStore<Record<string, TabInfo>>({}))
6773
const [closed, setClosed, , closedReady] = persisted(Persist.window("tabs.closed"), createStore<ClosedTab[]>([]))
6874

6975
const params = useParams()
@@ -102,6 +108,15 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({
102108
for (const key of draftPersistedKeys()) removePersisted(Persist.draft(draftID, key), platform)
103109
}
104110

111+
const removeInfo = (key: string) => {
112+
if (!info[key]) return
113+
setInfo(
114+
produce((draft) => {
115+
delete draft[key]
116+
}),
117+
)
118+
}
119+
105120
onCleanup(memory.dispose)
106121

107122
createEffect(() => {
@@ -110,11 +125,19 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({
110125
const next = store.filter((tab) => servers.has(tab.server))
111126
if (next.length !== store.length) {
112127
for (const tab of store) {
113-
if (!servers.has(tab.server)) memory.remove(tabKey(tab))
128+
if (!servers.has(tab.server)) {
129+
const key = tabKey(tab)
130+
memory.remove(key)
131+
removeInfo(key)
132+
}
114133
}
115134
setStore(() => next)
116135
}
117136
if (recent.key && !next.some((tab) => tabKey(tab) === recent.key)) setRecentKey(undefined)
137+
const keys = new Set(next.map(tabKey))
138+
for (const key of Object.keys(info)) {
139+
if (!keys.has(key)) removeInfo(key)
140+
}
118141
})
119142

120143
createEffect(() => {
@@ -150,6 +173,7 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({
150173
if (nextTab) navigateTab(nextTab)
151174
}).finally(() => closing.delete(key))
152175
memory.remove(key)
176+
removeInfo(key)
153177
if (draftID) removeDraftPersisted(draftID)
154178
}
155179

@@ -264,6 +288,7 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({
264288
const removed = store.filter((tab) => tab.server === key).map(tabKey)
265289
setStore((tabs) => tabs.filter((tab) => tab.server !== key))
266290
for (const key of removed) memory.remove(key)
291+
for (const key of removed) removeInfo(key)
267292
if (recent.key && removed.includes(recent.key)) setRecentKey(undefined)
268293
for (const draftID of drafts) removeDraftPersisted(draftID)
269294
if (server.key === key) navigate("/")
@@ -318,6 +343,14 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({
318343
if (recent.key && removed.includes(recent.key)) setRecentKey(undefined)
319344
})
320345
for (const key of removed) memory.remove(key)
346+
for (const key of removed) removeInfo(key)
347+
},
348+
rememberSessionInfo(tab: SessionTab, session: Session) {
349+
const key = tabKey(tab)
350+
const next = { title: session.title, directory: session.directory }
351+
const current = info[key]
352+
if (current?.title === next.title && current.directory === next.directory) return
353+
setInfo(key, next)
321354
},
322355
select: navigateTab,
323356
remember(tab: Tab) {
@@ -342,6 +375,6 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({
342375
},
343376
}
344377

345-
return { ...actions, store, ready, recentReady }
378+
return { ...actions, store, info, ready, recentReady }
346379
},
347380
})

0 commit comments

Comments
 (0)