mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
fix(tui,coding-agent): clear fullscreen selection on transcript rebuild (#10567)
Selection coordinates survived session switches and other transcript rebuilds, highlighting unrelated text in the new transcript. Reset selection and multi-click state before re-rendering session entries. Based on #9310. fixes #9311 Co-authored-by: xdagiz <xdagiz@protonmail.com>
This commit is contained in:
parent
8b5708dbb1
commit
83c9e26453
3 changed files with 48 additions and 0 deletions
|
|
@ -4054,6 +4054,8 @@ export class InteractiveMode {
|
|||
entries: SessionEntry[],
|
||||
options: { updateFooter?: boolean; populateHistory?: boolean } = {},
|
||||
): void {
|
||||
// Selection coordinates point into the transcript being replaced (#9311).
|
||||
if (this.renderer instanceof TuiAltScreen) this.renderer.resetTextSelection();
|
||||
const items = entries.flatMap((entry): RenderSessionItem[] => {
|
||||
if (entry.type === "custom" || (entry.type === "usage" && entry.kind === "cache_warm")) {
|
||||
return [entry];
|
||||
|
|
|
|||
|
|
@ -363,6 +363,46 @@ describe("InteractiveMode copy confirmation", () => {
|
|||
});
|
||||
});
|
||||
|
||||
type RenderSessionEntriesContext = {
|
||||
renderer: ReturnType<typeof createInteractiveTui>;
|
||||
renderSessionItems: (items: unknown[]) => void;
|
||||
};
|
||||
|
||||
describe("InteractiveMode transcript rebuild", () => {
|
||||
it("drops the fullscreen selection when session entries are re-rendered", async () => {
|
||||
// Regression test for #9311: selection coordinates survived session switches.
|
||||
const terminal = new RecordingTerminal(40, 4);
|
||||
const ui = createInteractiveTui({
|
||||
tuiMode: "fullscreen",
|
||||
showHardwareCursor: false,
|
||||
logDirectory: "/tmp",
|
||||
terminal,
|
||||
fullscreenCopyOnSelect: false,
|
||||
});
|
||||
ui.addChild(new Text("alpha\nbeta\ngamma\ndelta", 0, 0));
|
||||
const context: RenderSessionEntriesContext = { renderer: ui, renderSessionItems: vi.fn() };
|
||||
const { renderSessionEntries } = InteractiveMode.prototype as unknown as {
|
||||
renderSessionEntries(this: RenderSessionEntriesContext, entries: unknown[]): void;
|
||||
};
|
||||
|
||||
ui.start();
|
||||
try {
|
||||
await terminal.waitForRender();
|
||||
terminal.sendInput("\x1b[<0;1;1M");
|
||||
terminal.sendInput("\x1b[<32;4;2M");
|
||||
terminal.sendInput("\x1b[<0;4;2m");
|
||||
await terminal.waitForRender();
|
||||
expect(ui.hasActiveSelection()).toBe(true);
|
||||
|
||||
renderSessionEntries.call(context, []);
|
||||
|
||||
expect(ui.hasActiveSelection()).toBe(false);
|
||||
} finally {
|
||||
ui.stop();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
type StatusEditor = {
|
||||
embedWorkingStatus: boolean;
|
||||
setWorkingStatusIndicator: (indicator: StatusIndicator | undefined) => void;
|
||||
|
|
|
|||
|
|
@ -313,6 +313,12 @@ export class TuiAltScreen extends TuiBase implements ViewportTUI {
|
|||
return this.copyTextToClipboard(text);
|
||||
}
|
||||
|
||||
/** Drop the text selection and multi-click history, e.g. before the host replaces the transcript. */
|
||||
resetTextSelection(): void {
|
||||
this.clearTextSelection();
|
||||
this.lastClick = undefined;
|
||||
}
|
||||
|
||||
/** The lines of the last rendered frame, one per terminal row, as written to the terminal. */
|
||||
getScreenLines(): string[] {
|
||||
return [...this.previousScreen];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue