fix(editor): preserve multi-click selection drags

This commit is contained in:
Eve authored and GitHub committed 2026-09-10 14:30:23 +08:00
1 parent b37f63e716
commit a688aadec2
4 files changed
+20 -19

No files matched your search

@@ -137,7 +137,7 @@ import { sqlBlockFoldService } from "@/lib/editor/codemirrorSqlBlockFolding";
import { focusEditorView } from "@/lib/editor/queryEditorFocus";
import { createDbxCodeMirrorSqlDialect, type CodeMirrorSqlDialectName } from "@/lib/editor/codemirrorSqlDialect";
import { sqlSemanticTableNameSpansForSyntaxTree } from "@/lib/editor/codemirrorSqlSemanticHighlight";
import { startsQueryEditorRectangularSelection, usesQueryEditorObjectNavigationModifier } from "@/lib/editor/queryEditorPointerSelection";
import { startsQueryEditorRectangularSelection, startsQueryEditorSelectionDrag, usesQueryEditorObjectNavigationModifier } from "@/lib/editor/queryEditorPointerSelection";
import { LARGE_PASTE_HISTORY_USER_EVENT, normalizeQueryEditorPasteText, recoverableNativePasteSuffix, shouldRecoverLargeTauriPaste } from "@/lib/editor/queryEditorLargePaste";
import { computePasteCaretResyncTarget } from "@/lib/editor/queryEditorPasteCaretResync";
import { queryEditorCommentTokens, queryEditorLineCommentToken, queryEditorWordLanguageData } from "@/lib/editor/queryEditorLineComment";
@@ -1417,10 +1417,7 @@ function updateEditorSelectionDropCursor(currentView: EditorViewType, event: Mou
}
function startEditorSelectionDrag(currentView: EditorViewType, event: MouseEvent): boolean {
// Shift is CodeMirror's native extend-selection gesture. Keep it out of the
// custom selection drag path so a shift-click inside the current selection
// extends or shrinks the selection instead of collapsing it to the cursor.
if (event.shiftKey) return false;
if (!startsQueryEditorSelectionDrag(event)) return false;
const selection = selectedRangeAtPointer(currentView, event);
if (!selection) return false;
@@ -199,16 +199,3 @@ describe("QueryEditor batch column selection", () => {
expect(source).toContain("maxRenderedOptions: batchColumnSelectionExpandedRendering ? Number.MAX_SAFE_INTEGER : 100,");
});
});
describe("QueryEditor pointer selection", () => {
it("lets CodeMirror handle shift-click instead of starting the selection drag gesture", () => {
const start = source.indexOf("function startEditorSelectionDrag");
const end = source.indexOf("\n}\n\nfunction executeFromContextMenu", start);
const dragSource = source.slice(start, end);
expect(start).toBeGreaterThanOrEqual(0);
expect(end).toBeGreaterThan(start);
expect(dragSource).toContain("if (event.shiftKey) return false;");
expect(dragSource.indexOf("if (event.shiftKey) return false;")).toBeLessThan(dragSource.indexOf("const selection = selectedRangeAtPointer"));
});
});
@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { startsQueryEditorRectangularSelection, usesQueryEditorObjectNavigationModifier } from "@/lib/editor/queryEditorPointerSelection";
import { startsQueryEditorRectangularSelection, startsQueryEditorSelectionDrag, usesQueryEditorObjectNavigationModifier } from "@/lib/editor/queryEditorPointerSelection";
describe("query editor pointer selection", () => {
it("starts rectangular selection for Alt+left drag", () => {
@@ -14,6 +14,14 @@ describe("query editor pointer selection", () => {
expect(startsQueryEditorRectangularSelection({ altKey: false, button: 0 })).toBe(false);
});
it("leaves multi-click and Shift selection gestures to CodeMirror", () => {
expect(startsQueryEditorSelectionDrag({ detail: 0, shiftKey: false })).toBe(true);
expect(startsQueryEditorSelectionDrag({ detail: 1, shiftKey: false })).toBe(true);
expect(startsQueryEditorSelectionDrag({ detail: 1, shiftKey: true })).toBe(false);
expect(startsQueryEditorSelectionDrag({ detail: 2, shiftKey: false })).toBe(false);
expect(startsQueryEditorSelectionDrag({ detail: 3, shiftKey: false })).toBe(false);
});
it("uses Cmd or Ctrl without Alt for object navigation", () => {
expect(usesQueryEditorObjectNavigationModifier({ altKey: false, ctrlKey: false, metaKey: true })).toBe(true);
expect(usesQueryEditorObjectNavigationModifier({ altKey: false, ctrlKey: true, metaKey: false })).toBe(true);
@@ -3,6 +3,11 @@ export interface QueryEditorPointerEvent {
button: number;
}
export interface QueryEditorSelectionDragEvent {
detail: number;
shiftKey: boolean;
}
export interface QueryEditorObjectNavigationModifierEvent {
altKey: boolean;
ctrlKey: boolean;
@@ -13,6 +18,10 @@ export function startsQueryEditorRectangularSelection(event: QueryEditorPointerE
return event.altKey || event.button === 1;
}
export function startsQueryEditorSelectionDrag(event: QueryEditorSelectionDragEvent): boolean {
return !event.shiftKey && event.detail <= 1;
}
export function usesQueryEditorObjectNavigationModifier(event: QueryEditorObjectNavigationModifierEvent): boolean {
return !event.altKey && (event.metaKey || event.ctrlKey);
}