дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 11:15:40 +02:00
fix(ui): treat every second click of a burst as a double-click
WebKit fires `dblclick` only for the second click of a burst. A quick double-click right after another arrives as `click` with `detail` 3 and 4 and no `dblclick`, so the second double-click on a folder in the Project view (and on any tree row, tab or list item handled by `onDoubleClick`) did nothing. A window-level shim now dispatches a `dblclick` on the click's target for every later even click of a burst (detail 4, 6, ...), after the page's own click handlers. Existing `onDoubleClick` handlers and their `stopPropagation` apply unchanged; an engine that fires its own `dblclick` for that click gets it dropped as a duplicate. The Project view test now delivers bursts the way WebKit does (`dblclick` only at detail 2) and checks both expand modes over 2–6 click bursts. Refs #724
Цей коміт міститься в:
1 джерело
eefe166cf7
коміт
329ad2c644
4 files changed
+151
-23
No files matched your search
@@ -1,6 +1,7 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { act, fireEvent, render, screen, waitFor, within } from "@testing-library/react";
|
||||
import { emitLocalIdeEvent } from "@/platform/ipc";
|
||||
import { installRepeatedDoubleClick } from "@/platform/doubleClick";
|
||||
import { getContext } from "@/platform/context";
|
||||
import { provideEditorService, registerProjectViewRoot, type EditorService } from "@/workbench/contributions";
|
||||
import { activate } from "./index";
|
||||
@@ -211,29 +212,34 @@ describe("ProjectView", () => {
|
||||
});
|
||||
|
||||
it("toggles folders once for each rapid double-click pair", async () => {
|
||||
const { row, rows } = setup();
|
||||
await waitFor(() => expect(rows()).toContain("README.md"));
|
||||
act(() => setViewOption("singleClickExpand", true));
|
||||
const content = () => row("src").querySelector("[data-project-path]")!;
|
||||
const click = (detail: number) => {
|
||||
fireEvent.mouseDown(row("src"), { detail });
|
||||
fireEvent.click(content(), { detail });
|
||||
};
|
||||
click(1);
|
||||
click(2);
|
||||
fireEvent.doubleClick(content(), { detail: 2 });
|
||||
await waitFor(() => expect(rows()).toContain("App.kt"));
|
||||
click(3);
|
||||
click(4);
|
||||
fireEvent.doubleClick(content(), { detail: 4 });
|
||||
expect(rows()).not.toContain("App.kt");
|
||||
|
||||
act(() => setViewOption("singleClickExpand", false));
|
||||
click(5);
|
||||
click(6);
|
||||
expect(rows()).not.toContain("App.kt");
|
||||
fireEvent.doubleClick(content(), { detail: 6 });
|
||||
await waitFor(() => expect(rows()).toContain("App.kt"));
|
||||
const uninstall = installRepeatedDoubleClick();
|
||||
try {
|
||||
const { row, rows } = setup();
|
||||
await waitFor(() => expect(rows()).toContain("README.md"));
|
||||
const content = () => row("src").querySelector("[data-project-path]")!;
|
||||
// WebKit fires `dblclick` only for the second click of a burst, never for the 4th or 6th.
|
||||
const burst = (clicks: number) => {
|
||||
for (let detail = 1; detail <= clicks; detail++) {
|
||||
fireEvent.mouseDown(row("src"), { detail });
|
||||
fireEvent.click(content(), { detail });
|
||||
if (detail === 2) fireEvent.doubleClick(content(), { detail });
|
||||
}
|
||||
};
|
||||
// Double-click mode toggles once per pair; single-click mode once per odd click.
|
||||
let expanded = false;
|
||||
for (const singleClickExpand of [false, true]) {
|
||||
act(() => setViewOption("singleClickExpand", singleClickExpand));
|
||||
for (const clicks of [2, 4, 6, 3, 5]) {
|
||||
burst(clicks);
|
||||
const toggles = singleClickExpand ? Math.ceil(clicks / 2) : Math.floor(clicks / 2);
|
||||
if (toggles % 2) expanded = !expanded;
|
||||
await waitFor(() => expect(rows().includes("App.kt")).toBe(expanded));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
uninstall();
|
||||
act(() => setViewOption("singleClickExpand", false));
|
||||
}
|
||||
});
|
||||
|
||||
it("cancels a new file when its name field loses focus", async () => {
|
||||
|
||||
Reference in new issue
Заблокувати користувача