@oh-my-pi/pi-tui 17.1.1 → 17.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/package.json +3 -3
- package/src/tui.ts +52 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [17.1.2] - 2026-07-24
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Fixed the terminal flickering when leaving a fullscreen overlay (e.g. `/settings`, the models page) or resizing on terminals that re-report their size whenever the alternate screen buffer toggles: the alt-toggle size echo no longer arms a destructive full-screen (ED3) rebuild, and the in-place repaint path is now auto-detected for any such terminal instead of only Warp ([#6511](https://github.com/can1357/oh-my-pi/issues/6511)).
|
|
10
|
+
|
|
5
11
|
## [17.1.1] - 2026-07-24
|
|
6
12
|
|
|
7
13
|
### Fixed
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-tui",
|
|
4
|
-
"version": "17.1.
|
|
4
|
+
"version": "17.1.2",
|
|
5
5
|
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"fmt": "biome format --write ."
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@oh-my-pi/pi-natives": "17.1.
|
|
41
|
-
"@oh-my-pi/pi-utils": "17.1.
|
|
40
|
+
"@oh-my-pi/pi-natives": "17.1.2",
|
|
41
|
+
"@oh-my-pi/pi-utils": "17.1.2",
|
|
42
42
|
"lru-cache": "11.5.2",
|
|
43
43
|
"marked": "^18.0.6"
|
|
44
44
|
},
|
package/src/tui.ts
CHANGED
|
@@ -1091,6 +1091,13 @@ export class TUI extends Container {
|
|
|
1091
1091
|
// resize frames so width changes truncate the transient viewport instead of
|
|
1092
1092
|
// pushing wrapped fragments into native scrollback.
|
|
1093
1093
|
#resizeAltActive = false;
|
|
1094
|
+
// Latched once this terminal is observed re-reporting its size across an
|
|
1095
|
+
// alternate-screen toggle (a pure height change between alt-buffer enter and
|
|
1096
|
+
// exit). That is the Warp-class quirk {@link reportsSizeOnAltScreenToggle}
|
|
1097
|
+
// hardcodes: without it, leaving a fullscreen overlay flashes a destructive
|
|
1098
|
+
// ED3 full paint and the revert SIGWINCH flashes another (#6511). Once set,
|
|
1099
|
+
// {@link #resizeRepaintsInPlace} routes resizes through the in-place path.
|
|
1100
|
+
#altToggleResizesInPlace = false;
|
|
1094
1101
|
#stopped = false;
|
|
1095
1102
|
// Always-on event-loop lag probe. The high default threshold keeps it quiet;
|
|
1096
1103
|
// it only logs `ui.loop-blocked` (with the current loop phase) when a frame
|
|
@@ -1590,8 +1597,26 @@ export class TUI extends Container {
|
|
|
1590
1597
|
// window) into a single render once the pane is quiet —
|
|
1591
1598
|
// `#resizeEventPending` is set first so the eventual render still
|
|
1592
1599
|
// classifies as a resize.
|
|
1600
|
+
// A SIGWINCH while a fullscreen overlay covers the transcript is
|
|
1601
|
+
// either a genuine resize behind the overlay or the alt-toggle size
|
|
1602
|
+
// echo (a terminal re-reporting its size whenever the alternate
|
|
1603
|
+
// screen buffer toggles). The transcript is not visible either way,
|
|
1604
|
+
// so arming the drag/settle would only queue a destructive ED3
|
|
1605
|
+
// rebuild that fires as a flash when the overlay closes (#6511). A
|
|
1606
|
+
// pure height change is the alt-toggle-echo signature — latch the
|
|
1607
|
+
// in-place resize path — and just repaint the overlay at the new
|
|
1608
|
+
// size. #resizeEventPending carries to the overlay-exit render so it
|
|
1609
|
+
// still classifies as a resize.
|
|
1610
|
+
if (this.#altActive) {
|
|
1611
|
+
if (this.#altEnterWidth === this.terminal.columns && this.#altEnterHeight !== this.terminal.rows) {
|
|
1612
|
+
this.#altToggleResizesInPlace = true;
|
|
1613
|
+
}
|
|
1614
|
+
this.#resizeEventPending = true;
|
|
1615
|
+
this.requestRender();
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1593
1618
|
this.#resizeEventPending = true;
|
|
1594
|
-
if (!resizeRepaintsInPlace()) {
|
|
1619
|
+
if (!this.#resizeRepaintsInPlace()) {
|
|
1595
1620
|
// Enter the viewport fast path and (re)arm the settle timer, then
|
|
1596
1621
|
// request the cheap viewport-only paint. The authoritative full
|
|
1597
1622
|
// replay fires from the settle timer once the drag goes quiet.
|
|
@@ -2815,9 +2840,15 @@ export class TUI extends Container {
|
|
|
2815
2840
|
this.#altPreviousLines = [];
|
|
2816
2841
|
// A resize while on the alt buffer reflowed the terminal's saved
|
|
2817
2842
|
// normal screen; it no longer matches our accounting, so force the
|
|
2818
|
-
// geometry rebuild path instead of a stale diff.
|
|
2843
|
+
// geometry rebuild path instead of a stale diff. A pure height change
|
|
2844
|
+
// across the alt-buffer boundary (width unchanged) is the signature of
|
|
2845
|
+
// a terminal that re-reports its size whenever the alternate screen
|
|
2846
|
+
// toggles — the Warp-class quirk. Latch the in-place resize path so
|
|
2847
|
+
// this exit and the revert SIGWINCH repaint without an ED3 scrollback
|
|
2848
|
+
// rewrap instead of flashing a destructive full paint (#6511).
|
|
2819
2849
|
if (width !== this.#altEnterWidth || height !== this.#altEnterHeight) {
|
|
2820
2850
|
this.#resizeEventPending = true;
|
|
2851
|
+
if (width === this.#altEnterWidth) this.#altToggleResizesInPlace = true;
|
|
2821
2852
|
}
|
|
2822
2853
|
} else if (wantMouseTracking !== this.#altMouseTrackingActive) {
|
|
2823
2854
|
this.terminal.write(wantMouseTracking ? MOUSE_TRACKING_ON : MOUSE_TRACKING_OFF);
|
|
@@ -2870,7 +2901,7 @@ export class TUI extends Container {
|
|
|
2870
2901
|
// count too: both enter the geometry rebuild path below.
|
|
2871
2902
|
const replayFullHistory =
|
|
2872
2903
|
this.#hasEverRendered &&
|
|
2873
|
-
!resizeRepaintsInPlace() &&
|
|
2904
|
+
!this.#resizeRepaintsInPlace() &&
|
|
2874
2905
|
(this.#clearScrollbackOnNextRender ||
|
|
2875
2906
|
this.#resizeEventPending ||
|
|
2876
2907
|
(this.#previousWidth > 0 && this.#previousWidth !== width) ||
|
|
@@ -3018,7 +3049,7 @@ export class TUI extends Container {
|
|
|
3018
3049
|
// feedback loop), so committed history keeps its old wrap.
|
|
3019
3050
|
const firstPaint = !this.#hasEverRendered;
|
|
3020
3051
|
const replaceRequested = this.#clearScrollbackOnNextRender;
|
|
3021
|
-
const geometryRebuild = geometryChanged && !resizeRepaintsInPlace();
|
|
3052
|
+
const geometryRebuild = geometryChanged && !this.#resizeRepaintsInPlace();
|
|
3022
3053
|
// Committed history no longer matches the frame: a finalized block
|
|
3023
3054
|
// replaced its scrolled-off live render, or the frame collapsed into
|
|
3024
3055
|
// recorded rows. Native scrollback is a render cache, not a court
|
|
@@ -3175,7 +3206,8 @@ export class TUI extends Container {
|
|
|
3175
3206
|
windowTop,
|
|
3176
3207
|
prevWindowTop,
|
|
3177
3208
|
prevHardwareCursorRow,
|
|
3178
|
-
forceWindowRewrite:
|
|
3209
|
+
forceWindowRewrite:
|
|
3210
|
+
this.#forceViewportRepaintOnNextRender || (geometryChanged && this.#resizeRepaintsInPlace()),
|
|
3179
3211
|
repaintVirtualScrollInPlace: hasVisibleOverlay,
|
|
3180
3212
|
cursorTrackingLineCount,
|
|
3181
3213
|
});
|
|
@@ -3812,6 +3844,21 @@ export class TUI extends Container {
|
|
|
3812
3844
|
return `${enhancementExit}${ALT_SCREEN_EXIT}`;
|
|
3813
3845
|
}
|
|
3814
3846
|
|
|
3847
|
+
/**
|
|
3848
|
+
* Whether a resize repaints the visible window in place — no alternate-screen
|
|
3849
|
+
* borrow, no ED3 scrollback rewrap. Combines the static host detection
|
|
3850
|
+
* ({@link resizeRepaintsInPlace}) with the runtime {@link #altToggleResizesInPlace}
|
|
3851
|
+
* latch, so a terminal that re-reports its size on alt-screen toggles is
|
|
3852
|
+
* treated like Warp once observed, breaking the overlay-exit ED3 flash loop.
|
|
3853
|
+
* An explicit `PI_TUI_RESIZE_IN_PLACE=0|false` suppresses the runtime latch;
|
|
3854
|
+
* multiplexer handling remains authoritative through the static predicate.
|
|
3855
|
+
*/
|
|
3856
|
+
#resizeRepaintsInPlace(): boolean {
|
|
3857
|
+
const override = Bun.env.PI_TUI_RESIZE_IN_PLACE;
|
|
3858
|
+
const allowAutoDetection = override !== "0" && override !== "false";
|
|
3859
|
+
return resizeRepaintsInPlace() || (allowAutoDetection && this.#altToggleResizesInPlace);
|
|
3860
|
+
}
|
|
3861
|
+
|
|
3815
3862
|
/**
|
|
3816
3863
|
* Emit a throwaway viewport repaint for the resize fast path as a per-row
|
|
3817
3864
|
* overwrite. A width change can make the terminal's normal buffer reflow
|