refactor(tiles): one helper drops a tile's queued loads and destroys it

closeTileGrid, removeTile, dropSessionOnTile and _remountTile each spelled
out `grid.queue?.drop(tile); tile.destroy()`. They now call
_destroyTerminalTile(tile), which keeps that order (the waiting loads are
resolved and the loading state cleared before the tile goes) and says why
once. The tile's element stays the caller's to remove.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-10-07 09:37:03 +02:00
parent 6af38abc76
commit a24b548389
+15 -8
View File
@@ -263,8 +263,7 @@ Object.assign(CodemanApp.prototype, {
grid.resizeObserver?.disconnect(); grid.resizeObserver?.disconnect();
grid.resizeObserver = null; grid.resizeObserver = null;
for (const { tile, el } of grid.tiles.values()) { for (const { tile, el } of grid.tiles.values()) {
grid.queue?.drop(tile); this._destroyTerminalTile(tile);
tile.destroy();
el.remove(); el.remove();
} }
grid.tiles.clear(); grid.tiles.clear();
@@ -685,8 +684,7 @@ Object.assign(CodemanApp.prototype, {
// The zoomed tile leaving restores the grid (an automatic zoom moves to // The zoomed tile leaving restores the grid (an automatic zoom moves to
// the neighbour with focus, below). // the neighbour with focus, below).
if (grid.zoomedId === sessionId) grid.zoomedId = grid.autoZoom && refocus ? neighbor : null; if (grid.zoomedId === sessionId) grid.zoomedId = grid.autoZoom && refocus ? neighbor : null;
grid.queue?.drop(entry.tile); this._destroyTerminalTile(entry.tile);
entry.tile.destroy();
entry.el.remove(); entry.el.remove();
grid.tiles.delete(sessionId); grid.tiles.delete(sessionId);
grid.ids.splice(grid.ids.indexOf(sessionId), 1); grid.ids.splice(grid.ids.indexOf(sessionId), 1);
@@ -802,8 +800,7 @@ Object.assign(CodemanApp.prototype, {
grid.ids.pop(); grid.ids.pop();
grid.ids.splice(index, 1, draggedId); grid.ids.splice(index, 1, draggedId);
const old = grid.tiles.get(targetId); const old = grid.tiles.get(targetId);
grid.queue?.drop(old.tile); this._destroyTerminalTile(old.tile);
old.tile.destroy();
old.el.remove(); old.el.remove();
grid.tiles.delete(targetId); grid.tiles.delete(targetId);
if (grid.zoomedId === targetId) grid.zoomedId = grid.autoZoom ? draggedId : null; if (grid.zoomedId === targetId) grid.zoomedId = grid.autoZoom ? draggedId : null;
@@ -908,6 +905,17 @@ Object.assign(CodemanApp.prototype, {
return tile; return tile;
}, },
/**
* A grid tile's TerminalTile goes for good: its loads still waiting in the
* grid's queue are dropped first (resolved, never run, its loading state
* cleared), then the tile itself (socket, xterm, listeners). Its element is
* the caller's.
*/
_destroyTerminalTile(tile) {
this._tileGrid.queue?.drop(tile);
tile.destroy();
},
/** /**
* Replaces a tile's TerminalTile with a fresh one in the same place (after * Replaces a tile's TerminalTile with a fresh one in the same place (after
* Attach: a tile whose socket stopped for good cannot reconnect, and a fresh * Attach: a tile whose socket stopped for good cannot reconnect, and a fresh
@@ -917,8 +925,7 @@ Object.assign(CodemanApp.prototype, {
const entry = this._tileGrid?.open ? this._tileGrid.tiles.get(sessionId) : null; const entry = this._tileGrid?.open ? this._tileGrid.tiles.get(sessionId) : null;
if (!entry) return; if (!entry) return;
const hadKeyboard = this._focusedTile === entry.tile; const hadKeyboard = this._focusedTile === entry.tile;
this._tileGrid.queue?.drop(entry.tile); this._destroyTerminalTile(entry.tile);
entry.tile.destroy();
entry.tile = this._newTerminalTile(sessionId, entry.body); entry.tile = this._newTerminalTile(sessionId, entry.body);
this._connectTile(sessionId); this._connectTile(sessionId);
if (hadKeyboard) this._noteFocusedTile(entry.tile); if (hadKeyboard) this._noteFocusedTile(entry.tile);