From a6b66667f1b9edbb299e496932690c2e364a7d3d Mon Sep 17 00:00:00 2001 From: Lachezar Lechev Date: Thu, 16 May 2024 19:38:34 +0300 Subject: [PATCH 01/27] feat(player): add seek action and handle seeking player state w/ debug statements Signed-off-by: Lachezar Lechev --- src/routes/Player/Player.js | 28 ++++++++++++++++++++++++++-- src/routes/Player/usePlayer.d.ts | 2 +- src/routes/Player/usePlayer.js | 15 ++++++++++++++- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 0a2efef8a..3ad5dfea2 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -34,7 +34,7 @@ const Player = ({ urlParams, queryParams }) => { return queryParams.has('forceTranscoding'); }, [queryParams]); - const [player, videoParamsChanged, timeChanged, pausedChanged, ended, nextVideo] = usePlayer(urlParams); + const [player, videoParamsChanged, timeChanged, seek, pausedChanged, ended, nextVideo] = usePlayer(urlParams); const [settings, updateSettings] = useSettings(); const streamingServer = useStreamingServer(); const statistics = useStatistics(player, streamingServer); @@ -42,6 +42,8 @@ const Player = ({ urlParams, queryParams }) => { const routeFocused = useRouteFocused(); const toast = useToast(); + const [seeking, setSeeking] = React.useState(false); + const [casting, setCasting] = React.useState(() => { return chromecast.active && chromecast.transport.getCastState() === cast.framework.CastState.CONNECTED; }); @@ -136,6 +138,8 @@ const Player = ({ urlParams, queryParams }) => { const onPlayRequested = React.useCallback(() => { video.setProp('paused', false); + setSeeking(false); + console.log(`setSeeking to (PlayRequested - Space): false`); }, []); const onPlayRequestedDebounced = React.useCallback(debounce(onPlayRequested, 200), []); @@ -159,6 +163,9 @@ const Player = ({ urlParams, queryParams }) => { const onSeekRequested = React.useCallback((time) => { video.setProp('time', time); + + setSeeking(true); + console.log(`setSeeking to (SeekRequested): true`); }, []); const onPlaybackSpeedChanged = React.useCallback((rate) => { @@ -341,11 +348,24 @@ const Player = ({ urlParams, queryParams }) => { video.setProp('extraSubtitlesOutlineColor', settings.subtitlesOutlineColor); }, [settings.subtitlesOutlineColor]); + React.useEffect(() => { + if (seeking && video.state.buffered) { + console.log(`setSeeking to (on !video.state.buffering): false`); + setSeeking(false); + } + }, [video.state.buffering]); + React.useEffect(() => { if (video.state.time !== null && !isNaN(video.state.time) && video.state.duration !== null && !isNaN(video.state.duration) && video.state.manifest !== null && typeof video.state.manifest.name === 'string') { - timeChanged(video.state.time, video.state.duration, video.state.manifest.name); + + if (seeking) { + seek(video.state.time, video.state.duration, video.state.manifest.name) + // timeChanged(video.state.time, video.state.duration, video.state.manifest.name); + } else { + timeChanged(video.state.time, video.state.duration, video.state.manifest.name); + } } }, [video.state.time, video.state.duration, video.state.manifest]); @@ -468,8 +488,12 @@ const Player = ({ urlParams, queryParams }) => { if (!menusOpen && !nextVideoPopupOpen && video.state.paused !== null) { if (video.state.paused) { onPlayRequested(); + setSeeking(false); + console.log(`setSeeking to (play requested - Space): false`); } else { onPauseRequested(); + setSeeking(false); + console.log(`setSeeking to (pause requested - Space): false`); } } diff --git a/src/routes/Player/usePlayer.d.ts b/src/routes/Player/usePlayer.d.ts index 8580583f3..0ee68cf56 100644 --- a/src/routes/Player/usePlayer.d.ts +++ b/src/routes/Player/usePlayer.d.ts @@ -1,2 +1,2 @@ -declare const usePlayer: (urlParams: UrlParams, videoParams: any) => [Player, (time: number, duration: number, device: string) => void, (paused: boolean) => void, () => void, () => void]; +declare const usePlayer: (urlParams: UrlParams, videoParams: { hash: string | null, size: number | null, filename: string | null } | null | undefined) => [Player, (videoParams: { hash: string | null, size: number | null, filename: string | null }) => void, (time: number, duration: number, device: string) => void, (time: number, duration: number, device: string) => void, (paused: boolean) => void, () => void, () => void,]; export = usePlayer; \ No newline at end of file diff --git a/src/routes/Player/usePlayer.js b/src/routes/Player/usePlayer.js index 9bbc1673d..9beb0ba06 100644 --- a/src/routes/Player/usePlayer.js +++ b/src/routes/Player/usePlayer.js @@ -81,6 +81,7 @@ const usePlayer = (urlParams) => { } }; } else { + console.warn("Player Unload triggered"); return { action: 'Unload' }; @@ -104,6 +105,17 @@ const usePlayer = (urlParams) => { } }, 'player'); }, []); + + const seek = React.useCallback((time, duration, device) => { + core.transport.dispatch({ + action: 'Player', + args: { + action: 'Seek', + args: { time, duration, device } + } + }, 'player'); + }, []); + const ended = React.useCallback(() => { core.transport.dispatch({ action: 'Player', @@ -129,8 +141,9 @@ const usePlayer = (urlParams) => { } }, 'player'); }, []); + const player = useModelState({ model: 'player', action, map }); - return [player, videoParamsChanged, timeChanged, pausedChanged, ended, nextVideo]; + return [player, videoParamsChanged, timeChanged, pausedChanged, ended, nextVideo, seek]; }; module.exports = usePlayer; From 5d5c28b1184ce0e02419703ae7203e3a0bf62ab2 Mon Sep 17 00:00:00 2001 From: Lachezar Lechev Date: Fri, 17 May 2024 10:19:33 +0300 Subject: [PATCH 02/27] fix(player): buffering effects for seeking Signed-off-by: Lachezar Lechev --- src/routes/Player/Player.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 3ad5dfea2..44b75c724 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -349,8 +349,8 @@ const Player = ({ urlParams, queryParams }) => { }, [settings.subtitlesOutlineColor]); React.useEffect(() => { - if (seeking && video.state.buffered) { - console.log(`setSeeking to (on !video.state.buffering): false`); + if (seeking && video.state.buffering) { + console.log(`setSeeking to (on video.state.buffering): false`); setSeeking(false); } }, [video.state.buffering]); From e66c383e23eb1840183ee0813f0d57ffdf143f14 Mon Sep 17 00:00:00 2001 From: Lachezar Lechev Date: Fri, 17 May 2024 11:24:49 +0300 Subject: [PATCH 03/27] fix: usePlayer exports and TS definition Signed-off-by: Lachezar Lechev --- src/routes/Player/usePlayer.d.ts | 2 +- src/routes/Player/usePlayer.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/Player/usePlayer.d.ts b/src/routes/Player/usePlayer.d.ts index 0ee68cf56..256424dd4 100644 --- a/src/routes/Player/usePlayer.d.ts +++ b/src/routes/Player/usePlayer.d.ts @@ -1,2 +1,2 @@ -declare const usePlayer: (urlParams: UrlParams, videoParams: { hash: string | null, size: number | null, filename: string | null } | null | undefined) => [Player, (videoParams: { hash: string | null, size: number | null, filename: string | null }) => void, (time: number, duration: number, device: string) => void, (time: number, duration: number, device: string) => void, (paused: boolean) => void, () => void, () => void,]; +declare const usePlayer: (urlParams: UrlParams) => [Player, (videoParams: { hash: string | null, size: number | null, filename: string | null }) => void, (time: number, duration: number, device: string) => void, (time: number, duration: number, device: string) => void, (paused: boolean) => void, () => void, () => void,]; export = usePlayer; \ No newline at end of file diff --git a/src/routes/Player/usePlayer.js b/src/routes/Player/usePlayer.js index 9beb0ba06..c2a2ff165 100644 --- a/src/routes/Player/usePlayer.js +++ b/src/routes/Player/usePlayer.js @@ -143,7 +143,7 @@ const usePlayer = (urlParams) => { }, []); const player = useModelState({ model: 'player', action, map }); - return [player, videoParamsChanged, timeChanged, pausedChanged, ended, nextVideo, seek]; + return [player, videoParamsChanged, timeChanged, seek, pausedChanged, ended, nextVideo]; }; module.exports = usePlayer; From 97451619990a0301155c558de73c6250ed6fe31c Mon Sep 17 00:00:00 2001 From: Lachezar Lechev Date: Fri, 17 May 2024 11:25:26 +0300 Subject: [PATCH 04/27] fix(player): setSeeking false right after seek instead of using video.state.buffering Signed-off-by: Lachezar Lechev --- src/routes/Player/Player.js | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 44b75c724..521fc2387 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -348,24 +348,19 @@ const Player = ({ urlParams, queryParams }) => { video.setProp('extraSubtitlesOutlineColor', settings.subtitlesOutlineColor); }, [settings.subtitlesOutlineColor]); - React.useEffect(() => { - if (seeking && video.state.buffering) { - console.log(`setSeeking to (on video.state.buffering): false`); - setSeeking(false); - } - }, [video.state.buffering]); - React.useEffect(() => { if (video.state.time !== null && !isNaN(video.state.time) && video.state.duration !== null && !isNaN(video.state.duration) && video.state.manifest !== null && typeof video.state.manifest.name === 'string') { - if (seeking) { - seek(video.state.time, video.state.duration, video.state.manifest.name) - // timeChanged(video.state.time, video.state.duration, video.state.manifest.name); - } else { - timeChanged(video.state.time, video.state.duration, video.state.manifest.name); - } + if (seeking) { + seek(video.state.time, video.state.duration, video.state.manifest.name) + setSeeking(false); + console.log(`setSeeking to (on video.state.time change): false`); + + } else { + timeChanged(video.state.time, video.state.duration, video.state.manifest.name); + } } }, [video.state.time, video.state.duration, video.state.manifest]); From 84ad70fc43651275d531707e6f15d9b1eeb8d940 Mon Sep 17 00:00:00 2001 From: Lachezar Lechev Date: Thu, 25 Jul 2024 15:54:01 +0300 Subject: [PATCH 05/27] fix: Player - onSeekRequest and setting the seeking flag to true before updating the video player Signed-off-by: Lachezar Lechev --- src/routes/Player/Player.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 521fc2387..670cd31e1 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -162,10 +162,11 @@ const Player = ({ urlParams, queryParams }) => { }, []); const onSeekRequested = React.useCallback((time) => { - video.setProp('time', time); - + // first set seeking to true and then update time! setSeeking(true); console.log(`setSeeking to (SeekRequested): true`); + + video.setProp('time', time); }, []); const onPlaybackSpeedChanged = React.useCallback((rate) => { @@ -354,11 +355,12 @@ const Player = ({ urlParams, queryParams }) => { video.state.manifest !== null && typeof video.state.manifest.name === 'string') { if (seeking) { - seek(video.state.time, video.state.duration, video.state.manifest.name) + seek(video.state.time, video.state.duration, video.state.manifest.name); setSeeking(false); console.log(`setSeeking to (on video.state.time change): false`); } else { + console.log(`time changed!`); timeChanged(video.state.time, video.state.duration, video.state.manifest.name); } } From 9168df4b823ce22054e4bb0c5ed0d700e2b1562b Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Wed, 31 Jul 2024 10:52:38 +0300 Subject: [PATCH 06/27] refactor: add onKeyUp to not setSeeking to false --- src/routes/Player/Player.js | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 62c842d45..8bf74ee9a 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -139,7 +139,6 @@ const Player = ({ urlParams, queryParams }) => { const onPlayRequested = React.useCallback(() => { video.setProp('paused', false); setSeeking(false); - console.log(`setSeeking to (PlayRequested - Space): false`); }, []); const onPlayRequestedDebounced = React.useCallback(debounce(onPlayRequested, 200), []); @@ -162,10 +161,8 @@ const Player = ({ urlParams, queryParams }) => { }, []); const onSeekRequested = React.useCallback((time) => { - // first set seeking to true and then update time! setSeeking(true); console.log(`setSeeking to (SeekRequested): true`); - video.setProp('time', time); }, []); @@ -353,16 +350,10 @@ const Player = ({ urlParams, queryParams }) => { if (video.state.time !== null && !isNaN(video.state.time) && video.state.duration !== null && !isNaN(video.state.duration) && video.state.manifest !== null && typeof video.state.manifest.name === 'string') { - - if (seeking) { - seek(video.state.time, video.state.duration, video.state.manifest.name); - setSeeking(false); - console.log(`setSeeking to (on video.state.time change): false`); - - } else { - console.log(`time changed!`); + seeking ? + seek(video.state.time, video.state.duration, video.state.manifest.name) + : timeChanged(video.state.time, video.state.duration, video.state.manifest.name); - } } }, [video.state.time, video.state.duration, video.state.manifest]); @@ -489,8 +480,6 @@ const Player = ({ urlParams, queryParams }) => { console.log(`setSeeking to (play requested - Space): false`); } else { onPauseRequested(); - setSeeking(false); - console.log(`setSeeking to (pause requested - Space): false`); } } @@ -574,6 +563,12 @@ const Player = ({ urlParams, queryParams }) => { } } }; + const onKeyUp = (event) => { + if (event.code === 'ArrowRight' || event.code === 'ArrowLeft') { + setSeeking(false); + console.log(`setSeeking to (key up - ArrowRight/ArrowLeft): false`); + } + }; const onWheel = ({ deltaY }) => { if (deltaY > 0) { if (!menusOpen && video.state.volume !== null) { @@ -587,10 +582,12 @@ const Player = ({ urlParams, queryParams }) => { }; if (routeFocused) { window.addEventListener('keydown', onKeyDown); + window.addEventListener('keyup', onKeyUp); window.addEventListener('wheel', onWheel); } return () => { window.removeEventListener('keydown', onKeyDown); + window.removeEventListener('keyup', onKeyUp); window.removeEventListener('wheel', onWheel); }; }, [player.metaItem, player.selected, streamingServer.statistics, settings.seekTimeDuration, settings.seekShortTimeDuration, 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, toggleInfoMenu, toggleVideosMenu, toggleStatisticsMenu]); From 42ca0550ae1b9c6d4013ffe96d2f7fed69968074 Mon Sep 17 00:00:00 2001 From: ArtificialSloth Date: Sun, 22 Sep 2024 00:17:06 -0400 Subject: [PATCH 07/27] feat/subtitles-track-label --- src/routes/Player/SubtitlesMenu/SubtitlesMenu.js | 5 ++++- src/routes/Player/SubtitlesMenu/styles.less | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/routes/Player/SubtitlesMenu/SubtitlesMenu.js b/src/routes/Player/SubtitlesMenu/SubtitlesMenu.js index 0130c58e2..23b44eb35 100644 --- a/src/routes/Player/SubtitlesMenu/SubtitlesMenu.js +++ b/src/routes/Player/SubtitlesMenu/SubtitlesMenu.js @@ -204,7 +204,10 @@ const SubtitlesMenu = React.memo((props) => {
{subtitlesTracksForLanguage.map((track, index) => (