diff --git a/src/common/CONSTANTS.js b/src/common/CONSTANTS.js index f5702fd4e..ff9d18e58 100644 --- a/src/common/CONSTANTS.js +++ b/src/common/CONSTANTS.js @@ -3,6 +3,7 @@ const CHROMECAST_RECEIVER_APP_ID = '1634F54B'; const SUBTITLES_SIZES = [75, 100, 125, 150, 175, 200, 250]; const SUBTITLES_FONTS = ['Roboto', 'Arial', 'Halvetica', 'Times New Roman', 'Verdana', 'Courier', 'Lucida Console', 'sans-serif', 'serif', 'monospace']; +const SEEK_TIME_DURATIONS = [5000, 10000, 15000, 20000, 25000, 30000]; const CATALOG_PREVIEW_SIZE = 10; const CATALOG_PAGE_SIZE = 100; const NONE_EXTRA_VALUE = 'None'; @@ -28,6 +29,7 @@ module.exports = { CHROMECAST_RECEIVER_APP_ID, SUBTITLES_SIZES, SUBTITLES_FONTS, + SEEK_TIME_DURATIONS, CATALOG_PREVIEW_SIZE, CATALOG_PAGE_SIZE, NONE_EXTRA_VALUE, diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 42fc7a2aa..af4a341a0 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -344,14 +344,16 @@ const Player = ({ urlParams, queryParams }) => { } case 'ArrowRight': { if (!subtitlesMenuOpen && !infoMenuOpen && videoState.time !== null) { - onSeekRequested(videoState.time + 15000); + const seekTimeMultiplier = event.shiftKey ? 3 : 1; + onSeekRequested(videoState.time + (settings.seekTimeDuration * seekTimeMultiplier)); } break; } case 'ArrowLeft': { if (!subtitlesMenuOpen && !infoMenuOpen && videoState.time !== null) { - onSeekRequested(videoState.time - 15000); + const seekTimeMultiplier = event.shiftKey ? 3 : 1; + onSeekRequested(videoState.time - (settings.seekTimeDuration * seekTimeMultiplier)); } break; @@ -399,7 +401,7 @@ const Player = ({ urlParams, queryParams }) => { return () => { window.removeEventListener('keydown', onKeyDown); }; - }, [player, routeFocused, subtitlesMenuOpen, infoMenuOpen, videoState.paused, videoState.time, videoState.volume, videoState.subtitlesTracks, toggleSubtitlesMenu, toggleInfoMenu]); + }, [player, routeFocused, subtitlesMenuOpen, infoMenuOpen, videoState.paused, videoState.time, videoState.volume, videoState.subtitlesTracks, toggleSubtitlesMenu, toggleInfoMenu, settings.seekTimeDuration]); React.useLayoutEffect(() => { return () => { setImmersedDebounced.cancel(); diff --git a/src/routes/Settings/Settings.js b/src/routes/Settings/Settings.js index 546912994..8d4ac199f 100644 --- a/src/routes/Settings/Settings.js +++ b/src/routes/Settings/Settings.js @@ -27,6 +27,7 @@ const Settings = () => { subtitlesTextColorInput, subtitlesBackgroundColorInput, subtitlesOutlineColorInput, + seekTimeDuration, bingeWatchingCheckbox, playInBackgroundCheckbox, playInExternalPlayerCheckbox, @@ -303,6 +304,15 @@ const Settings = () => { {...subtitlesOutlineColorInput} /> +
+
+
Arrow keys seek time
+
+ +
Auto-play next episode
diff --git a/src/routes/Settings/useProfileSettingsInputs.js b/src/routes/Settings/useProfileSettingsInputs.js index 26619afce..479b1bf49 100644 --- a/src/routes/Settings/useProfileSettingsInputs.js +++ b/src/routes/Settings/useProfileSettingsInputs.js @@ -110,6 +110,28 @@ const useProfileSettingsInputs = (profile) => { }); } }), [profile.settings]); + const seekTimeDuration = useDeepEqualMemo(() => ({ + options: CONSTANTS.SEEK_TIME_DURATIONS.map((size) => ({ + value: `${size}`, + label: `${size / 1000}s` + })), + selected: [`${profile.settings.seekTimeDuration}`], + renderLabelText: () => { + return `${profile.settings.seekTimeDuration / 1000}s`; + }, + onSelect: (event) => { + core.transport.dispatch({ + action: 'Ctx', + args: { + action: 'UpdateSettings', + args: { + ...profile.settings, + seekTimeDuration: parseInt(event.value, 10) + } + } + }); + } + }), [profile.settings]); const bingeWatchingCheckbox = useDeepEqualMemo(() => ({ checked: profile.settings.bingeWatching, onClick: () => { @@ -192,6 +214,7 @@ const useProfileSettingsInputs = (profile) => { subtitlesTextColorInput, subtitlesBackgroundColorInput, subtitlesOutlineColorInput, + seekTimeDuration, bingeWatchingCheckbox, playInBackgroundCheckbox, playInExternalPlayerCheckbox,