fix(player): guard the play overlay against the synthesized touch click
After the DR-098 tap rewrite, pausing became impossible while unpausing always worked — an asymmetry that pointed straight at the overlay. Pausing renders a full-screen play-overlay button over the video. The compatibility click Android synthesizes from the tap arrives ~30-130ms later, by which time that button exists, so the click lands on the OVERLAY rather than the <video>. Its onclick called togglePlayPause with no guard at all, resuming immediately. Unpausing was unaffected because it removes the overlay, leaving nothing to intercept the click. The suppression rule was only wired into the video element's handler. Extract it as isSynthesizedTouchClick() in tapGestures.ts (unit-tested) and use it from every click target layered over the video, the overlay included. Verified: 724 frontend tests pass, svelte-check clean. Bumped to 0.2.5 so the APK installs over 2004.
This commit is contained in:
@@ -24,6 +24,34 @@
|
||||
/** A second tap within this window pairs with the previous one (seek + re-toggle). */
|
||||
export const DOUBLE_TAP_WINDOW_MS = 300;
|
||||
|
||||
/**
|
||||
* How long after a touch tap a mouse `click` is assumed to be the compatibility
|
||||
* event the browser synthesizes from that touch. Android's WebView can deliver it
|
||||
* noticeably late, so this is generous.
|
||||
*/
|
||||
export const TOUCH_CLICK_SUPPRESS_MS = 700;
|
||||
|
||||
/**
|
||||
* Whether a `click` should be ignored because a touch tap already handled it.
|
||||
*
|
||||
* EVERY click target layered over the video must consult this — not just the
|
||||
* `<video>` element. Pausing swaps in a full-screen play-overlay button, so the
|
||||
* synthesized click lands on *that* button rather than the video, and an
|
||||
* unguarded handler there re-toggles and undoes the pause (pause appeared
|
||||
* impossible while unpause worked, because unpausing removes the overlay).
|
||||
*
|
||||
* `detail === 0` catches the synthesized click on engines that report it; the
|
||||
* recency check covers engines that report a real `detail`.
|
||||
*/
|
||||
export function isSynthesizedTouchClick(
|
||||
detail: number,
|
||||
now: number,
|
||||
lastTouchTapAt: number
|
||||
): boolean {
|
||||
if (detail === 0) return true;
|
||||
return now - lastTouchTapAt < TOUCH_CLICK_SUPPRESS_MS;
|
||||
}
|
||||
|
||||
/** Double tap on the right half: skip forward. */
|
||||
export const SEEK_FORWARD_SECONDS = 30;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user