diff --git a/src/App/GamepadModal/GamepadDiagram.tsx b/src/App/GamepadModal/GamepadDiagram.tsx index 35a93e013..3747e68ed 100644 --- a/src/App/GamepadModal/GamepadDiagram.tsx +++ b/src/App/GamepadModal/GamepadDiagram.tsx @@ -8,6 +8,7 @@ import styles from './styles.less'; type ActiveButton = string | null; const CX = 400; +const BTN = { L1: 'L1', L2: 'L2', R1: 'R1', R2: 'R2' }; const GamepadDiagram = () => { const { t } = useTranslation(); @@ -79,12 +80,12 @@ const GamepadDiagram = () => { d={`M${CX - SX - 38},68 Q${CX - SX - 40},48 ${CX - SX - 28},42 L${CX - SX + 28},42 Q${CX - SX + 40},48 ${CX - SX + 38},68 Z`} fill={'url(#triggerGrad)'} stroke={'#3d3660'} strokeWidth={'1'} opacity={'0.7'} /> - L2 + {BTN.L2} - R2 + {BTN.R2} {/* ===== CONTROLLER BODY ===== */} { d={`M${CX - SX - 40},74 Q${CX - SX - 38},66 ${CX - SX - 30},64 L${CX - SX + 30},64 Q${CX - SX + 38},66 ${CX - SX + 40},74 L${CX - SX + 36},82 Q${CX - SX + 34},85 ${CX - SX + 28},85 L${CX - SX - 28},85 Q${CX - SX - 34},85 ${CX - SX - 36},82 Z`} fill={'url(#bumperGrad)'} stroke={glow('l1') || '#5848a0'} strokeWidth={'1.2'} opacity={glowOp('l1') || 0.9} /> - L1 + {BTN.L1} - R1 + {BTN.R1} {/* ===== FACE BUTTONS (right, centered at CX+BX) ===== */} diff --git a/src/App/GamepadModal/GamepadModal.tsx b/src/App/GamepadModal/GamepadModal.tsx index cdd624fbf..c3f68940c 100644 --- a/src/App/GamepadModal/GamepadModal.tsx +++ b/src/App/GamepadModal/GamepadModal.tsx @@ -9,6 +9,18 @@ import { useGamepad } from 'stremio/services'; import GamepadDiagram from './GamepadDiagram'; import styles from './styles.less'; +const CROSS = '✕'; +const CIRCLE = '○'; +const TRIANGLE = '△'; +const SQUARE = '□'; +const L_STICK = 'L stick'; +const L1 = 'L1'; +const R1 = 'R1'; +const LEFT = '←'; +const RIGHT = '→'; +const UP = '↑'; +const DOWN = '↓'; + type Props = { onClose: () => void, }; @@ -52,37 +64,37 @@ const GamepadModal = ({ onClose }: Props) => {
{t('GAMEPAD_SECTION_NAVIGATION')}
- L stick + {L_STICK} {t('GAMEPAD_ACTION_NAVIGATE')}
- + {CROSS} {t('GAMEPAD_ACTION_SELECT')}
- + {CIRCLE} {t('GAMEPAD_ACTION_BACK')}
- + {TRIANGLE} {t('GAMEPAD_ACTION_FULLSCREEN')}
- + {SQUARE} {t('GAMEPAD_ACTION_GUIDE')}
- L1 + {L1} {t('GAMEPAD_ACTION_PREV_TAB')}
- R1 + {R1} {t('GAMEPAD_ACTION_NEXT_TAB')}
@@ -91,28 +103,28 @@ const GamepadModal = ({ onClose }: Props) => {
{t('GAMEPAD_SECTION_PLAYER')}
- + {CROSS} {t('GAMEPAD_ACTION_PLAY_PAUSE')}
- L stick - {'←'} + {L_STICK} + {LEFT} {t('GAMEPAD_ACTION_SEEK_BACK')}
- L stick - {'→'} + {L_STICK} + {RIGHT} {t('GAMEPAD_ACTION_SEEK_FWD')}
- L stick - {'↑'} + {L_STICK} + {UP} {t('GAMEPAD_ACTION_VOL_UP')}
- L stick - {'↓'} + {L_STICK} + {DOWN} {t('GAMEPAD_ACTION_VOL_DOWN')}
diff --git a/src/services/GamepadContext/GamepadProvider.tsx b/src/services/GamepadContext/GamepadProvider.tsx index d86517bfb..260aa16ce 100644 --- a/src/services/GamepadContext/GamepadProvider.tsx +++ b/src/services/GamepadContext/GamepadProvider.tsx @@ -52,37 +52,35 @@ const GamepadProvider: React.FC<{ } }; - const onGamepadConnected = () => { + const onGamepadConnected = useCallback(() => { // @ts-expect-error show() expects no arguments toast.show({ type: 'info', title: t('GAMEPAD_CONNECTED'), timeout: 4000, }); - }; + }, [toast, t]); - const onGamepadDisconnected = () => { + const onGamepadDisconnected = useCallback(() => { // @ts-expect-error show() expects no arguments toast.show({ type: 'info', title: t('GAMEPAD_DISCONNECTED'), timeout: 4000, }); - }; + }, [toast, t]); useEffect(() => { - if (enabled) { - window.addEventListener('gamepadconnected', onGamepadConnected); - window.addEventListener('gamepaddisconnected', onGamepadDisconnected); - } + if (!enabled) return; + + window.addEventListener('gamepadconnected', onGamepadConnected); + window.addEventListener('gamepaddisconnected', onGamepadDisconnected); return () => { - if (enabled) { - window.removeEventListener('gamepadconnected', onGamepadConnected); - window.removeEventListener('gamepaddisconnected', onGamepadDisconnected); - } + window.removeEventListener('gamepadconnected', onGamepadConnected); + window.removeEventListener('gamepaddisconnected', onGamepadDisconnected); }; - }, [enabled]); + }, [enabled, onGamepadConnected, onGamepadDisconnected]); useEffect(() => { if (onGuide) { diff --git a/src/services/GamepadNavigation/useContentGamepadNavigation.tsx b/src/services/GamepadNavigation/useContentGamepadNavigation.tsx index c9406f2fa..22162d77d 100644 --- a/src/services/GamepadNavigation/useContentGamepadNavigation.tsx +++ b/src/services/GamepadNavigation/useContentGamepadNavigation.tsx @@ -103,8 +103,8 @@ const useContentGamepadNavigation = ( elements[0].focus(); return; } - const isActiveSelectElement = [activeElement.classList].some((className) => /^select-input/.test(className.toString())); - if (!isActiveSelectElement) { + const isSelect = Array.from(activeElement.classList).some((cls) => cls.startsWith('select-input')); + if (!isSelect) { activeElement?.click(); } };