mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 14:03:49 +00:00
fix(tui): full redraw on terminal width/height resize\n\ncloses #1844
This commit is contained in:
parent
bb85cad0ba
commit
dabcda0db3
4 changed files with 45 additions and 5 deletions
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed editor/footer visibility drift during terminal resize by forcing full redraws when terminal width or height changes ([#1844](https://github.com/badlogic/pi-mono/pull/1844) by [@ghoulr](https://github.com/ghoulr)).
|
||||
|
||||
## [0.56.1] - 2026-03-05
|
||||
|
||||
### Fixed
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed editor/footer visibility drift during terminal resize by forcing full redraws when terminal width or height changes ([#1844](https://github.com/badlogic/pi-mono/pull/1844) by [@ghoulr](https://github.com/ghoulr)).
|
||||
|
||||
## [0.56.1] - 2026-03-05
|
||||
|
||||
### Fixed
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ export class TUI extends Container {
|
|||
public terminal: Terminal;
|
||||
private previousLines: string[] = [];
|
||||
private previousWidth = 0;
|
||||
private previousHeight = 0;
|
||||
private focusedComponent: Component | null = null;
|
||||
private inputListeners = new Set<InputListener>();
|
||||
|
||||
|
|
@ -425,6 +426,7 @@ export class TUI extends Container {
|
|||
if (force) {
|
||||
this.previousLines = [];
|
||||
this.previousWidth = -1; // -1 triggers widthChanged, forcing a full clear
|
||||
this.previousHeight = -1; // -1 triggers heightChanged, forcing a full clear
|
||||
this.cursorRow = 0;
|
||||
this.hardwareCursorRow = 0;
|
||||
this.maxLinesRendered = 0;
|
||||
|
|
@ -871,8 +873,9 @@ export class TUI extends Container {
|
|||
|
||||
newLines = this.applyLineResets(newLines);
|
||||
|
||||
// Width changed - need full re-render (line wrapping changes)
|
||||
// Width or height changed - need full re-render
|
||||
const widthChanged = this.previousWidth !== 0 && this.previousWidth !== width;
|
||||
const heightChanged = this.previousHeight !== 0 && this.previousHeight !== height;
|
||||
|
||||
// Helper to clear scrollback and viewport and render all new lines
|
||||
const fullRender = (clear: boolean): void => {
|
||||
|
|
@ -897,6 +900,7 @@ export class TUI extends Container {
|
|||
this.positionHardwareCursor(cursorPos, newLines.length);
|
||||
this.previousLines = newLines;
|
||||
this.previousWidth = width;
|
||||
this.previousHeight = height;
|
||||
};
|
||||
|
||||
const debugRedraw = process.env.PI_DEBUG_REDRAW === "1";
|
||||
|
|
@ -908,15 +912,15 @@ export class TUI extends Container {
|
|||
};
|
||||
|
||||
// First render - just output everything without clearing (assumes clean screen)
|
||||
if (this.previousLines.length === 0 && !widthChanged) {
|
||||
if (this.previousLines.length === 0 && !widthChanged && !heightChanged) {
|
||||
logRedraw("first render");
|
||||
fullRender(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Width changed - full re-render (line wrapping changes)
|
||||
if (widthChanged) {
|
||||
logRedraw(`width changed (${this.previousWidth} -> ${width})`);
|
||||
// Width or height changed - full re-render
|
||||
if (widthChanged || heightChanged) {
|
||||
logRedraw(`terminal size changed (${this.previousWidth}x${this.previousHeight} -> ${width}x${height})`);
|
||||
fullRender(true);
|
||||
return;
|
||||
}
|
||||
|
|
@ -958,6 +962,7 @@ export class TUI extends Container {
|
|||
if (firstChanged === -1) {
|
||||
this.positionHardwareCursor(cursorPos, newLines.length);
|
||||
this.previousViewportTop = Math.max(0, this.maxLinesRendered - height);
|
||||
this.previousHeight = height;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -996,6 +1001,7 @@ export class TUI extends Container {
|
|||
this.positionHardwareCursor(cursorPos, newLines.length);
|
||||
this.previousLines = newLines;
|
||||
this.previousWidth = width;
|
||||
this.previousHeight = height;
|
||||
this.previousViewportTop = Math.max(0, this.maxLinesRendered - height);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1144,6 +1150,7 @@ export class TUI extends Container {
|
|||
|
||||
this.previousLines = newLines;
|
||||
this.previousWidth = width;
|
||||
this.previousHeight = height;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -23,6 +23,31 @@ function getCellItalic(terminal: VirtualTerminal, row: number, col: number): num
|
|||
}
|
||||
|
||||
describe("TUI resize handling", () => {
|
||||
it("triggers full re-render when terminal height changes", async () => {
|
||||
const terminal = new VirtualTerminal(40, 10);
|
||||
const tui = new TUI(terminal);
|
||||
const component = new TestComponent();
|
||||
tui.addChild(component);
|
||||
|
||||
component.lines = ["Line 0", "Line 1", "Line 2"];
|
||||
tui.start();
|
||||
await terminal.flush();
|
||||
|
||||
const initialRedraws = tui.fullRedraws;
|
||||
|
||||
// Resize height
|
||||
terminal.resize(40, 15);
|
||||
await terminal.flush();
|
||||
|
||||
// Should have triggered a full redraw
|
||||
assert.ok(tui.fullRedraws > initialRedraws, "Height change should trigger full redraw");
|
||||
|
||||
const viewport = terminal.getViewport();
|
||||
assert.ok(viewport[0]?.includes("Line 0"), "Content preserved after height change");
|
||||
|
||||
tui.stop();
|
||||
});
|
||||
|
||||
it("triggers full re-render when terminal width changes", async () => {
|
||||
const terminal = new VirtualTerminal(40, 10);
|
||||
const tui = new TUI(terminal);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue