Pixi only fills `detail` on the `click` event it synthesises; on `pointerdown` it is always 0, so every `e.detail === 2` branch was dead code. Asset rows, hierarchy folding and select-all in text fields never responded to a double-click. A shared click counter in src/ui/clicks.ts replaces the three readings of `e.detail`. A finished double-click ends the run, so two in a row count 2 and 2 rather than 3 and 4. The harness could only send `clickCount: 1`, which is why no test caught this: every "activate" check went through Enter. It can send real double-clicks now, and five checks drive the three paths separately.
49 lines
1.6 KiB
TypeScript
49 lines
1.6 KiB
TypeScript
import type { FederatedPointerEvent } from 'pixi.js';
|
||
|
||
/** Longest gap between two presses that still reads as one double-click. */
|
||
const DOUBLE_MS = 400;
|
||
/** How far the pointer may travel between them. */
|
||
const SLOP = 6;
|
||
|
||
interface LastPress {
|
||
key: unknown;
|
||
button: number;
|
||
time: number;
|
||
x: number;
|
||
y: number;
|
||
count: number;
|
||
}
|
||
|
||
let last: LastPress = { key: null, button: -1, time: 0, x: 0, y: 0, count: 0 };
|
||
|
||
/**
|
||
* How often `key` was pressed in a row with the same button – 2 on a double-click. Pixi counts
|
||
* clicks only for the `click`/`pointertap` it synthesises and leaves `detail` at 0 on
|
||
* `pointerdown`, so a press handler reading `e.detail` never sees a second click.
|
||
*
|
||
* `key` identifies what was hit and should survive a rebuild of the widget it belongs to: list
|
||
* rows are thrown away and recreated whenever the list refreshes, which a selection – the first
|
||
* click – can trigger.
|
||
*/
|
||
export function pressCount(e: FederatedPointerEvent, key: unknown): number {
|
||
const gap = e.timeStamp - last.time;
|
||
const repeat =
|
||
key === last.key &&
|
||
e.button === last.button &&
|
||
gap >= 0 &&
|
||
gap <= DOUBLE_MS &&
|
||
Math.hypot(e.global.x - last.x, e.global.y - last.y) <= SLOP;
|
||
const count = repeat ? last.count + 1 : 1;
|
||
last = {
|
||
key,
|
||
button: e.button,
|
||
time: e.timeStamp,
|
||
x: e.global.x,
|
||
y: e.global.y,
|
||
// A finished double-click ends the run: folding a row open and shut again is two
|
||
// double-clicks, and the second must count as one rather than as clicks three and four.
|
||
count: count === 2 ? 0 : count,
|
||
};
|
||
return count;
|
||
}
|