feat(web): render durable session titles
This commit is contained in:
@@ -153,7 +153,7 @@ function sessionRow(g: Group, s: SessionSummary, depth: number, hasChildren: boo
|
||||
type: 'session',
|
||||
id: s.id,
|
||||
groupKey: g.key,
|
||||
title: s.title,
|
||||
title: s.displayTitle,
|
||||
depth,
|
||||
hasChildren,
|
||||
expanded,
|
||||
@@ -182,7 +182,7 @@ function flattenVisible(g: Group, expandedSessions: ReadonlySet<string>, rows: S
|
||||
function searchVisible(g: Group, q: string): Set<SessionId> {
|
||||
const visible = new Set<SessionId>()
|
||||
for (const m of g.summaries.values()) {
|
||||
if (!m.title.toLowerCase().includes(q)) continue
|
||||
if (!m.displayTitle.toLowerCase().includes(q)) continue
|
||||
let cur: SessionSummary | undefined = m
|
||||
while (cur !== undefined && !visible.has(cur.id)) {
|
||||
visible.add(cur.id)
|
||||
@@ -212,9 +212,9 @@ function flattenSearch(g: Group, visible: ReadonlySet<SessionId>, rows: SidebarR
|
||||
*
|
||||
* Normal mode: every project row shows; sessions show under expanded
|
||||
* projects, descending only into expanded sessions. Search mode (non-blank
|
||||
* query, case-insensitive title substring): expansion state is ignored —
|
||||
* query, case-insensitive display-title substring): expansion state is ignored —
|
||||
* matched sessions and their ancestor chains are forced visible, groups
|
||||
* without a title or label hit are dropped, and a label-only hit keeps the
|
||||
* without a display-title or label hit are dropped, and a label-only hit keeps the
|
||||
* bare project row.
|
||||
* @param list - sessions list snapshot.
|
||||
* @param view - expansion sets and search query.
|
||||
|
||||
@@ -28,7 +28,7 @@ async function bench() {
|
||||
await ctx.plugin(SlotsService).await()
|
||||
const list = createSnapshotStore<SessionListState>({
|
||||
ids: [sid('a')],
|
||||
byId: { [sid('a')]: { id: sid('a'), title: 'alpha', cwd: '/proj', running: false, updatedAt: 1 } },
|
||||
byId: { [sid('a')]: { id: sid('a'), title: 'alpha', displayTitle: 'alpha', cwd: '/proj', running: false, updatedAt: 1 } },
|
||||
})
|
||||
const sessions = { list, create: vi.fn(async () => sid('minted')) }
|
||||
const layout = {
|
||||
@@ -132,7 +132,7 @@ describe('apply', () => {
|
||||
sessions.list.update((draft) => {
|
||||
draft.ids.push(sid('kid'))
|
||||
draft.byId[sid('kid')] = {
|
||||
id: sid('kid'), title: 'child', cwd: '/proj', parentId: sid('a'), running: false, updatedAt: 2,
|
||||
id: sid('kid'), title: 'child', displayTitle: 'child', cwd: '/proj', parentId: sid('a'), running: false, updatedAt: 2,
|
||||
}
|
||||
})
|
||||
await ctx.plugin({ inject: [...inject], apply }).await()
|
||||
|
||||
@@ -31,6 +31,7 @@ function summary(init: SummaryInit): SessionSummary {
|
||||
const s: SessionSummary = {
|
||||
id: sid(init.id),
|
||||
title: init.title ?? init.id,
|
||||
displayTitle: init.title ?? init.id,
|
||||
running: init.running ?? false,
|
||||
updatedAt: init.updatedAt ?? 0,
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ function summary(init: SummaryInit): SessionSummary {
|
||||
const s: SessionSummary = {
|
||||
id: sid(init.id),
|
||||
title: init.title ?? init.id,
|
||||
displayTitle: init.title ?? init.id,
|
||||
running: init.running ?? false,
|
||||
updatedAt: init.updatedAt ?? 0,
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ const sid = (s: string) => s as SessionId
|
||||
interface SummaryInit {
|
||||
id: string
|
||||
title?: string
|
||||
displayTitle?: string
|
||||
cwd?: string
|
||||
parentId?: string
|
||||
running?: boolean
|
||||
@@ -20,10 +21,11 @@ interface SummaryInit {
|
||||
function summary(init: SummaryInit): SessionSummary {
|
||||
const s: SessionSummary = {
|
||||
id: sid(init.id),
|
||||
title: init.title ?? init.id,
|
||||
displayTitle: init.displayTitle ?? init.title ?? init.id,
|
||||
running: init.running ?? false,
|
||||
updatedAt: init.updatedAt ?? 0,
|
||||
}
|
||||
if (init.title !== undefined) s.title = init.title
|
||||
if (init.cwd !== undefined) s.cwd = init.cwd
|
||||
if (init.parentId !== undefined) s.parentId = sid(init.parentId)
|
||||
return s
|
||||
@@ -211,6 +213,15 @@ describe('deriveRows search', () => {
|
||||
const rows = deriveRows(list, view({ query: ' ' }))
|
||||
expect(rows.every(r => r.type === 'project')).toBe(true)
|
||||
})
|
||||
|
||||
it('matches the effective display title when no durable title is available', () => {
|
||||
const fallback = listOf(summary({ id: 'raw-id', displayTitle: 'project fallback', cwd: '/elsewhere' }))
|
||||
const rows = deriveRows(fallback, view({ query: 'fallback' }))
|
||||
expect(rows).toEqual([
|
||||
expect.objectContaining({ type: 'project', key: '/elsewhere' }),
|
||||
expect.objectContaining({ type: 'session', id: 'raw-id', title: 'project fallback' }),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('formatRelativeTime', () => {
|
||||
|
||||
Reference in New Issue
Block a user