mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-04 22:49:41 +02:00
Merge pull request #397 from irisitymichaelgrundberg/fix/detached-session-owns-its-pane-size
fix(terminal): let a detached session's own window own its pane size
This commit is contained in:
+20
-1
@@ -1332,7 +1332,11 @@ class CodemanApp {
|
||||
this._redock(id);
|
||||
}
|
||||
|
||||
/** Clear all dashboard-side detached state/timers for a session. */
|
||||
/** Clear all dashboard-side detached state/timers for a session, and take its
|
||||
* sizing back: the popup owned the pane while it was open, so the dashboard's
|
||||
* record of it is stale and the session it is showing needs re-measuring.
|
||||
* ⚠️ Not idempotent — each call re-asserts, so a path that redocks twice for
|
||||
* one close sends two SIGWINCHs. */
|
||||
_redock(id) {
|
||||
const t = this._detachWatchTimers.get(id);
|
||||
if (t) { clearInterval(t); this._detachWatchTimers.delete(id); }
|
||||
@@ -1340,6 +1344,21 @@ class CodemanApp {
|
||||
this._detachOrphanStrikes.delete(id);
|
||||
this.detachedWindows.delete(id);
|
||||
this._markDetached(id, false);
|
||||
// While the popup owned this session the dashboard sent no resizes, so
|
||||
// `_lastResizeDims` — one value for the whole window — no longer describes
|
||||
// the PTY, which the popup has been sizing. Clearing it makes the next
|
||||
// sendResize report truthfully, on every redock path rather than only the
|
||||
// active one: `selectSession` reads that answer to decide whether to wait
|
||||
// for the TUI's redraw, and a false "unchanged" makes it fetch the frame
|
||||
// before the redraw lands.
|
||||
this._lastResizeDims = null;
|
||||
// Sizing comes back with the session. `force` buys a guaranteed repaint for
|
||||
// the case where popup and dashboard happened to agree on a size; the server
|
||||
// already resizes on its own comparison against the real pane whenever the
|
||||
// two differ.
|
||||
if (this.sessions.has(id) && id === this.activeSessionId) {
|
||||
this.sendResize(id, { force: true })?.catch?.(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
/** Defer a channel-driven redock briefly. A popup *reload* emits 'redocked'
|
||||
|
||||
@@ -940,7 +940,10 @@ Object.assign(CodemanApp.prototype, {
|
||||
// causes Ink to re-render at the new row count, garbling terminal output.
|
||||
// Local fit() still runs so xterm knows the viewport size for scrolling.
|
||||
const keyboardUp = typeof KeyboardHandler !== 'undefined' && KeyboardHandler.keyboardVisible;
|
||||
if (this.activeSessionId && !keyboardUp) {
|
||||
// Same yield as sendResize: never resize a PTY whose session is showing
|
||||
// in its own window. Dragging the dashboard's border must not reshape it.
|
||||
const detachedElsewhere = !this.isSoloWindow && this.detachedSessions?.has(this.activeSessionId);
|
||||
if (this.activeSessionId && !keyboardUp && !detachedElsewhere) {
|
||||
const dims = this.fitAddon.proposeDimensions();
|
||||
// Enforce minimum dimensions to prevent layout issues
|
||||
const cols = dims ? Math.max(dims.cols, MIN_COLS) : MIN_COLS;
|
||||
@@ -3848,6 +3851,14 @@ Object.assign(CodemanApp.prototype, {
|
||||
return;
|
||||
}
|
||||
|
||||
// The pane belongs to the popup showing it, so this window has nothing to
|
||||
// restore. Say so rather than reporting a size that was never sent — the
|
||||
// same button in that window does the job.
|
||||
if (!this.isSoloWindow && this.detachedSessions?.has(this.activeSessionId)) {
|
||||
this.showToast('This session is sized by its own window', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
const dims = this.getTerminalDimensions();
|
||||
if (!dims) {
|
||||
this.showToast('Could not determine terminal size', 'error');
|
||||
@@ -4900,6 +4911,17 @@ Object.assign(CodemanApp.prototype, {
|
||||
// Fit terminal to container before reading dimensions — ensures local
|
||||
// terminal size matches what we report to the server PTY.
|
||||
if (this.fitAddon) this.fitAddon.fit();
|
||||
// One PTY cannot hold two sizes. A detached session is owned by its own
|
||||
// window, and the dashboard's terminal is narrower than that window because
|
||||
// the session rail takes width the popup does not have — so both sizing it
|
||||
// makes the CLI draw frames that fit neither, which garbles the popup. The
|
||||
// dashboard yields; the solo window sizes what it alone displays.
|
||||
// (_maybeRefetchFullHistory already stands aside for the same reason.)
|
||||
// ⚠️ AFTER the fit, never before: the local reflow keeps the dashboard's own
|
||||
// xterm right, and only the SERVER write is the dashboard's to withhold —
|
||||
// the mobile-keyboard guard below draws exactly this line. tab-rail-resize
|
||||
// performs its one settle-time refit through this call and has no fallback.
|
||||
if (!this.isSoloWindow && this.detachedSessions?.has(sessionId)) return false;
|
||||
const dims = this.getTerminalDimensions();
|
||||
if (!dims) return false;
|
||||
// Did the dimensions actually change since the last resize we sent? Callers
|
||||
|
||||
Reference in New Issue
Block a user