From e7914da42d0b3cb272eecc1ed13731bdffb2d168 Mon Sep 17 00:00:00 2001 From: Daniel Kutyla Date: Thu, 19 Mar 2026 12:17:21 +0100 Subject: [PATCH] fix(shell): persist drag-and-drop pane reorder across navigation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The server-side fix alone was insufficient — the client-side panes Map (which controls remount order) was never reordered on drag-and-drop. When navigating away and back, mount() iterates the Map in insertion order, restoring the original layout. Add _reorderPanesMap() helper that rebuilds the Map in visual order after each drag-and-drop swap and after receiving state:panes-reordered from the server (multi-client sync). --- src/apps/shell/public/page.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/apps/shell/public/page.js b/src/apps/shell/public/page.js index 2a1b05b..6c88bdc 100644 --- a/src/apps/shell/public/page.js +++ b/src/apps/shell/public/page.js @@ -391,6 +391,9 @@ function _attachDragHandlers(header, wrapper, id) { } } + // Reorder the in-memory panes Map so remount preserves visual order + _reorderPanesMap(newOrder); + // Emit to server for persistence socket.emit('state:reorder-panes', { order: newOrder }); @@ -398,6 +401,20 @@ function _attachDragHandlers(header, wrapper, id) { }); } +/** Reorder the panes Map to match a given ID order (preserves remount order). */ +function _reorderPanesMap(order) { + const snapshot = new Map(panes); + panes.clear(); + for (const id of order) { + const p = snapshot.get(id); + if (p) panes.set(id, p); + } + // Append any remaining panes not in the order list + for (const [id, p] of snapshot) { + if (!panes.has(id)) panes.set(id, p); + } +} + // ── Terminal pane creation ────────────────────────────────────────── function createTerminalPane({ id, shellType, title, onClose, onFocus, skipInitialFit = false, parentElement = null }) { @@ -1343,6 +1360,8 @@ function wireSocketEvents(refs) { const tab = refs.tabBar.querySelector(`.shell-tab[data-tab="${id}"]`); if (tab) refs.tabBar.appendChild(tab); } + // Reorder the in-memory panes Map so remount preserves visual order + _reorderPanesMap(order); // Re-fit after DOM reorder — moving elements can change terminal dimensions relayout(refs); };