From f6d4e3f4a60c808d701d649cbc165fea631d8099 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 16 Jun 2025 15:22:10 +0200 Subject: [PATCH 1/4] feat: add player subtitles delay shortcuts --- src/common/animations.less | 13 ++++ src/routes/Player/Indicator/Indicator.less | 23 +++++++ src/routes/Player/Indicator/Indicator.tsx | 73 ++++++++++++++++++++++ src/routes/Player/Player.js | 47 +++++++++++++- src/routes/Player/styles.less | 7 +++ src/routes/Settings/Settings.js | 10 +++ 6 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 src/routes/Player/Indicator/Indicator.less create mode 100644 src/routes/Player/Indicator/Indicator.tsx diff --git a/src/common/animations.less b/src/common/animations.less index 91dbe386d..3b9815f14 100644 --- a/src/common/animations.less +++ b/src/common/animations.less @@ -82,6 +82,19 @@ transform: translateY(100%); } +.fade-enter { + opacity: 0; +} + +.fade-active { + opacity: 1; + transition: opacity 0.3s cubic-bezier(0.32, 0, 0.67, 0); +} + +.fade-exit { + opacity: 0; +} + @keyframes fade-in-no-motion { 0% { opacity: 0; diff --git a/src/routes/Player/Indicator/Indicator.less b/src/routes/Player/Indicator/Indicator.less new file mode 100644 index 000000000..699c53d23 --- /dev/null +++ b/src/routes/Player/Indicator/Indicator.less @@ -0,0 +1,23 @@ +.indicator-container { + position: absolute; + display: flex; + align-items: center; + justify-content: center; + height: 4rem; + user-select: none; + + .indicator { + flex: none; + position: relative; + display: flex; + align-items: center; + justify-content: center; + height: 100%; + padding: 0 2rem; + border-radius: 4rem; + text-align: center; + font-weight: bold; + color: var(--primary-foreground-color); + background-color: var(--modal-background-color); + } +} \ No newline at end of file diff --git a/src/routes/Player/Indicator/Indicator.tsx b/src/routes/Player/Indicator/Indicator.tsx new file mode 100644 index 000000000..cc0ef4ccf --- /dev/null +++ b/src/routes/Player/Indicator/Indicator.tsx @@ -0,0 +1,73 @@ +import React, { useEffect, useMemo, useRef, useState } from 'react'; +import classNames from 'classnames'; +import { t } from 'i18next'; +import { Transition } from 'stremio/components'; +import { useBinaryState } from 'stremio/common'; +import styles from './Indicator.less'; + +type Property = { + label: string, + format: (value: number) => string, +}; + +const PROPERTIES: Record = { + 'extraSubtitlesDelay': { + label: 'SUBTITLES_DELAY', + format: (value) => `${(value / 1000).toFixed(2)}s`, + }, +}; + +type VideoState = Record; + +type Props = { + className: string, + videoState: VideoState, +}; + +const Indicator = ({ className, videoState }: Props) => { + const timeout = useRef(null); + const prevVideoState = useRef(videoState); + + const [shown, show, hide] = useBinaryState(false); + const [current, setCurrent] = useState(null); + + const label = useMemo(() => { + const property = current && PROPERTIES[current]; + return property && t(property.label); + }, [current]); + + const value = useMemo(() => { + const property = current && PROPERTIES[current]; + const value = current && videoState[current]; + return property && value && property.format(value); + }, [current, videoState]); + + useEffect(() => { + for (const property of Object.keys(PROPERTIES)) { + const prev = prevVideoState.current[property]; + const next = videoState[property]; + + if (next && next !== prev) { + setCurrent(property); + show(); + + timeout.current && clearTimeout(timeout.current); + timeout.current = setTimeout(hide, 1000); + } + } + + prevVideoState.current = videoState; + }, [videoState]); + + return ( + +
+
+
{label} {value}
+
+
+
+ ); +}; + +export default Indicator; diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 8ba813786..65c02534f 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -27,6 +27,7 @@ const useStatistics = require('./useStatistics'); const useVideo = require('./useVideo'); const styles = require('./styles'); const Video = require('./Video'); +const { default: Indicator } = require('./Indicator/Indicator'); const Player = ({ urlParams, queryParams }) => { const { t } = useTranslation(); @@ -216,6 +217,16 @@ const Player = ({ urlParams, queryParams }) => { video.setProp('extraSubtitlesDelay', delay); }, []); + const onIncreaseSubtitlesDelay = React.useCallback(() => { + const delay = video.state.extraSubtitlesDelay + 250; + onExtraSubtitlesDelayChanged(delay); + }, [video.state.extraSubtitlesDelay, onExtraSubtitlesDelayChanged]); + + const onDecreaseSubtitlesDelay = React.useCallback(() => { + const delay = video.state.extraSubtitlesDelay - 250; + onExtraSubtitlesDelayChanged(delay); + }, [video.state.extraSubtitlesDelay, onExtraSubtitlesDelayChanged]); + const onSubtitlesSizeChanged = React.useCallback((size) => { updateSettings({ subtitlesSize: size }); }, [updateSettings]); @@ -587,6 +598,14 @@ const Player = ({ urlParams, queryParams }) => { break; } + case 'KeyG': { + onDecreaseSubtitlesDelay(); + break; + } + case 'KeyH': { + onIncreaseSubtitlesDelay(); + break; + } case 'Escape': { closeMenus(); !settings.escExitFullscreen && window.history.back(); @@ -620,7 +639,29 @@ const Player = ({ urlParams, queryParams }) => { window.removeEventListener('keyup', onKeyUp); window.removeEventListener('wheel', onWheel); }; - }, [player.metaItem, player.selected, streamingServer.statistics, settings.seekTimeDuration, settings.seekShortTimeDuration, settings.escExitFullscreen, routeFocused, menusOpen, nextVideoPopupOpen, video.state.paused, video.state.time, video.state.volume, video.state.audioTracks, video.state.subtitlesTracks, video.state.extraSubtitlesTracks, video.state.playbackSpeed, toggleSubtitlesMenu, toggleStatisticsMenu, toggleSideDrawer]); + }, [ + player.metaItem, + player.selected, + streamingServer.statistics, + settings.seekTimeDuration, + settings.seekShortTimeDuration, + settings.escExitFullscreen, + routeFocused, + menusOpen, + nextVideoPopupOpen, + video.state.paused, + video.state.time, + video.state.volume, + video.state.audioTracks, + video.state.subtitlesTracks, + video.state.extraSubtitlesTracks, + video.state.playbackSpeed, + toggleSubtitlesMenu, + toggleStatisticsMenu, + toggleSideDrawer, + onDecreaseSubtitlesDelay, + onIncreaseSubtitlesDelay, + ]); React.useEffect(() => { video.events.on('error', onError); @@ -760,6 +801,10 @@ const Player = ({ urlParams, queryParams }) => { onMouseOver={onBarMouseMove} onTouchEnd={onContainerMouseLeave} /> + { nextVideoPopupOpen ? { F +
+
+
{ t('SETTINGS_SHORTCUT_SUBTITLES_DELAY') }
+
+
+ G +
and
+ H +
+
{ t('SETTINGS_SHORTCUT_NAVIGATE_MENUS') }
From cb405878a0ea0862f834520ddb0be31feb7a1028 Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 18 Jun 2025 09:59:54 +0200 Subject: [PATCH 2/4] chore: update stremio-translations --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 79e66d642..0584eb3d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,7 @@ "react-i18next": "^15.1.3", "react-is": "18.3.1", "spatial-navigation-polyfill": "github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6", - "stremio-translations": "github:Stremio/stremio-translations#a6be0425573917c2e82b66d28968c1a4d444cb96", + "stremio-translations": "github:Stremio/stremio-translations#8efdffbcf6eeadf01ab658e54adcc6a236b7b10f", "url": "0.11.4", "use-long-press": "^3.2.0" }, @@ -13373,9 +13373,9 @@ } }, "node_modules/stremio-translations": { - "version": "1.44.10", - "resolved": "git+ssh://git@github.com/Stremio/stremio-translations.git#a6be0425573917c2e82b66d28968c1a4d444cb96", - "integrity": "sha512-77kVE/eos/SA16kzeK7TTWmqoLF0mLPCJXjITwVIVzMHr8XyBPZFOfmiVEg4M6W1W7qYqA+dHhzicyLs7hJhlw==", + "version": "1.44.12", + "resolved": "git+ssh://git@github.com/Stremio/stremio-translations.git#8efdffbcf6eeadf01ab658e54adcc6a236b7b10f", + "integrity": "sha512-doFloPfrWQ5EqufZMCTMPlvR5BBI/B7S//UD0G0Fr5NHRdIwKXB4Hf47y+adUTjn3oAGrepVfMpQVaIp5BIrKg==", "license": "MIT" }, "node_modules/string_decoder": { diff --git a/package.json b/package.json index 5ed9368ab..36e556149 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "react-i18next": "^15.1.3", "react-is": "18.3.1", "spatial-navigation-polyfill": "github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6", - "stremio-translations": "github:Stremio/stremio-translations#a6be0425573917c2e82b66d28968c1a4d444cb96", + "stremio-translations": "github:Stremio/stremio-translations#8efdffbcf6eeadf01ab658e54adcc6a236b7b10f", "url": "0.11.4", "use-long-press": "^3.2.0" }, From cf654ae825d258c2c9817a501efc42acfcf1e526 Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 18 Jun 2025 23:28:57 +0200 Subject: [PATCH 3/4] chore: update stremio-translations --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index a7a258109..d7d3c7d4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,7 @@ "react-i18next": "^15.1.3", "react-is": "18.3.1", "spatial-navigation-polyfill": "github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6", - "stremio-translations": "github:Stremio/stremio-translations#8efdffbcf6eeadf01ab658e54adcc6a236b7b10f", + "stremio-translations": "github:Stremio/stremio-translations#8212fa77c4febd22ddb611590e9fb574dc845416", "url": "0.11.4", "use-long-press": "^3.2.0" }, @@ -13405,8 +13405,8 @@ }, "node_modules/stremio-translations": { "version": "1.44.12", - "resolved": "git+ssh://git@github.com/Stremio/stremio-translations.git#8efdffbcf6eeadf01ab658e54adcc6a236b7b10f", - "integrity": "sha512-doFloPfrWQ5EqufZMCTMPlvR5BBI/B7S//UD0G0Fr5NHRdIwKXB4Hf47y+adUTjn3oAGrepVfMpQVaIp5BIrKg==", + "resolved": "git+ssh://git@github.com/Stremio/stremio-translations.git#8212fa77c4febd22ddb611590e9fb574dc845416", + "integrity": "sha512-5DladLUsghLlVRsZh2bBnb7UMqU8NEYMHc+YbzBvb1llgMk9elXFSHtAjInepZlC5zWx2pJYOQ8lQzzqogQdFw==", "license": "MIT" }, "node_modules/string_decoder": { diff --git a/package.json b/package.json index 51bd9036c..77f7477b7 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "react-i18next": "^15.1.3", "react-is": "18.3.1", "spatial-navigation-polyfill": "github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6", - "stremio-translations": "github:Stremio/stremio-translations#8efdffbcf6eeadf01ab658e54adcc6a236b7b10f", + "stremio-translations": "github:Stremio/stremio-translations#8212fa77c4febd22ddb611590e9fb574dc845416", "url": "0.11.4", "use-long-press": "^3.2.0" }, From 00bac0aca21c072114a5abe768a50d7e3e78d348 Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 18 Jun 2025 23:30:10 +0200 Subject: [PATCH 4/4] refactor(Settings): add translation for shortcuts and --- src/routes/Settings/Settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/Settings/Settings.js b/src/routes/Settings/Settings.js index 552b6116c..d79bcebeb 100644 --- a/src/routes/Settings/Settings.js +++ b/src/routes/Settings/Settings.js @@ -715,7 +715,7 @@ const Settings = () => {
G -
and
+
{ t('SETTINGS_SHORTCUT_AND') }
H