feat(ui): enable "TerminalBuffer" mode to solve flicker (#24512)

This commit is contained in:
Jacob Richman
2026-04-02 17:39:49 -07:00
committed by GitHub
parent 1ae0499e5d
commit 1f5d7014c6
53 changed files with 694 additions and 286 deletions
@@ -176,6 +176,8 @@ export const createMockConfig = (overrides: Partial<Config> = {}): Config =>
getHasAccessToPreviewModel: vi.fn().mockReturnValue(false),
validatePathAccess: vi.fn().mockReturnValue(null),
getUseAlternateBuffer: vi.fn().mockReturnValue(false),
getUseTerminalBuffer: vi.fn().mockReturnValue(false),
getUseRenderProcess: vi.fn().mockReturnValue(false),
...overrides,
}) as unknown as Config;
+7 -2
View File
@@ -223,7 +223,7 @@ class XtermStdout extends EventEmitter {
this.once('render', resolve),
);
const timeoutPromise = new Promise((resolve) =>
setTimeout(resolve, 50),
setTimeout(resolve, 1000),
);
await Promise.race([renderPromise, timeoutPromise]);
}
@@ -254,7 +254,12 @@ class XtermStdout extends EventEmitter {
const isMatch = () => {
if (expectedFrame === '...') {
return currentFrame !== '';
// '...' is our fallback when output isn't in metrics, meaning Ink rendered *something*
// but we don't know what it is. If terminal has content, we consider it a match.
// However, if the component rendered null, both would be empty, but our fallback
// made expectedFrame '...'. In that case, we can't easily know if it's ready,
// but we can assume if there are no pending writes, it's ready.
return currentFrame !== '' || this.pendingWrites === 0;
}
// If Ink expects nothing (no new static content and no dynamic output),