diff --git a/src/routes/Player/Indicator/Indicator.tsx b/src/routes/Player/Indicator/Indicator.tsx index b9290ad64..c7591b028 100644 --- a/src/routes/Player/Indicator/Indicator.tsx +++ b/src/routes/Player/Indicator/Indicator.tsx @@ -10,10 +10,10 @@ type Property = { format: (value: number | string) => string, }; -const VIDEO_SCALE_LABELS: Record = { - 'contain': 'Fit', - 'cover': 'Crop', - 'fill': 'Stretch', +const VIDEO_SCALE_KEYS: Record = { + 'contain': 'PLAYER_SCALE_FIT', + 'cover': 'PLAYER_SCALE_CROP', + 'fill': 'PLAYER_SCALE_STRETCH', }; const PROPERTIES: Record = { @@ -23,7 +23,7 @@ const PROPERTIES: Record = { }, 'videoScale': { label: 'VIDEO_SCALE', - format: (value) => VIDEO_SCALE_LABELS[String(value)] || String(value), + format: (value) => t(VIDEO_SCALE_KEYS[String(value)] || String(value)), }, }; @@ -38,6 +38,7 @@ type Props = { const Indicator = ({ className, videoState, disabled }: Props) => { const timeout = useRef(null); const prevVideoState = useRef(videoState); + const initialized = useRef>(new Set()); const [shown, show, hide] = useBinaryState(false); const [current, setCurrent] = useState(null); @@ -59,11 +60,15 @@ const Indicator = ({ className, videoState, disabled }: Props) => { const next = videoState[property]; if (next && next !== prev) { - setCurrent(property); - show(); + if (!initialized.current.has(property)) { + initialized.current.add(property); + } else { + setCurrent(property); + show(); - timeout.current && clearTimeout(timeout.current); - timeout.current = setTimeout(hide, 1000); + timeout.current && clearTimeout(timeout.current); + timeout.current = setTimeout(hide, 1000); + } } } diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 2ef6db67a..42ff18e7b 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -99,7 +99,7 @@ const Player = ({ urlParams, queryParams }) => { const isNavigating = React.useRef(false); const VIDEO_SCALES = ['contain', 'cover', 'fill']; - const VIDEO_SCALE_LABELS = { contain: 'Fit', cover: 'Crop', fill: 'Stretch' }; + const VIDEO_SCALE_LABELS = { contain: t('PLAYER_SCALE_FIT'), cover: t('PLAYER_SCALE_CROP'), fill: t('PLAYER_SCALE_STRETCH') }; const playbackSpeed = React.useRef(video.state.playbackSpeed || 1); const pressTimer = React.useRef(null); @@ -609,6 +609,29 @@ const Player = ({ urlParams, queryParams }) => { useMediaSession(video.state, player, onPlayRequested, onPauseRequested, onNextVideoRequested); + React.useEffect(() => { + const onMediaKey = (action) => { + switch (action) { + case 'play-pause': + video.state.paused ? onPlayRequested() : onPauseRequested(); + break; + case 'next-track': + if (player.nextVideo !== null) { + video.setTime(0); + onNextVideoRequested(); + } + break; + case 'previous-track': + if (video.state.time !== null && video.state.time > 5000) { + onSeekRequested(0); + } + break; + } + }; + shell.on('media-key', onMediaKey); + return () => shell.off('media-key', onMediaKey); + }, [video.state.paused, video.state.time, player.nextVideo, onPlayRequested, onPauseRequested, onNextVideoRequested, onSeekRequested]); + onShortcut('seekForward', (combo) => { if (video.state.time !== null) { const seekDuration = combo === 1 ? settings.seekShortTimeDuration : settings.seekTimeDuration;