diff --git a/src/components/canvas/players/player.ts b/src/components/canvas/players/player.ts
index 81efb1a..644a42b 100644
--- a/src/components/canvas/players/player.ts
+++ b/src/components/canvas/players/player.ts
@@ -59,7 +59,6 @@ export enum PlayerType {
*/
export abstract class Player extends Entity {
private static readonly DiscardedFrameCount = 0;
- private static readonly DoubleClickThresholdMs = 350;
public layer: number;
public shouldDispose: boolean;
@@ -493,13 +492,8 @@ export abstract class Player extends Entity {
return this.getPlaybackTime() < Player.DiscardedFrameCount;
}
- /** Timestamp of last single-click on this player, used for double-click detection. */
- private lastClickAt = 0;
-
/**
- * Handle pointer down - emit click event for selection handling.
- * Two clicks within DoubleClickThresholdMs on the same player also emit
- * CanvasClipDoubleClicked so text-clip editing can be triggered from the canvas.
+ * Handle pointer down — emit click event for selection handling.
* All drag/resize/rotate interaction is handled by SelectionHandles.
*/
private onPointerDown(event: pixi.FederatedPointerEvent): void {
@@ -508,14 +502,6 @@ export abstract class Player extends Entity {
}
this.edit.getInternalEvents().emit(InternalEvent.CanvasClipClicked, { player: this });
-
- const now = performance.now();
- if (now - this.lastClickAt <= Player.DoubleClickThresholdMs) {
- this.edit.getInternalEvents().emit(InternalEvent.CanvasClipDoubleClicked, { player: this });
- this.lastClickAt = 0;
- } else {
- this.lastClickAt = now;
- }
}
private clipHasKeyframes(): boolean {
diff --git a/src/core/edit-session.ts b/src/core/edit-session.ts
index f9106af..3e37ba6 100644
--- a/src/core/edit-session.ts
+++ b/src/core/edit-session.ts
@@ -2236,15 +2236,34 @@ export class Edit {
return bestMatch;
}
+ private lastClipClick: { player: Player; at: number } | null = null;
+ private static readonly DoubleClickThresholdMs = 500;
+
// ─── Intent Listeners ────────────────────────────────────────────────────────
private setupIntentListeners(): void {
this.internalEvents.on(InternalEvent.CanvasClipClicked, data => {
- this.selectPlayer(data.player);
+ const wasSelected = this.getSelectedClipInfo()?.player === data.player;
+
+ if (!wasSelected) {
+ this.selectPlayer(data.player);
+ this.lastClipClick = null;
+ return;
+ }
+
+ const now = performance.now();
+ const within = this.lastClipClick && now - this.lastClipClick.at <= Edit.DoubleClickThresholdMs;
+ if (this.lastClipClick?.player === data.player && within) {
+ this.internalEvents.emit(InternalEvent.CanvasClipDoubleClicked, { player: data.player });
+ this.lastClipClick = null;
+ } else {
+ this.lastClipClick = { player: data.player, at: now };
+ }
});
this.internalEvents.on(InternalEvent.CanvasBackgroundClicked, () => {
this.clearSelection();
+ this.lastClipClick = null;
});
}
diff --git a/src/core/ui/base-toolbar.ts b/src/core/ui/base-toolbar.ts
index 3151538..b60298d 100644
--- a/src/core/ui/base-toolbar.ts
+++ b/src/core/ui/base-toolbar.ts
@@ -43,8 +43,7 @@ export const TOOLBAR_ICONS = {
chevron: `