mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-05-10 11:20:49 +00:00
fix: tests + stale callbacks
This commit is contained in:
parent
f95273b8ce
commit
0b601010e2
4 changed files with 46 additions and 35 deletions
|
|
@ -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'}
|
||||
/>
|
||||
<text x={CX - SX} y={'58'} textAnchor={'middle'} fill={'#8b7faa'} fontSize={'8'} fontWeight={'500'}>L2</text>
|
||||
<text x={CX - SX} y={'58'} textAnchor={'middle'} fill={'#8b7faa'} fontSize={'8'} fontWeight={'500'}>{BTN.L2}</text>
|
||||
<path
|
||||
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'}
|
||||
/>
|
||||
<text x={CX + SX} y={'58'} textAnchor={'middle'} fill={'#8b7faa'} fontSize={'8'} fontWeight={'500'}>R2</text>
|
||||
<text x={CX + SX} y={'58'} textAnchor={'middle'} fill={'#8b7faa'} fontSize={'8'} fontWeight={'500'}>{BTN.R2}</text>
|
||||
|
||||
{/* ===== CONTROLLER BODY ===== */}
|
||||
<path
|
||||
|
|
@ -120,14 +121,14 @@ const GamepadDiagram = () => {
|
|||
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}
|
||||
/>
|
||||
<text x={CX - SX} y={'78'} textAnchor={'middle'} fill={'#a89ecc'} fontSize={'9'} fontWeight={'600'}>L1</text>
|
||||
<text x={CX - SX} y={'78'} textAnchor={'middle'} fill={'#a89ecc'} fontSize={'9'} fontWeight={'600'}>{BTN.L1}</text>
|
||||
</g>
|
||||
<g filter={active === 'r1' ? 'url(#glow)' : undefined}>
|
||||
<path
|
||||
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('r1') || '#5848a0'} strokeWidth={'1.2'} opacity={glowOp('r1') || 0.9}
|
||||
/>
|
||||
<text x={CX + SX} y={'78'} textAnchor={'middle'} fill={'#a89ecc'} fontSize={'9'} fontWeight={'600'}>R1</text>
|
||||
<text x={CX + SX} y={'78'} textAnchor={'middle'} fill={'#a89ecc'} fontSize={'9'} fontWeight={'600'}>{BTN.R1}</text>
|
||||
</g>
|
||||
|
||||
{/* ===== FACE BUTTONS (right, centered at CX+BX) ===== */}
|
||||
|
|
|
|||
|
|
@ -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) => {
|
|||
<div className={styles['section']}>
|
||||
<div className={styles['section-title']}>{t('GAMEPAD_SECTION_NAVIGATION')}</div>
|
||||
<div className={styles['mapping']}>
|
||||
<kbd className={styles['kbd']}>L stick</kbd>
|
||||
<kbd className={styles['kbd']}>{L_STICK}</kbd>
|
||||
<span className={styles['dir']} />
|
||||
<span className={styles['action']}>{t('GAMEPAD_ACTION_NAVIGATE')}</span>
|
||||
</div>
|
||||
<div className={styles['mapping']}>
|
||||
<kbd className={styles['kbd']}>✕</kbd>
|
||||
<kbd className={styles['kbd']}>{CROSS}</kbd>
|
||||
<span className={styles['dir']} />
|
||||
<span className={styles['action']}>{t('GAMEPAD_ACTION_SELECT')}</span>
|
||||
</div>
|
||||
<div className={styles['mapping']}>
|
||||
<kbd className={styles['kbd']}>○</kbd>
|
||||
<kbd className={styles['kbd']}>{CIRCLE}</kbd>
|
||||
<span className={styles['dir']} />
|
||||
<span className={styles['action']}>{t('GAMEPAD_ACTION_BACK')}</span>
|
||||
</div>
|
||||
<div className={styles['mapping']}>
|
||||
<kbd className={styles['kbd']}>△</kbd>
|
||||
<kbd className={styles['kbd']}>{TRIANGLE}</kbd>
|
||||
<span className={styles['dir']} />
|
||||
<span className={styles['action']}>{t('GAMEPAD_ACTION_FULLSCREEN')}</span>
|
||||
</div>
|
||||
<div className={styles['mapping']}>
|
||||
<kbd className={styles['kbd']}>□</kbd>
|
||||
<kbd className={styles['kbd']}>{SQUARE}</kbd>
|
||||
<span className={styles['dir']} />
|
||||
<span className={styles['action']}>{t('GAMEPAD_ACTION_GUIDE')}</span>
|
||||
</div>
|
||||
<div className={styles['mapping']}>
|
||||
<kbd className={styles['kbd']}>L1</kbd>
|
||||
<kbd className={styles['kbd']}>{L1}</kbd>
|
||||
<span className={styles['dir']} />
|
||||
<span className={styles['action']}>{t('GAMEPAD_ACTION_PREV_TAB')}</span>
|
||||
</div>
|
||||
<div className={styles['mapping']}>
|
||||
<kbd className={styles['kbd']}>R1</kbd>
|
||||
<kbd className={styles['kbd']}>{R1}</kbd>
|
||||
<span className={styles['dir']} />
|
||||
<span className={styles['action']}>{t('GAMEPAD_ACTION_NEXT_TAB')}</span>
|
||||
</div>
|
||||
|
|
@ -91,28 +103,28 @@ const GamepadModal = ({ onClose }: Props) => {
|
|||
<div className={styles['section']}>
|
||||
<div className={styles['section-title']}>{t('GAMEPAD_SECTION_PLAYER')}</div>
|
||||
<div className={styles['mapping']}>
|
||||
<kbd className={styles['kbd']}>✕</kbd>
|
||||
<kbd className={styles['kbd']}>{CROSS}</kbd>
|
||||
<span className={styles['dir']} />
|
||||
<span className={styles['action']}>{t('GAMEPAD_ACTION_PLAY_PAUSE')}</span>
|
||||
</div>
|
||||
<div className={styles['mapping']}>
|
||||
<kbd className={styles['kbd']}>L stick</kbd>
|
||||
<span className={styles['dir']}>{'←'}</span>
|
||||
<kbd className={styles['kbd']}>{L_STICK}</kbd>
|
||||
<span className={styles['dir']}>{LEFT}</span>
|
||||
<span className={styles['action']}>{t('GAMEPAD_ACTION_SEEK_BACK')}</span>
|
||||
</div>
|
||||
<div className={styles['mapping']}>
|
||||
<kbd className={styles['kbd']}>L stick</kbd>
|
||||
<span className={styles['dir']}>{'→'}</span>
|
||||
<kbd className={styles['kbd']}>{L_STICK}</kbd>
|
||||
<span className={styles['dir']}>{RIGHT}</span>
|
||||
<span className={styles['action']}>{t('GAMEPAD_ACTION_SEEK_FWD')}</span>
|
||||
</div>
|
||||
<div className={styles['mapping']}>
|
||||
<kbd className={styles['kbd']}>L stick</kbd>
|
||||
<span className={styles['dir']}>{'↑'}</span>
|
||||
<kbd className={styles['kbd']}>{L_STICK}</kbd>
|
||||
<span className={styles['dir']}>{UP}</span>
|
||||
<span className={styles['action']}>{t('GAMEPAD_ACTION_VOL_UP')}</span>
|
||||
</div>
|
||||
<div className={styles['mapping']}>
|
||||
<kbd className={styles['kbd']}>L stick</kbd>
|
||||
<span className={styles['dir']}>{'↓'}</span>
|
||||
<kbd className={styles['kbd']}>{L_STICK}</kbd>
|
||||
<span className={styles['dir']}>{DOWN}</span>
|
||||
<span className={styles['action']}>{t('GAMEPAD_ACTION_VOL_DOWN')}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue