From a3fa2e86699d776fad87f29602d08ded79c14d31 Mon Sep 17 00:00:00 2001 From: NightWatcher Date: Sat, 23 May 2026 21:16:29 +0800 Subject: [PATCH] fix(web): preserve session preview folding --- web/src/components/SessionList.test.ts | 25 +++++++++++++++++++------ web/src/components/SessionList.tsx | 9 +-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/web/src/components/SessionList.test.ts b/web/src/components/SessionList.test.ts index b739ccd0b3..aa6402824b 100644 --- a/web/src/components/SessionList.test.ts +++ b/web/src/components/SessionList.test.ts @@ -102,10 +102,10 @@ describe('session list search helpers', () => { }) describe('getVisibleSessionPreview', () => { - it('keeps selected and active sessions inside the collapsed preview without promoting them', () => { + it('keeps selected and pending sessions inside the collapsed preview without promoting them', () => { const sessions = Array.from({ length: 6 }, (_, index) => makeSession({ id: `s-${index + 1}`, - active: index === 4, + pendingRequestsCount: index === 4 ? 1 : 0, metadata: { path: '/work/hapi' }, updatedAt: 100 - index })) @@ -118,6 +118,19 @@ describe('getVisibleSessionPreview', () => { expect(preview.map(session => session.id)).toEqual(['s-1', 's-5', 's-6']) }) + it('does not exceed the limit just because many sessions are active', () => { + const sessions = Array.from({ length: 6 }, (_, index) => makeSession({ + id: `s-${index + 1}`, + active: true, + metadata: { path: '/work/hapi' }, + updatedAt: 100 - index + })) + + const preview = getVisibleSessionPreview(sessions, { limit: 4 }) + + expect(preview.map(session => session.id)).toEqual(['s-1', 's-2', 's-3', 's-4']) + }) + it('does not move an already-visible selected session to the top', () => { const sessions = Array.from({ length: 6 }, (_, index) => makeSession({ id: `s-${index + 1}`, @@ -145,7 +158,7 @@ describe('getVisibleSessionPreview', () => { describe('expandSelectedSessionCollapseOverrides', () => { - it('expands collapsed project, machine, and session preview overrides for selected sessions', () => { + it('expands collapsed project and machine, but preserves session preview folding', () => { const overrides = new Map([ ['machine-1::/work/hapi', true], ['sessions::machine-1::/work/hapi', true], @@ -158,11 +171,11 @@ describe('expandSelectedSessionCollapseOverrides', () => { }) expect(result.has('machine-1::/work/hapi')).toBe(false) - expect(result.get('sessions::machine-1::/work/hapi')).toBe(false) + expect(result.get('sessions::machine-1::/work/hapi')).toBe(true) expect(result.has('machine::machine-1')).toBe(false) }) - it('sets missing session preview override to expanded', () => { + it('leaves missing session preview override unset', () => { const overrides = new Map() const result = expandSelectedSessionCollapseOverrides(overrides, { @@ -170,6 +183,6 @@ describe('expandSelectedSessionCollapseOverrides', () => { machineId: 'machine-1' }) - expect(result.get('sessions::machine-1::/work/hapi')).toBe(false) + expect(result.has('sessions::machine-1::/work/hapi')).toBe(false) }) }) diff --git a/web/src/components/SessionList.tsx b/web/src/components/SessionList.tsx index 7de5be981e..2e77a545f8 100644 --- a/web/src/components/SessionList.tsx +++ b/web/src/components/SessionList.tsx @@ -191,13 +191,6 @@ export function expandSelectedSessionCollapseOverrides( changed = true } - // Session preview keys use inverted semantics: false = expanded, true/missing = collapsed. - const sessionPreviewKey = `sessions::${group.key}` - if (overrides.get(sessionPreviewKey) !== false) { - next.set(sessionPreviewKey, false) - changed = true - } - const machineKey = `machine::${group.machineId ?? UNKNOWN_MACHINE_ID}` if (overrides.has(machineKey) && overrides.get(machineKey)) { next.delete(machineKey) @@ -438,7 +431,7 @@ export function getVisibleSessionPreview( const requiredIds = new Set() for (const session of sessions) { - if (session.active) requiredIds.add(session.id) + if (session.pendingRequestsCount > 0) requiredIds.add(session.id) } if (options.selectedSessionId && sessions.some(session => session.id === options.selectedSessionId)) { requiredIds.add(options.selectedSessionId)