fix(editor): clear stale text focus when switching tabs

This commit is contained in:
l0ng-ai
2026-10-29 22:42:19 +08:00
parent f6a0152488
commit b9cfd54742
2 changed files with 71 additions and 1 deletions
+70 -1
View File
@@ -1,4 +1,4 @@
import { afterEach, describe, expect, it } from "vitest";
import { afterEach, describe, expect, it, vi } from "vitest";
import { EditorController, openFilePaths, useEditorStatus, useTabs } from "./controller";
import { createMemoryBackend } from "./backend";
import { initialTabsState } from "./model/tabs";
@@ -7,6 +7,9 @@ import { resetDistractionFree, setDistractionFree } from "@/workbench/distractio
import { registerActions } from "@/platform/actions";
import { useProject } from "@/platform/project";
import { resolveMenuItems } from "@/ui";
import { getContext } from "@/platform/context";
import { installKeyboardDispatcher } from "@/platform/keymap";
import { TEXT_WHEN } from "./actions";
let ctrl: EditorController | null = null;
@@ -18,6 +21,72 @@ afterEach(() => {
});
describe("EditorController", () => {
it("leaves modified Enter to a non-text editor after switching from a focused file", async () => {
ctrl = new EditorController(createMemoryBackend({ "/p/a.ts": "one\ntwo\n" }));
ctrl.start();
await ctrl.openFile("/p/a.ts", { focus: false });
const slot = ctrl.activeSlot!;
const host = document.createElement("div");
document.body.appendChild(host);
const view = slot.mount(host);
ctrl.onMounted(slot);
view.focus();
await vi.waitFor(() => expect(getContext().editorTextFocus).toBe(true));
const splitLine = vi.fn();
const dispose = registerActions([
{
id: "code.splitLine",
title: "Split Line",
when: TEXT_WHEN,
run: splitLine,
},
]);
const uninstall = installKeyboardDispatcher(window);
const message = document.createElement("textarea");
const send = vi.fn();
message.addEventListener("keydown", send);
try {
await ctrl.openInput({ kind: "agent-session", key: "task" });
slot.unmount();
host.appendChild(message);
message.focus();
message.dispatchEvent(
new KeyboardEvent("keydown", {
key: "Enter",
code: "Enter",
metaKey: true,
bubbles: true,
cancelable: true,
}),
);
expect(splitLine).not.toHaveBeenCalled();
expect(send).toHaveBeenCalledOnce();
expect(getContext().editorTextFocus).toBe(false);
await ctrl.openFile("/p/a.ts", { focus: false });
const reopened = slot.mount(host);
ctrl.onMounted(slot);
reopened.focus();
await vi.waitFor(() => expect(getContext().editorTextFocus).toBe(true));
reopened.contentDOM.dispatchEvent(
new KeyboardEvent("keydown", {
key: "Enter",
code: "Enter",
metaKey: true,
bubbles: true,
cancelable: true,
}),
);
expect(splitLine).toHaveBeenCalledOnce();
} finally {
uninstall();
dispose();
slot.unmount();
host.remove();
}
});
it("updates the caret status synchronously on programmatic selection changes", async () => {
ctrl = new EditorController(createMemoryBackend({ "/p/a.ts": "one\ntwo\nthree\n" }));
ctrl.start();
+1
View File
@@ -713,6 +713,7 @@ export class EditorController implements SlotHost {
Object.values(s.panes).some((p) => p.tabs.length > 0),
);
setContext("editorSplit", paneIds(s).length > 1);
setContext("editorTextFocus", !!slot?.view?.hasFocus);
setContext("textEditorActive", !!slot);
}