From 63ac10dcc0cb28ceedcadbd8ef9a703ea72efadb Mon Sep 17 00:00:00 2001 From: Codeman maintainer Date: Tue, 13 Oct 2026 18:59:39 +0200 Subject: [PATCH] fix(tiles): docking a tile asks any pop-out of that session to close (#584 merge-time fix) _dockForeignTile posted close-request only when this window knew the session was popped out. A pop-out opened from another dashboard window was not in this window's detachedSessions, so it stayed open beside the newly docked tile and two views sized one PTY. The request now goes out for every docked id; dashboards ignore it and only that session's pop-out reacts. Co-Authored-By: Claude Opus 5.5 (1M context) --- src/web/public/tile-grid.js | 5 ++++- test/tile-grid-detach.test.ts | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/web/public/tile-grid.js b/src/web/public/tile-grid.js index e78193f0..d95c6b27 100644 --- a/src/web/public/tile-grid.js +++ b/src/web/public/tile-grid.js @@ -2980,7 +2980,10 @@ Object.assign(CodemanApp.prototype, { place(sessionId); if (!grid.has(sessionId)) return false; (this._tileDockedAt ||= new Map()).set(sessionId, Date.now()); - if (poppedOut) this._postWindowMessage?.({ type: 'close-request', id: sessionId }); + // Asked unconditionally: a pop-out this window never heard of (opened from + // another dashboard) closes too. Dashboards ignore it; only that id's + // pop-out reacts. + this._postWindowMessage?.({ type: 'close-request', id: sessionId }); this._postWindowMessage?.({ type: 'tile-adopted', id: sessionId, by: this._wsTabNonce }); return true; }, diff --git a/test/tile-grid-detach.test.ts b/test/tile-grid-detach.test.ts index d3b983c9..40c2265a 100644 --- a/test/tile-grid-detach.test.ts +++ b/test/tile-grid-detach.test.ts @@ -387,6 +387,14 @@ describe('a tile from another window dropped here', () => { expect(app._tileGrid.ids).toContain('s-other'); }); + it("asks the session's pop-out to close even when this window did not know of one", () => { + // Popped out from another dashboard: this window's detachedSessions never had it. + const app = openGrid(THREE); + tileEl('s-c').dispatch('drop', foreign('s-other')); + expect(app._tileGrid.ids).toContain('s-other'); + expect(app._postWindowMessage).toHaveBeenCalledWith({ type: 'close-request', id: 's-other' }); + }); + it('an id this page does not know docks nowhere', () => { const app = openGrid(THREE); tileEl('s-b').dispatch('drop', foreign('s-gone'));