fix: ensure session state is removed correctly when closing tabs

This commit is contained in:
Andy Dixon
2026-05-22 15:29:29 +01:00
parent cb76b77f1b
commit 759485fc47
3 changed files with 33 additions and 4 deletions
+1 -1
View File
@@ -384,8 +384,8 @@
this.rawViewer.destroyViewer(sessionId); this.rawViewer.destroyViewer(sessionId);
window.NexusTerminal.GitHubViewer.destroyViewer(sessionId); window.NexusTerminal.GitHubViewer.destroyViewer(sessionId);
window.NexusTerminal.VNCViewer.destroyViewer(sessionId); window.NexusTerminal.VNCViewer.destroyViewer(sessionId);
this.state.removeSession(sessionId);
this.tabs.removeTab(sessionId); this.tabs.removeTab(sessionId);
this.state.removeSession(sessionId);
this.updateStatusBar(); this.updateStatusBar();
} }
+4 -3
View File
@@ -65,6 +65,7 @@
*/ */
removeTab(sessionId) { removeTab(sessionId) {
const idx = this.order.indexOf(sessionId); const idx = this.order.indexOf(sessionId);
const wasActive = this.app.state.activeSessionId === sessionId;
if (idx !== -1) this.order.splice(idx, 1); if (idx !== -1) this.order.splice(idx, 1);
// Remove tab element // Remove tab element
@@ -77,8 +78,8 @@
const panel = document.getElementById(`panel-${sessionId}`); const panel = document.getElementById(`panel-${sessionId}`);
if (panel) panel.remove(); if (panel) panel.remove();
// If this was the active tab, activate the nearest neighbour // Activate the nearest neighbour
if (this.app.state.activeSessionId === sessionId) { if (wasActive) {
const next = const next =
this.order.length > 0 this.order.length > 0
? this.order[Math.min(idx, this.order.length - 1)] ? this.order[Math.min(idx, this.order.length - 1)]
@@ -176,8 +177,8 @@
this.app.terminals.destroyTerminal(sessionId); this.app.terminals.destroyTerminal(sessionId);
this.app.rawViewer.destroyViewer(sessionId); this.app.rawViewer.destroyViewer(sessionId);
window.NexusTerminal.GitHubViewer.destroyViewer(sessionId); window.NexusTerminal.GitHubViewer.destroyViewer(sessionId);
this.app.state.removeSession(sessionId);
this.removeTab(sessionId); this.removeTab(sessionId);
this.app.state.removeSession(sessionId);
} }
/** /**
+28
View File
@@ -112,6 +112,34 @@
}); });
} }
// Alternate-screen scroll passthrough for screen/tmux/byobu.
// When the terminal is in the alternate buffer (used by multiplexers),
// convert mouse-wheel events into arrow-key sequences so the remote
// application handles scrollback instead of xterm.js (which has no
// scrollback content in alternate mode).
const viewportEl = container.querySelector(".xterm-viewport");
if (viewportEl) {
viewportEl.addEventListener("wheel", (e) => {
if (term.buffer.active !== term.buffer.alternate) return;
// Only intercept when mouse tracking is NOT active (if mouse mode
// is on, xterm.js already forwards events correctly).
if (term.modes && term.modes.mouseTrackingMode &&
term.modes.mouseTrackingMode !== "none") return;
e.preventDefault();
e.stopPropagation();
const lines = Math.max(1, Math.round(Math.abs(e.deltaY) / 40));
const seq = e.deltaY < 0 ? "\x1b[A" : "\x1b[B";
const data = seq.repeat(lines);
const b64 = btoa(data);
try {
window.go.api.Service.WriteSession(sessionId, b64);
} catch (_) {
/* non-critical */
}
}, { passive: false });
}
// Drag-and-drop file handling // Drag-and-drop file handling
container.addEventListener("dragover", (e) => { container.addEventListener("dragover", (e) => {
if ( if (