fix(editor): Ctrl/⌘-hover info replaces hover popups instead of stacking (#60)

Root cause: the quick-doc/problem hover and the Ctrl/⌘-hover navigation info were independent tooltips with no precedence, and the navigation modifier was only seen through the focused editor's key events, so holding Ctrl stacked both popups.

Fix: a window-wide platform navigation modifier (`src/platform/navigationModifier.ts`, ⌘ on macOS / Ctrl elsewhere, unchorded); with it held the plain hover doesn't open, late LSP results are dropped, an open hover closes (unless the pointer is inside it, so Ctrl/⌘+C still copies), release clears the link and info.

Siblings: problem/diagnostic hover, debugger value tooltip, inlay hint hovers (no doc or underline through hints, platform-correct Ctrl/⌘-click), consistent ⌘ vs ⌃ handling on macOS.

Verified in the app on macOS (⌘): hover then ⌘ leaves only the nav info, ⌘ before hover shows only nav info, release clears both and plain hover returns. Not verified on Windows.

Fixes #57

https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
Цей коміт міститься в:
l0ng-ai authored and GitHub committed 2026-10-27 11:46:04 +08:00
1 джерело 7146779f6c
коміт e16253a890
7 files changed
+307 -56

No files matched your search

+4 -1
Переглянути файл
@@ -6,6 +6,7 @@
import type { Extension } from "@codemirror/state";
import { hoverTooltip, type EditorView } from "@codemirror/view";
import { workflowSettings } from "@/platform/workflowSettings";
import { navigationModifierHeld } from "@/platform/navigationModifier";
import { activeSession, evaluate } from "../state";
import { inlineValue } from "../values";
import { tx } from "@/platform/i18n";
@@ -40,7 +41,8 @@ export function valueTooltip(): Extension {
return hoverTooltip(
async (view, pos) => {
const dbg = workflowSettings().debugger;
if (!dbg.valueTooltip) return null;
// ⌘/Ctrl-hover shows the navigation info instead (closed on press by the LSP hover).
if (!dbg.valueTooltip || navigationModifierHeld()) return null;
const session = activeSession();
if (!session || session.status !== "paused") return null;
const expr = expressionAt(view, pos);
@@ -53,6 +55,7 @@ export function valueTooltip(): Extension {
} catch {
return null;
}
if (navigationModifierHeld()) return null;
return {
pos: expr.from,
end: expr.to,