дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 03:05:40 +02:00
fix(search): keep Search Everywhere's keys from the editor's actions behind it (#1114)
The capture-phase keymap ran editor actions on keys the Search Everywhere field handles, since editor actions apply while a popup is open over an editor: ⌥↵ ran Show Context Actions instead of Assign Shortcut, and ⌥↑/⌥↓ and the other navigation keys could reach the editor too. The field now claims the keys its onKeyDown handles while it has focus.
Цей коміт міститься в:
1 джерело
2bb8f3b091
коміт
809c6adcf1
2 files changed
+48
-1
No files matched your search
@@ -0,0 +1,36 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { registerAction } from "@/platform/actions";
|
||||
import { setContext } from "@/platform/context";
|
||||
import { installKeyboardDispatcher, useKeymap } from "@/platform/keymap";
|
||||
import { claimSearchKeys } from "../everywhere/SearchEverywhere";
|
||||
|
||||
const disposers: Array<() => void> = [];
|
||||
afterEach(() => {
|
||||
disposers.splice(0).forEach((d) => d());
|
||||
document.body.innerHTML = "";
|
||||
});
|
||||
|
||||
describe("Search Everywhere's query field", () => {
|
||||
it("keeps ⌥↵ and the navigation keys from the editor's actions behind the popup", () => {
|
||||
const intentions = vi.fn();
|
||||
const extend = vi.fn();
|
||||
useKeymap.setState({ overrides: { "t.intentions": ["Alt+Enter"], "t.extend": ["Alt+ArrowUp"] } } as never);
|
||||
setContext("textEditorActive", true);
|
||||
const input = document.body.appendChild(document.createElement("input"));
|
||||
const other = document.body.appendChild(document.createElement("input"));
|
||||
disposers.push(
|
||||
registerAction({ id: "t.intentions", title: "Show Context Actions", run: intentions }),
|
||||
registerAction({ id: "t.extend", title: "Extend Selection", run: extend }),
|
||||
installKeyboardDispatcher(window),
|
||||
claimSearchKeys(() => input),
|
||||
);
|
||||
const press = (target: HTMLElement, key: string) =>
|
||||
target.dispatchEvent(new KeyboardEvent("keydown", { key, altKey: true, bubbles: true, cancelable: true }));
|
||||
press(input, "Enter");
|
||||
press(input, "ArrowUp");
|
||||
expect(intentions).not.toHaveBeenCalled();
|
||||
expect(extend).not.toHaveBeenCalled();
|
||||
press(other, "Enter");
|
||||
expect(intentions).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
@@ -4,7 +4,7 @@ import clsx from "clsx";
|
||||
import { actionToggled, executeAction, executeActionFrom, getAction } from "@/platform/actions";
|
||||
import type { ProjectFileSet } from "@/platform/ipc";
|
||||
import { tx as translate, useTx } from "@/platform/i18n";
|
||||
import { hasPrimaryModifier, shortcutLabel } from "@/platform/keymap";
|
||||
import { hasPrimaryModifier, registerKeyClaim, shortcutLabel } from "@/platform/keymap";
|
||||
import {
|
||||
Checkbox,
|
||||
Dialog,
|
||||
@@ -73,6 +73,13 @@ const SE_SCOPES: Array<{ value: SeScope; label: string }> = [
|
||||
{ value: "test", label: "Project Test Files" },
|
||||
];
|
||||
|
||||
/** Keys the query field handles itself (`onKeyDown`), in every modifier combination. */
|
||||
const SEARCH_KEYS: ReadonlySet<string> = new Set(["Enter", "Tab", "ArrowUp", "ArrowDown", "PageUp", "PageDown"]);
|
||||
|
||||
/** Keeps the global keymap off the keys the query field handles while it has focus. */
|
||||
export function claimSearchKeys(input: () => HTMLElement | null): () => void {
|
||||
return registerKeyClaim((e) => e.target === input() && SEARCH_KEYS.has(e.key));
|
||||
}
|
||||
const ROW = 24;
|
||||
const MAX_LIST = 672;
|
||||
const MIN_LIST = 10 * ROW;
|
||||
@@ -313,6 +320,10 @@ function SearchEverywhereDialog() {
|
||||
activateSelection(pending.side);
|
||||
});
|
||||
|
||||
// The keys the input handles below are its own: with an editor open, the global keymap would
|
||||
// otherwise run editor actions on them (⌥↵ Show Context Actions, ⌥↑ Extend Selection…).
|
||||
useEffect(() => claimSearchKeys(() => inputRef.current), []);
|
||||
|
||||
/** IDEA's ⌥↵ on an action: record a shortcut for it (written to the active keymap). */
|
||||
const assignShortcut = (id: string) => closeThen(() => void executeAction("settings.assignShortcut", id));
|
||||
|
||||
|
||||
Reference in new issue
Заблокувати користувача