39 lines
1.1 KiB
TypeScript
39 lines
1.1 KiB
TypeScript
"use client";
|
|||
|
|
|
||
|
|
import { useEffect } from "react";
|
||
|
|
import type { attachTouchControls as AttachTouchControls } from "@valknar/vpinball-wasm";
|
||
|
|
|
||
|
|
const ENGINE_BASE_URL = "/vendor/vpinball-wasm";
|
||
|
|
|
||
|
|
function isTouchDevice(): boolean {
|
||
|
|
return typeof window !== "undefined" && ("ontouchstart" in window || navigator.maxTouchPoints > 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Attaches the engine's on-screen touch overlay to `containerRef` while `active` is true. */
|
||
|
|
export function useTouchControls(
|
||
|
|
containerRef: React.RefObject<HTMLElement | null>,
|
||
|
|
active: boolean,
|
||
|
|
): void {
|
||
|
|
useEffect(() => {
|
||
|
|
if (!active || !isTouchDevice()) return;
|
||
|
|
const container = containerRef.current;
|
||
|
|
if (!container) return;
|
||
|
|
|
||
|
|
let handle: { detach: () => void } | undefined;
|
||
|
|
let cancelled = false;
|
||
|
|
|
||
|
|
(async () => {
|
||
|
|
const { attachTouchControls } = (await import(
|
||
|
|
/* webpackIgnore: true */ `${ENGINE_BASE_URL}/index.js`
|
||
|
|
)) as { attachTouchControls: typeof AttachTouchControls };
|
||
|
|
if (cancelled) return;
|
||
|
|
handle = attachTouchControls({ container });
|
||
|
|
})();
|
||
|
|
|
||
|
|
return () => {
|
||
|
|
cancelled = true;
|
||
|
|
handle?.detach();
|
||
|
|
};
|
||
|
|
}, [containerRef, active]);
|
||
|
|
}
|