web: Allow context menu to work on iOS using PointerEvents (#9598)
Co-authored-by: nosamu <71368227+n0samu@users.noreply.github.com>
This commit is contained in:
parent
e17b154d47
commit
bcbf8c9108
|
@ -133,6 +133,9 @@ export class RufflePlayer extends HTMLElement {
|
||||||
// Whether this device is a touch device.
|
// Whether this device is a touch device.
|
||||||
// Set to true when a touch event is encountered.
|
// Set to true when a touch event is encountered.
|
||||||
private isTouch = false;
|
private isTouch = false;
|
||||||
|
// Whether this device sends contextmenu events.
|
||||||
|
// Set to true when a contextmenu event is seen.
|
||||||
|
private contextMenuSupported = false;
|
||||||
|
|
||||||
// The effective config loaded upon `.load()`.
|
// The effective config loaded upon `.load()`.
|
||||||
private loadedConfig: Required<Config> = DEFAULT_CONFIG;
|
private loadedConfig: Required<Config> = DEFAULT_CONFIG;
|
||||||
|
@ -148,6 +151,7 @@ export class RufflePlayer extends HTMLElement {
|
||||||
private _cachedDebugInfo: string | null = null;
|
private _cachedDebugInfo: string | null = null;
|
||||||
|
|
||||||
private isExtension = false;
|
private isExtension = false;
|
||||||
|
private longPressTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggered when a movie metadata has been loaded (such as movie width and height).
|
* Triggered when a movie metadata has been loaded (such as movie width and height).
|
||||||
|
@ -219,8 +223,21 @@ export class RufflePlayer extends HTMLElement {
|
||||||
this.preloader = this.shadow.getElementById("preloader")!;
|
this.preloader = this.shadow.getElementById("preloader")!;
|
||||||
|
|
||||||
this.contextMenuElement = this.shadow.getElementById("context-menu")!;
|
this.contextMenuElement = this.shadow.getElementById("context-menu")!;
|
||||||
|
window.addEventListener("pointerdown", this.pointerDown.bind(this));
|
||||||
this.addEventListener("contextmenu", this.showContextMenu.bind(this));
|
this.addEventListener("contextmenu", this.showContextMenu.bind(this));
|
||||||
this.addEventListener("pointerdown", this.pointerDown.bind(this));
|
this.container.addEventListener(
|
||||||
|
"pointerdown",
|
||||||
|
this.startLongPressTimer.bind(this)
|
||||||
|
);
|
||||||
|
this.container.addEventListener(
|
||||||
|
"pointerup",
|
||||||
|
this.checkLongPress.bind(this)
|
||||||
|
);
|
||||||
|
this.container.addEventListener(
|
||||||
|
"pointercancel",
|
||||||
|
this.clearLongPressTimer.bind(this)
|
||||||
|
);
|
||||||
|
|
||||||
this.addEventListener(
|
this.addEventListener(
|
||||||
"fullscreenchange",
|
"fullscreenchange",
|
||||||
this.fullScreenChange.bind(this)
|
this.fullScreenChange.bind(this)
|
||||||
|
@ -229,7 +246,6 @@ export class RufflePlayer extends HTMLElement {
|
||||||
"webkitfullscreenchange",
|
"webkitfullscreenchange",
|
||||||
this.fullScreenChange.bind(this)
|
this.fullScreenChange.bind(this)
|
||||||
);
|
);
|
||||||
window.addEventListener("click", this.hideContextMenu.bind(this));
|
|
||||||
|
|
||||||
this.instance = null;
|
this.instance = null;
|
||||||
this.onFSCommand = null;
|
this.onFSCommand = null;
|
||||||
|
@ -770,8 +786,6 @@ export class RufflePlayer extends HTMLElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
private pointerDown(event: PointerEvent): void {
|
private pointerDown(event: PointerEvent): void {
|
||||||
// Give option to disable context menu when touch support is being used
|
|
||||||
// to avoid a long press triggering the context menu. (#1972)
|
|
||||||
if (event.pointerType === "touch" || event.pointerType === "pen") {
|
if (event.pointerType === "touch" || event.pointerType === "pen") {
|
||||||
this.isTouch = true;
|
this.isTouch = true;
|
||||||
}
|
}
|
||||||
|
@ -877,6 +891,8 @@ export class RufflePlayer extends HTMLElement {
|
||||||
window.open(RUFFLE_ORIGIN, "_blank");
|
window.open(RUFFLE_ORIGIN, "_blank");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
// Give option to disable context menu when touch support is being used
|
||||||
|
// to avoid a long press triggering the context menu. (#1972)
|
||||||
if (this.isTouch) {
|
if (this.isTouch) {
|
||||||
items.push(null);
|
items.push(null);
|
||||||
items.push({
|
items.push({
|
||||||
|
@ -887,8 +903,52 @@ export class RufflePlayer extends HTMLElement {
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
private showContextMenu(e: MouseEvent): void {
|
private clearLongPressTimer(): void {
|
||||||
e.preventDefault();
|
if (this.longPressTimer) {
|
||||||
|
clearTimeout(this.longPressTimer);
|
||||||
|
this.longPressTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private startLongPressTimer(): void {
|
||||||
|
const longPressTimeout = 800;
|
||||||
|
this.clearLongPressTimer();
|
||||||
|
this.longPressTimer = setTimeout(
|
||||||
|
() => this.clearLongPressTimer(),
|
||||||
|
longPressTimeout
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private checkLongPress(event: PointerEvent): void {
|
||||||
|
if (this.longPressTimer) {
|
||||||
|
this.clearLongPressTimer();
|
||||||
|
// The pointerType condition is to ensure right-click does not trigger
|
||||||
|
// a context menu the wrong way the first time you right-click,
|
||||||
|
// before contextMenuSupported is set.
|
||||||
|
} else if (
|
||||||
|
!this.contextMenuSupported &&
|
||||||
|
event.pointerType !== "mouse"
|
||||||
|
) {
|
||||||
|
this.showContextMenu(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private showContextMenu(event: MouseEvent | PointerEvent): void {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (event.type === "contextmenu") {
|
||||||
|
this.contextMenuSupported = true;
|
||||||
|
window.addEventListener("click", this.hideContextMenu.bind(this), {
|
||||||
|
once: true,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
window.addEventListener(
|
||||||
|
"pointerup",
|
||||||
|
this.hideContextMenu.bind(this),
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.loadedConfig.contextMenu === false ||
|
this.loadedConfig.contextMenu === false ||
|
||||||
|
@ -934,7 +994,10 @@ export class RufflePlayer extends HTMLElement {
|
||||||
this.contextMenuElement.appendChild(menuItem);
|
this.contextMenuElement.appendChild(menuItem);
|
||||||
|
|
||||||
if (enabled !== false) {
|
if (enabled !== false) {
|
||||||
menuItem.addEventListener("click", onClick);
|
menuItem.addEventListener(
|
||||||
|
this.isTouch ? "pointerup" : "click",
|
||||||
|
onClick
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
menuItem.classList.add("disabled");
|
menuItem.classList.add("disabled");
|
||||||
}
|
}
|
||||||
|
@ -948,8 +1011,8 @@ export class RufflePlayer extends HTMLElement {
|
||||||
this.contextMenuElement.style.display = "block";
|
this.contextMenuElement.style.display = "block";
|
||||||
|
|
||||||
const rect = this.getBoundingClientRect();
|
const rect = this.getBoundingClientRect();
|
||||||
const x = e.clientX - rect.x;
|
const x = event.clientX - rect.x;
|
||||||
const y = e.clientY - rect.y;
|
const y = event.clientY - rect.y;
|
||||||
const maxX = rect.width - this.contextMenuElement.clientWidth - 1;
|
const maxX = rect.width - this.contextMenuElement.clientWidth - 1;
|
||||||
const maxY = rect.height - this.contextMenuElement.clientHeight - 1;
|
const maxY = rect.height - this.contextMenuElement.clientHeight - 1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue