stremio-web/src/App/GamepadModal/GamepadModal.tsx
2026-04-28 23:52:59 +03:00

139 lines
6.6 KiB
TypeScript

// Copyright (C) 2017-2026 Smart code 203358507
import React, { useEffect } from 'react';
import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';
import Icon from '@stremio/stremio-icons/react';
import { Button } from 'stremio/components';
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 R_STICK = 'R stick';
const L1 = 'L1';
const R1 = 'R1';
const LEFT = '←';
const RIGHT = '→';
const UP = '↑';
const DOWN = '↓';
type Props = {
onClose: () => void,
};
const GamepadModal = ({ onClose }: Props) => {
const { t } = useTranslation();
const gamepad = useGamepad();
useEffect(() => {
const onKeyDown = ({ key }: KeyboardEvent) => {
key === 'Escape' && onClose();
};
document.addEventListener('keydown', onKeyDown);
gamepad?.on('buttonB', 'gamepad-modal', onClose);
return () => {
document.removeEventListener('keydown', onKeyDown);
gamepad?.off('buttonB', 'gamepad-modal');
};
}, [gamepad]);
return createPortal((
<div className={styles['gamepad-modal']}>
<div className={styles['backdrop']} onClick={onClose} />
<div className={styles['container']}>
<div className={styles['header']}>
<div className={styles['title']}>
{t('GAMEPAD_CONTROLS_TITLE')}
</div>
<Button className={styles['close-button']} title={t('BUTTON_CLOSE')} onClick={onClose}>
<Icon className={styles['icon']} name={'close'} />
</Button>
</div>
<div className={styles['content']}>
<GamepadDiagram />
<div className={styles['sections']}>
<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>
<span className={styles['dir']} />
<span className={styles['action']}>{t('GAMEPAD_ACTION_NAVIGATE')}</span>
</div>
<div className={styles['mapping']}>
<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']}>{CIRCLE}</kbd>
<span className={styles['dir']} />
<span className={styles['action']}>{t('GAMEPAD_ACTION_BACK')}</span>
</div>
<div className={styles['mapping']}>
<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']}>{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>
<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>
<span className={styles['dir']} />
<span className={styles['action']}>{t('GAMEPAD_ACTION_NEXT_TAB')}</span>
</div>
</div>
<div className={styles['section']}>
<div className={styles['section-title']}>{t('GAMEPAD_SECTION_PLAYER')}</div>
<div className={styles['mapping']}>
<kbd className={styles['kbd']}>{SQUARE}</kbd>
<span className={styles['dir']} />
<span className={styles['action']}>{t('GAMEPAD_ACTION_PLAY_PAUSE')}</span>
</div>
<div className={styles['mapping']}>
<kbd className={styles['kbd']}>{R_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']}>{R_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']}>{R_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']}>{R_STICK}</kbd>
<span className={styles['dir']}>{DOWN}</span>
<span className={styles['action']}>{t('GAMEPAD_ACTION_VOL_DOWN')}</span>
</div>
</div>
</div>
</div>
</div>
</div>
), document.body);
};
export default GamepadModal;