| author | |
| committer | |
| log | 85fe41bad0f6e3ab83de6b83f9635482daee79c4 |
| tree | 99858fcbeffcd3e6df67ec6aeb5eb6d64aece304 |
| parent | 0c26396f79b94f8212d3c62d0514dc4188866ee7 |
Co-authored-by: codex <codex@users.noreply.github.com>2 files changed, 20 insertions(+), 12 deletions(-)
apps/web/src/store.test.ts+6-6| ... | ... | @@ -287,7 +287,7 @@ describe("store reducer thread continuity", () => { |
| 287 | 287 | ]); |
| 288 | 288 | }); |
| 289 | 289 | |
| 290 | it("closes the final terminal and hides the drawer", () => { | |
| 290 | it("closes the final terminal and keeps the drawer visibility unchanged", () => { | |
| 291 | 291 | const state = makeState( |
| 292 | 292 | makeThread({ |
| 293 | 293 | terminalOpen: true, |
| ... | ... | @@ -300,14 +300,14 @@ describe("store reducer thread continuity", () => { |
| 300 | 300 | terminalId: DEFAULT_THREAD_TERMINAL_ID, |
| 301 | 301 | }); |
| 302 | 302 | |
| 303 | expect(next.threads[0]?.terminalOpen).toBe(false); | |
| 304 | expect(next.threads[0]?.terminalIds).toEqual([DEFAULT_THREAD_TERMINAL_ID]); | |
| 303 | expect(next.threads[0]?.terminalOpen).toBe(true); | |
| 304 | expect(next.threads[0]?.terminalIds).toEqual([`${DEFAULT_THREAD_TERMINAL_ID}-next`]); | |
| 305 | 305 | expect(next.threads[0]?.runningTerminalIds).toEqual([]); |
| 306 | expect(next.threads[0]?.activeTerminalId).toBe(DEFAULT_THREAD_TERMINAL_ID); | |
| 306 | expect(next.threads[0]?.activeTerminalId).toBe(`${DEFAULT_THREAD_TERMINAL_ID}-next`); | |
| 307 | 307 | expect(next.threads[0]?.terminalGroups).toEqual([ |
| 308 | 308 | { |
| 309 | id: `group-${DEFAULT_THREAD_TERMINAL_ID}`, | |
| 310 | terminalIds: [DEFAULT_THREAD_TERMINAL_ID], | |
| 309 | id: `group-${DEFAULT_THREAD_TERMINAL_ID}-next`, | |
| 310 | terminalIds: [`${DEFAULT_THREAD_TERMINAL_ID}-next`], | |
| 311 | 311 | }, |
| 312 | 312 | ]); |
| 313 | 313 | }); |
apps/web/src/store.ts+14-6| ... | ... | @@ -164,6 +164,13 @@ function fallbackGroupId(terminalId: string): string { |
| 164 | 164 | return `group-${terminalId}`; |
| 165 | 165 | } |
| 166 | 166 | |
| 167 | function replacementTerminalId(closedTerminalId: string): string { | |
| 168 | const normalizedId = closedTerminalId.trim(); | |
| 169 | return normalizedId === DEFAULT_THREAD_TERMINAL_ID | |
| 170 | ? `${DEFAULT_THREAD_TERMINAL_ID}-next` | |
| 171 | : DEFAULT_THREAD_TERMINAL_ID; | |
| 172 | } | |
| 173 | ||
| 167 | 174 | function assignUniqueGroupId(groupId: string, usedGroupIds: Set<string>): string { |
| 168 | 175 | if (!usedGroupIds.has(groupId)) { |
| 169 | 176 | usedGroupIds.add(groupId); |
| ... | ... | @@ -269,19 +276,20 @@ function closeThreadTerminal(thread: Thread, terminalId: string): Thread { |
| 269 | 276 | |
| 270 | 277 | const remainingTerminalIds = thread.terminalIds.filter((id) => id !== terminalId); |
| 271 | 278 | if (remainingTerminalIds.length === 0) { |
| 279 | const nextTerminalId = replacementTerminalId(terminalId); | |
| 280 | const nextTerminalGroupId = fallbackGroupId(nextTerminalId); | |
| 272 | 281 | return normalizeThreadTerminals({ |
| 273 | 282 | ...thread, |
| 274 | terminalOpen: false, | |
| 275 | terminalIds: [DEFAULT_THREAD_TERMINAL_ID], | |
| 283 | terminalIds: [nextTerminalId], | |
| 276 | 284 | runningTerminalIds: [], |
| 277 | activeTerminalId: DEFAULT_THREAD_TERMINAL_ID, | |
| 285 | activeTerminalId: nextTerminalId, | |
| 278 | 286 | terminalGroups: [ |
| 279 | 287 | { |
| 280 | id: fallbackGroupId(DEFAULT_THREAD_TERMINAL_ID), | |
| 281 | terminalIds: [DEFAULT_THREAD_TERMINAL_ID], | |
| 288 | id: nextTerminalGroupId, | |
| 289 | terminalIds: [nextTerminalId], | |
| 282 | 290 | }, |
| 283 | 291 | ], |
| 284 | activeTerminalGroupId: fallbackGroupId(DEFAULT_THREAD_TERMINAL_ID), | |
| 292 | activeTerminalGroupId: nextTerminalGroupId, | |
| 285 | 293 | }); |
| 286 | 294 | } |
| 287 | 295 |