fix(tiles): a tile docked in another window leaves this window's stored grid alone (#584 merge-time fix)

There is one stored grid per browser (codeman:tile-grid), and the window that
docked the tile has just written it. When this window then hears the claim and
drops the tile, removeTile (or, for its last tile, closeTileGrid with
keepStored: false) overwrote or forgot that stored grid. The removal now runs
under _tilePersistHold, and the last-tile close keeps the stored grid.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer committed 2026-10-13 18:58:22 +02:00
1 parent 9ad43fbd88
commit 3975089af3
2 files changed
+45 -2

No files matched your search

+10 -2
View File
@@ -3012,8 +3012,16 @@ Object.assign(CodemanApp.prototype, {
this._lastTileDrag = null;
const grid = this._tileGrid;
if (!grid?.has(sessionId)) return false;
if (grid.ids.length > 1) return this.removeTile(sessionId, { focus: false });
this.closeTileGrid({ keepStored: false, reselect: false });
// One stored grid per browser, and the window that docked the tile has
// just written it: this window losing the tile is no change of the
// user's to remember over that one (nor to forget it).
this._tilePersistHold = true;
try {
if (grid.ids.length > 1) return this.removeTile(sessionId, { focus: false });
this.closeTileGrid({ keepStored: true, reselect: false });
} finally {
this._tilePersistHold = false;
}
this.activeSessionId = null;
try {
localStorage.removeItem('codeman-active-session');
+35
View File
@@ -42,6 +42,7 @@ import {
FakeTile,
documentAddEventListener,
documentRemoveEventListener,
localStore,
makeGridApp,
pointHits,
resetGridHarness,
@@ -281,6 +282,40 @@ describe('another window docking the tile this one dragged', () => {
expect(app.terminal.clear).toHaveBeenCalled();
});
// One stored grid per browser: the window that docked the tile wrote it a
// moment before this one hears the claim. Losing the tile here is not a
// layout of this window's to store over that one, nor a reason to forget it.
const docked = JSON.stringify({
v: 1,
open: true,
ids: ['s-x', 's-b'],
count: 2,
focused: 's-b',
zoomed: null,
colFr: [1, 1],
rowFr: [1],
});
it("the stored grid stays the docking window's when this one keeps other tiles", () => {
const app = openGrid(FOUR);
startDrag('s-b');
endDrag('s-b', { clientX: -50, clientY: 300 }, 'move');
localStore.set('codeman:tile-grid', docked);
app._onWindowMessage({ type: 'tile-adopted', id: 's-b', by: 'c-there' });
expect(app._tileGrid.ids).toEqual(['s-a', 's-c', 's-d']);
expect(localStore.get('codeman:tile-grid')).toBe(docked);
});
it("the stored grid stays the docking window's when this one's last tile leaves", () => {
const app = openGrid(['s-b']);
startDrag('s-b');
endDrag('s-b', { clientX: -50, clientY: 300 }, 'move');
localStore.set('codeman:tile-grid', docked);
app._onWindowMessage({ type: 'tile-adopted', id: 's-b', by: 'c-there' });
expect(app._tileGrid.open).toBe(false);
expect(localStore.get('codeman:tile-grid')).toBe(docked);
});
it('a claim for a tile this window did not drag, or one it dragged long ago, is ignored', () => {
const app = openGrid(FOUR);
app._onWindowMessage({ type: 'tile-adopted', id: 's-b', by: 'c-there' });