From fd5be6985de540cfc6bd456f1dd74187aab4fb15 Mon Sep 17 00:00:00 2001 From: kKaskak <117831817+kKaskak@users.noreply.github.com> Date: Wed, 10 Jan 2024 17:56:22 +0200 Subject: [PATCH 1/5] feature: VolumeChangeIndicatorImplementation --- src/routes/Player/Player.js | 25 ++++++++- .../VolumeChangeIndicator.js | 31 +++++++++++ .../Player/VolumeChangeIndicator/index.js | 5 ++ .../Player/VolumeChangeIndicator/styles.less | 55 +++++++++++++++++++ 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/routes/Player/VolumeChangeIndicator/VolumeChangeIndicator.js create mode 100644 src/routes/Player/VolumeChangeIndicator/index.js create mode 100644 src/routes/Player/VolumeChangeIndicator/styles.less diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 9887156d2..f5373aea1 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -10,6 +10,7 @@ const { useRouteFocused } = require('stremio-router'); const { useServices } = require('stremio/services'); const { HorizontalNavBar, useFullscreen, useBinaryState, useToast, useStreamingServer, withCoreSuspender } = require('stremio/common'); const BufferingLoader = require('./BufferingLoader'); +const VolumeChangeIndicator = require('./VolumeChangeIndicator'); const Error = require('./Error'); const ControlBar = require('./ControlBar'); const NextVideoPopup = require('./NextVideoPopup'); @@ -56,6 +57,8 @@ const Player = ({ urlParams, queryParams }) => { const [videosMenuOpen, , closeVideosMenu, toggleVideosMenu] = useBinaryState(false); const [statisticsMenuOpen, , closeStatisticsMenu, toggleStatisticsMenu] = useBinaryState(false); const [nextVideoPopupOpen, openNextVideoPopup, closeNextVideoPopup] = useBinaryState(false); + const [volumeChangeIndicatorOpen, openVolumeChangeIndicator, closeVolumeChangeIndicator] = useBinaryState(false); + const volumeChangeTimeout = React.useRef(null); const menusOpen = React.useMemo(() => { return optionsMenuOpen || subtitlesMenuOpen || infoMenuOpen || speedMenuOpen || videosMenuOpen || statisticsMenuOpen; @@ -154,7 +157,11 @@ const Player = ({ urlParams, queryParams }) => { const onVolumeChangeRequested = React.useCallback((volume) => { video.setProp('volume', volume); - }, []); + openVolumeChangeIndicator(); + + if (volumeChangeTimeout.current) clearTimeout(volumeChangeTimeout.current); + volumeChangeTimeout.current = setTimeout(closeVolumeChangeIndicator, 1500); + }, [openVolumeChangeIndicator, closeVolumeChangeIndicator]); const onSeekRequested = React.useCallback((time) => { video.setProp('time', time); @@ -423,6 +430,12 @@ const Player = ({ urlParams, queryParams }) => { } }, [video.state.playbackSpeed]); + React.useEffect(() => { + return () => { + if (volumeChangeTimeout.current) clearTimeout(volumeChangeTimeout.current); + }; + }, []); + React.useEffect(() => { const toastFilter = (item) => item?.dataset?.type === 'CoreEvent'; toast.addFilter(toastFilter); @@ -630,6 +643,16 @@ const Player = ({ urlParams, queryParams }) => { : null } + { + volumeChangeIndicatorOpen ? + + : + null + } { + return ( +
+ + +
+ ); +}; + +module.exports = VolumeChangeIndicator; + +VolumeChangeIndicator.propTypes = { + muted: PropTypes.bool, + onVolumeChangeRequested: PropTypes.func, + volume: PropTypes.number +}; diff --git a/src/routes/Player/VolumeChangeIndicator/index.js b/src/routes/Player/VolumeChangeIndicator/index.js new file mode 100644 index 000000000..9ca3a62d4 --- /dev/null +++ b/src/routes/Player/VolumeChangeIndicator/index.js @@ -0,0 +1,5 @@ +// Copyright (C) 2017-2023 Smart code 203358507 + +const VolumeChangeIndicator = require('./VolumeChangeIndicator'); + +module.exports = VolumeChangeIndicator; diff --git a/src/routes/Player/VolumeChangeIndicator/styles.less b/src/routes/Player/VolumeChangeIndicator/styles.less new file mode 100644 index 000000000..2487297a4 --- /dev/null +++ b/src/routes/Player/VolumeChangeIndicator/styles.less @@ -0,0 +1,55 @@ +// Copyright (C) 2017-2023 Smart code 203358507 + +@import (reference) '~stremio/common/screen-sizes.less'; + +.volume-change-indicator { + position: absolute; + top: 50%; + left: 50%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + z-index: 99999; + transform: translate(-50%, -50%); + background-color: var(--overlay-color); + border-radius: var(--border-radius); + padding: 2rem 2.5rem; + gap: 1rem; + + .volume-icon { + width: 6.5rem; + height: 6.5rem; + color: var(--primary-foreground-color); + opacity: 0.5; + } + + .volume-slider { + border-radius: var(--border-radius); + opacity: 0.5; + max-height: 1rem; + width: 6.5rem; + max-height: 1rem; + flex: 0 1 10rem; + margin: 0 1rem; + + --track-size: 0.35rem; + --thumb-size: 1rem; + } + +} + +@media only screen and (max-width: @minimum) { + .volume-change-indicator { + padding: 1rem 1.5rem; + + .volume-icon { + width: 4rem; + height: 4rem; + } + + .volume-slider { + width: 4rem; + } + } +} \ No newline at end of file From 4ce1ee7a6a3c003220ccf12c4ecbb1cbff4ceeeb Mon Sep 17 00:00:00 2001 From: kKaskak <117831817+kKaskak@users.noreply.github.com> Date: Wed, 10 Jan 2024 18:15:07 +0200 Subject: [PATCH 2/5] refactor: add a conditional to the indicator --- src/routes/Player/Player.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index f5373aea1..3f1e9170e 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -157,11 +157,13 @@ const Player = ({ urlParams, queryParams }) => { const onVolumeChangeRequested = React.useCallback((volume) => { video.setProp('volume', volume); - openVolumeChangeIndicator(); + if (immersed && !menusOpen) { + openVolumeChangeIndicator(); + } if (volumeChangeTimeout.current) clearTimeout(volumeChangeTimeout.current); volumeChangeTimeout.current = setTimeout(closeVolumeChangeIndicator, 1500); - }, [openVolumeChangeIndicator, closeVolumeChangeIndicator]); + }, [immersed, menusOpen]); const onSeekRequested = React.useCallback((time) => { video.setProp('time', time); From 69e90e8d8bea1104a259c8f129655b2d9afa612e Mon Sep 17 00:00:00 2001 From: kKaskak <117831817+kKaskak@users.noreply.github.com> Date: Wed, 17 Jan 2024 20:24:20 +0200 Subject: [PATCH 3/5] refactor: moved & refactored the logic to the component --- src/routes/Player/Player.js | 20 ++----- .../VolumeChangeIndicator.js | 57 ++++++++++++++----- .../Player/VolumeChangeIndicator/styles.less | 3 - 3 files changed, 48 insertions(+), 32 deletions(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 3f1e9170e..8ee614aaf 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -57,8 +57,6 @@ const Player = ({ urlParams, queryParams }) => { const [videosMenuOpen, , closeVideosMenu, toggleVideosMenu] = useBinaryState(false); const [statisticsMenuOpen, , closeStatisticsMenu, toggleStatisticsMenu] = useBinaryState(false); const [nextVideoPopupOpen, openNextVideoPopup, closeNextVideoPopup] = useBinaryState(false); - const [volumeChangeIndicatorOpen, openVolumeChangeIndicator, closeVolumeChangeIndicator] = useBinaryState(false); - const volumeChangeTimeout = React.useRef(null); const menusOpen = React.useMemo(() => { return optionsMenuOpen || subtitlesMenuOpen || infoMenuOpen || speedMenuOpen || videosMenuOpen || statisticsMenuOpen; @@ -157,13 +155,7 @@ const Player = ({ urlParams, queryParams }) => { const onVolumeChangeRequested = React.useCallback((volume) => { video.setProp('volume', volume); - if (immersed && !menusOpen) { - openVolumeChangeIndicator(); - } - - if (volumeChangeTimeout.current) clearTimeout(volumeChangeTimeout.current); - volumeChangeTimeout.current = setTimeout(closeVolumeChangeIndicator, 1500); - }, [immersed, menusOpen]); + }, []); const onSeekRequested = React.useCallback((time) => { video.setProp('time', time); @@ -432,12 +424,6 @@ const Player = ({ urlParams, queryParams }) => { } }, [video.state.playbackSpeed]); - React.useEffect(() => { - return () => { - if (volumeChangeTimeout.current) clearTimeout(volumeChangeTimeout.current); - }; - }, []); - React.useEffect(() => { const toastFilter = (item) => item?.dataset?.type === 'CoreEvent'; toast.addFilter(toastFilter); @@ -646,11 +632,13 @@ const Player = ({ urlParams, queryParams }) => { null } { - volumeChangeIndicatorOpen ? + immersed ? : null diff --git a/src/routes/Player/VolumeChangeIndicator/VolumeChangeIndicator.js b/src/routes/Player/VolumeChangeIndicator/VolumeChangeIndicator.js index a3858e59f..66c47fc0e 100644 --- a/src/routes/Player/VolumeChangeIndicator/VolumeChangeIndicator.js +++ b/src/routes/Player/VolumeChangeIndicator/VolumeChangeIndicator.js @@ -6,26 +6,57 @@ const { default: Icon } = require('@stremio/stremio-icons/react'); const { default: classNames } = require('classnames'); const PropTypes = require('prop-types'); const styles = require('./styles'); +const { useBinaryState } = require('stremio/common'); + +const VolumeChangeIndicator = React.memo(({ muted, onVolumeChangeRequested, volume, menusOpen, immersed }) => { + + const [volumeIndicatorOpen, openVolumeIndicator, closeVolumeIndicator] = useBinaryState(false); + const volumeChangeTimeout = React.useRef(null); + + React.useEffect(() => { + if (immersed && !menusOpen) openVolumeIndicator(); + + if (volumeChangeTimeout.current) clearTimeout(volumeChangeTimeout.current); + volumeChangeTimeout.current = setTimeout(closeVolumeIndicator, 1500); + }, [volume, menusOpen, immersed]); + + React.useEffect(() => { + return () => { + if (volumeChangeTimeout.current) clearTimeout(volumeChangeTimeout.current); + }; + }, [volume]); -const VolumeChangeIndicator = ({ muted, onVolumeChangeRequested, volume }) => { return ( -
- - -
+ + { + volumeIndicatorOpen ? +
+ + +
+ : + null + } +
); -}; +}); + +VolumeChangeIndicator.displayName = 'VolumeChangeIndicator'; module.exports = VolumeChangeIndicator; VolumeChangeIndicator.propTypes = { muted: PropTypes.bool, onVolumeChangeRequested: PropTypes.func, - volume: PropTypes.number + volume: PropTypes.number, + menusOpen: PropTypes.bool, + immersed: PropTypes.bool, + openVolumeIndicator: PropTypes.func, + closeVolumeIndicator: PropTypes.func }; diff --git a/src/routes/Player/VolumeChangeIndicator/styles.less b/src/routes/Player/VolumeChangeIndicator/styles.less index 2487297a4..38d651b7b 100644 --- a/src/routes/Player/VolumeChangeIndicator/styles.less +++ b/src/routes/Player/VolumeChangeIndicator/styles.less @@ -10,7 +10,6 @@ flex-direction: column; align-items: center; justify-content: center; - z-index: 99999; transform: translate(-50%, -50%); background-color: var(--overlay-color); border-radius: var(--border-radius); @@ -21,12 +20,10 @@ width: 6.5rem; height: 6.5rem; color: var(--primary-foreground-color); - opacity: 0.5; } .volume-slider { border-radius: var(--border-radius); - opacity: 0.5; max-height: 1rem; width: 6.5rem; max-height: 1rem; From 15cdd4f70af20776c16f9d2d1ff23a9a20d8bfc2 Mon Sep 17 00:00:00 2001 From: kKaskak <117831817+kKaskak@users.noreply.github.com> Date: Wed, 17 Jan 2024 23:04:34 +0200 Subject: [PATCH 4/5] refactor: simplify the logic --- src/routes/Player/Player.js | 4 +--- .../VolumeChangeIndicator.js | 23 +++++++++---------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 8ee614aaf..33bff1368 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -632,13 +632,11 @@ const Player = ({ urlParams, queryParams }) => { null } { - immersed ? + video.state.volume !== null && overlayHidden ? : null diff --git a/src/routes/Player/VolumeChangeIndicator/VolumeChangeIndicator.js b/src/routes/Player/VolumeChangeIndicator/VolumeChangeIndicator.js index 66c47fc0e..dffe64de9 100644 --- a/src/routes/Player/VolumeChangeIndicator/VolumeChangeIndicator.js +++ b/src/routes/Player/VolumeChangeIndicator/VolumeChangeIndicator.js @@ -8,23 +8,26 @@ const PropTypes = require('prop-types'); const styles = require('./styles'); const { useBinaryState } = require('stremio/common'); -const VolumeChangeIndicator = React.memo(({ muted, onVolumeChangeRequested, volume, menusOpen, immersed }) => { - +const VolumeChangeIndicator = React.memo(({ muted, onVolumeChangeRequested, volume }) => { const [volumeIndicatorOpen, openVolumeIndicator, closeVolumeIndicator] = useBinaryState(false); const volumeChangeTimeout = React.useRef(null); + const prevVolume = React.useRef(volume); React.useEffect(() => { - if (immersed && !menusOpen) openVolumeIndicator(); + if (prevVolume.current !== volume) { + openVolumeIndicator(); + if (volumeChangeTimeout.current) clearTimeout(volumeChangeTimeout.current); + volumeChangeTimeout.current = setTimeout(closeVolumeIndicator, 1500); + } - if (volumeChangeTimeout.current) clearTimeout(volumeChangeTimeout.current); - volumeChangeTimeout.current = setTimeout(closeVolumeIndicator, 1500); - }, [volume, menusOpen, immersed]); + prevVolume.current = volume; + }, [volume]); React.useEffect(() => { return () => { if (volumeChangeTimeout.current) clearTimeout(volumeChangeTimeout.current); }; - }, [volume]); + }, []); return ( @@ -54,9 +57,5 @@ module.exports = VolumeChangeIndicator; VolumeChangeIndicator.propTypes = { muted: PropTypes.bool, onVolumeChangeRequested: PropTypes.func, - volume: PropTypes.number, - menusOpen: PropTypes.bool, - immersed: PropTypes.bool, - openVolumeIndicator: PropTypes.func, - closeVolumeIndicator: PropTypes.func + volume: PropTypes.number }; From 6ed892ad123b72949ad963b92ec13500661ef740 Mon Sep 17 00:00:00 2001 From: kKaskak <117831817+kKaskak@users.noreply.github.com> Date: Tue, 13 Feb 2024 19:29:14 +0100 Subject: [PATCH 5/5] refactor: implement useMemo for the iconName --- src/routes/Player/Player.js | 1 - .../VolumeChangeIndicator.js | 21 ++++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 33bff1368..713796b5a 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -636,7 +636,6 @@ const Player = ({ urlParams, queryParams }) => { : null diff --git a/src/routes/Player/VolumeChangeIndicator/VolumeChangeIndicator.js b/src/routes/Player/VolumeChangeIndicator/VolumeChangeIndicator.js index dffe64de9..cfba89c59 100644 --- a/src/routes/Player/VolumeChangeIndicator/VolumeChangeIndicator.js +++ b/src/routes/Player/VolumeChangeIndicator/VolumeChangeIndicator.js @@ -8,11 +8,19 @@ const PropTypes = require('prop-types'); const styles = require('./styles'); const { useBinaryState } = require('stremio/common'); -const VolumeChangeIndicator = React.memo(({ muted, onVolumeChangeRequested, volume }) => { +const VolumeChangeIndicator = React.memo(({ muted, volume }) => { const [volumeIndicatorOpen, openVolumeIndicator, closeVolumeIndicator] = useBinaryState(false); const volumeChangeTimeout = React.useRef(null); const prevVolume = React.useRef(volume); + const iconName = React.useMemo(() => { + return typeof muted === 'boolean' && muted ? 'volume-mute' : + volume === null || isNaN(volume) ? 'volume-off' : + volume < 30 ? 'volume-low' : + volume < 70 ? 'volume-medium' : + 'volume-high'; + }, [muted, volume]); + React.useEffect(() => { if (prevVolume.current !== volume) { openVolumeIndicator(); @@ -34,14 +42,8 @@ const VolumeChangeIndicator = React.memo(({ muted, onVolumeChangeRequested, volu { volumeIndicatorOpen ?
- - + +
: null @@ -56,6 +58,5 @@ module.exports = VolumeChangeIndicator; VolumeChangeIndicator.propTypes = { muted: PropTypes.bool, - onVolumeChangeRequested: PropTypes.func, volume: PropTypes.number };