Files
feuerwerk/src/ui/clicks.ts
T
root ed1fe31c77 Count clicks ourselves so double-clicks work at all
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.
2026-09-09 14:13:05 +02:00

49 lines
1.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
}