apply PR #5490: fix(tui): refresh dark/light appearance on explicit ctrl+l reset

Cherry-picked 69c9fe8d4; resolved terminal.ts against the newer
onPrivateModeReport signature and unioned appearance tests with the
Windows Terminal polling regression.
This commit is contained in:
can1357
2026-07-17 04:45:22 +02:00
parent 06d11d11a1
commit 4e85f6acee
6 changed files with 110 additions and 2 deletions
+1
View File
@@ -362,6 +362,7 @@
- Removed the `--prewalk-boomerang` feature and its associated configuration setting.
- Removed the unreliable Bing and Yahoo HTML-scraping web search providers.
- Fixed Ctrl+L (`app.display.reset`) not refreshing the dark/light theme on terminals without an end-to-end DEC Mode 2031 notification path (e.g. iTerm2 under tmux): the explicit reset gesture now issues one bounded OSC 11 background re-query before repainting, so a mid-session appearance switch is picked up without restarting. No timers or periodic polling are reintroduced ([#5352](https://github.com/can1357/oh-my-pi/issues/5352))
## [16.4.8] - 2026-07-12
@@ -391,7 +391,16 @@ export class InputController {
this.ctx.editor.onClear = () => this.handleCtrlC();
this.ctx.editor.setActionKeys("app.exit", this.ctx.keybindings.getKeys("app.exit"));
this.ctx.editor.setActionKeys("app.display.reset", this.ctx.keybindings.getKeys("app.display.reset"));
this.ctx.editor.onDisplayReset = () => this.ctx.ui.resetDisplay();
this.ctx.editor.onDisplayReset = () => {
// Explicit user gesture (Ctrl+L): re-query the terminal background once
// so a mid-session light/dark switch is picked up even on terminals
// without an end-to-end Mode 2031 notification path (#5352). The
// appearance callback re-evaluates the auto theme; the repaint below
// then renders the resolved palette. Bounded to one OSC 11 probe per
// gesture — no timers, no periodic polling.
this.ctx.ui.terminal.refreshAppearance?.();
this.ctx.ui.resetDisplay();
};
this.ctx.editor.onExit = () => this.handleCtrlD();
this.ctx.editor.setActionKeys("app.suspend", this.ctx.keybindings.getKeys("app.suspend"));
this.ctx.editor.onSuspend = () => this.handleCtrlZ();
@@ -79,6 +79,7 @@ async function createContext() {
});
const addStartListener = vi.fn();
const terminalWrite = vi.fn();
const refreshAppearance = vi.fn();
const prompt = vi.fn(async () => {});
const retry = vi.fn(async () => true);
const abort = vi.fn(async () => {});
@@ -135,7 +136,7 @@ async function createContext() {
addInputListener,
addStartListener,
getFocused: vi.fn(() => focused),
terminal: { write: terminalWrite },
terminal: { write: terminalWrite, refreshAppearance },
} as unknown as InteractiveModeContext["ui"],
loadingAnimation: undefined,
autoCompactionLoader: undefined,
@@ -217,6 +218,7 @@ async function createContext() {
retry,
abort,
resetDisplay,
refreshAppearance,
handleBtwBranchKey,
addInputListener,
canBranchBtw,
@@ -249,6 +251,12 @@ describe("InputController keybinding setup", () => {
expect(spies.showModelSelector).toHaveBeenNthCalledWith(1, { temporaryOnly: true });
expect(spies.showModelSelector).toHaveBeenNthCalledWith(2);
expect(spies.resetDisplay).toHaveBeenCalledTimes(1);
expect(spies.refreshAppearance).toHaveBeenCalledTimes(1);
// The background re-query must run before the repaint so the appearance
// callback re-evaluates the auto theme against the fresh classification.
expect(spies.refreshAppearance.mock.invocationCallOrder[0]!).toBeLessThan(
spies.resetDisplay.mock.invocationCallOrder[0]!,
);
});
it("does not mark pasted shell prompts as Python mode while editing", async () => {