gamepad: add lock unlock on dom

This commit is contained in:
Timothy Z. 2026-04-29 17:25:35 +03:00
parent 2c578bf40a
commit 7637620ac5
3 changed files with 23 additions and 1 deletions

View file

@ -55,6 +55,7 @@ const GamepadModal = ({ onClose }: Props) => {
const labels = LABELS[gamepad?.controllerType ?? 'generic'];
useEffect(() => {
gamepad?.lock('gamepad-');
const onKeyDown = ({ key }: KeyboardEvent) => {
key === 'Escape' && onClose();
};
@ -64,6 +65,7 @@ const GamepadModal = ({ onClose }: Props) => {
return () => {
document.removeEventListener('keydown', onKeyDown);
gamepad?.off('buttonB', 'gamepad-modal');
gamepad?.unlock();
};
}, [gamepad]);

View file

@ -7,6 +7,8 @@ export type ControllerType = 'playstation' | 'xbox' | 'generic';
const GamepadContext = createContext<{
on: (event: string, id: string, callback: (data?: string) => void) => void;
off: (event: string, id: string) => void;
lock: (prefix: string) => void;
unlock: () => void;
controllerType: ControllerType;
} | null>(null);

View file

@ -34,6 +34,7 @@ const GamepadProvider = ({ enabled, onGuide, children }: GamepadProviderProps) =
const axisTimer = useRef<number>(0);
const axisTimerRight = useRef<number>(0);
const eventHandlers = useRef<GamepadEventHandlers>(new Map());
const lockPrefix = useRef<string | null>(null);
const [controllerType, setControllerType] = useState<ControllerType>('generic');
const on = useCallback((event: string, id: string, callback: (data?: string) => void) => {
@ -55,12 +56,29 @@ const GamepadProvider = ({ enabled, onGuide, children }: GamepadProviderProps) =
}
}, []);
const lock = useCallback((prefix: string) => {
lockPrefix.current = prefix;
}, []);
const unlock = useCallback(() => {
lockPrefix.current = null;
}, []);
const emit = (event: string, data?: string) => {
if (eventHandlers.current.has(event)) {
const handlersMap = eventHandlers.current.get(event)!;
if (!handlersMap || handlersMap.size === 0) return;
if (lockPrefix.current) {
const matching = Array.from(handlersMap.entries())
.filter(([id]) => id.startsWith(lockPrefix.current!));
if (matching.length > 0) {
matching[matching.length - 1][1](data);
}
return;
}
const latestHandler = Array.from(handlersMap.values()).slice(-1)[0];
if (latestHandler) {
latestHandler(data);
@ -244,7 +262,7 @@ const GamepadProvider = ({ enabled, onGuide, children }: GamepadProviderProps) =
}, [enabled]);
return (
<GamepadContext.Provider value={{ on, off, controllerType }}>
<GamepadContext.Provider value={{ on, off, lock, unlock, controllerType }}>
{children}
</GamepadContext.Provider>
);