From 3bd2738001b8def0c0a758d6a3369a84fb2ea434 Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 3 Nov 2022 05:44:40 +0100 Subject: [PATCH 01/16] feat(Player): implement next video popup --- .../Player/NextVideoPopup/NextVideoPopup.js | 114 ++++++++++++++++ src/routes/Player/NextVideoPopup/index.js | 3 + src/routes/Player/NextVideoPopup/styles.less | 122 ++++++++++++++++++ src/routes/Player/Player.js | 52 ++++++-- 4 files changed, 283 insertions(+), 8 deletions(-) create mode 100644 src/routes/Player/NextVideoPopup/NextVideoPopup.js create mode 100644 src/routes/Player/NextVideoPopup/index.js create mode 100644 src/routes/Player/NextVideoPopup/styles.less diff --git a/src/routes/Player/NextVideoPopup/NextVideoPopup.js b/src/routes/Player/NextVideoPopup/NextVideoPopup.js new file mode 100644 index 000000000..6198a5b2a --- /dev/null +++ b/src/routes/Player/NextVideoPopup/NextVideoPopup.js @@ -0,0 +1,114 @@ +const React = require('react'); +const PropTypes = require('prop-types'); +const classnames = require('classnames'); +const Icon = require('@stremio/stremio-icons/dom'); +const { Image, Button } = require('stremio/common'); +const styles = require('./styles'); + +const ICON_FOR_TYPE = new Map([ + ['movie', 'ic_movies'], + ['series', 'ic_series'], + ['channel', 'ic_channels'], + ['tv', 'ic_tv'], + ['book', 'ic_book'], + ['game', 'ic_games'], + ['music', 'ic_music'], + ['adult', 'ic_adult'], + ['radio', 'ic_radio'], + ['podcast', 'ic_podcast'], + ['other', 'ic_movies'], +]); + +const NextVideoPopup = ({ className, metaItem, nextVideo, onDismiss, onPlayNextVideoRequested }) => { + const watchNowButtonRef = React.useRef(null); + const [animationEnded, setAnimationEnded] = React.useState(false); + const videoName = React.useMemo(() => { + const title = nextVideo && nextVideo.title || metaItem && metaItem.title; + return nextVideo !== null && + typeof nextVideo.season === 'number' && + typeof nextVideo.episode === 'number' ? + `${title} (S${nextVideo.season}E${nextVideo.episode})` + : + title; + }, [metaItem, nextVideo]); + const onAnimationEnd = React.useCallback(() => { + setAnimationEnded(true); + }, []); + const renderPosterFallback = React.useCallback(() => { + return metaItem !== null && typeof metaItem.type === 'string' ? + + : + null; + }, [metaItem]); + const onDismissButtonClick = React.useCallback(() => { + if (typeof onDismiss === 'function') { + onDismiss(); + } + }, [onDismiss]); + const onWatchNowButtonClick = React.useCallback(() => { + if (typeof onPlayNextVideoRequested === 'function') { + onPlayNextVideoRequested(); + } + }, [onPlayNextVideoRequested]); + React.useLayoutEffect(() => { + if (animationEnded === true && watchNowButtonRef.current !== null) { + watchNowButtonRef.current.focus(); + } + }, [animationEnded]); + return ( +
+
+ {' +
+
+
+ { + typeof videoName === 'string' ? +
+ { videoName } +
+ : + null + } + { + nextVideo !== null && typeof nextVideo.overview === 'string' ? +
+ { nextVideo.overview } +
+ : + null + } +
+
+ + +
+
+
+ ); +}; + +NextVideoPopup.propTypes = { + className: PropTypes.string, + metaItem: PropTypes.object, + nextVideo: PropTypes.object, + onDismiss: PropTypes.func, + onPlayNextVideoRequested: PropTypes.func +}; + +module.exports = NextVideoPopup; diff --git a/src/routes/Player/NextVideoPopup/index.js b/src/routes/Player/NextVideoPopup/index.js new file mode 100644 index 000000000..9c10ee432 --- /dev/null +++ b/src/routes/Player/NextVideoPopup/index.js @@ -0,0 +1,3 @@ +const NextEpisodeModal = require('./NextVideoPopup'); + +module.exports = NextEpisodeModal; diff --git a/src/routes/Player/NextVideoPopup/styles.less b/src/routes/Player/NextVideoPopup/styles.less new file mode 100644 index 000000000..20bfe08db --- /dev/null +++ b/src/routes/Player/NextVideoPopup/styles.less @@ -0,0 +1,122 @@ +@import (reference) '~@stremio/stremio-colors/less/stremio-colors.less'; + +.next-video-popup-container { + display: flex; + flex-direction: row; + height: 16rem; + width: 40rem; + animation: slide-fade-in 0.5s ease-in; + + @keyframes slide-fade-in { + 0% { + opacity: 0; + transform: translateX(calc(40rem + 2rem)); + } + + 100% { + opacity: 1; + transform: translateX(0); + } + } + + .poster-container { + flex: 1 1 40%; + display: flex; + justify-content: center; + align-items: center; + background-color: @color-background; + + .poster-image { + flex: none; + width: 100%; + height: 100%; + object-position: center; + object-fit: cover; + } + + .placeholder-icon { + flex: none; + width: 80%; + height: 50%; + fill: @color-background-light3-90; + } + } + + .info-container { + flex: 1 1 70%; + display: flex; + flex-direction: column; + + .details-container { + flex: auto; + padding: 1.5rem 1.5rem; + + .name { + flex: none; + align-self: stretch; + max-height: 2.4em; + font-weight: 600; + margin-bottom: 0.5rem; + color: @color-surface-light5-90; + } + + .description { + color: @color-surface-light5-50; + } + } + + .buttons-container { + display: flex; + flex-direction: row; + + .spacing { + flex: 0 0 50%; + } + + .button-container { + flex: 0 0 50%; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + height: 3.5rem; + + &.play-button { + background-color: @color-accent3; + + .icon { + fill: @color-surface-light5-90; + } + + .label { + color: @color-surface-light5-90; + } + + &:hover, &:focus { + background-color: @color-accent3-light1; + } + } + + .icon { + flex: none; + width: 1.4rem; + height: 1.4rem; + margin-right: 1rem; + fill: @color-secondaryvariant1-90; + } + + .label { + flex: none; + max-height: 2.4em; + font-size: 1.1rem; + font-weight: 500; + color: @color-secondaryvariant1-90; + } + + &:hover, &:focus { + background-color: @color-background-light2; + } + } + } + } +} \ No newline at end of file diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index a8f7c2c3f..d11c17e16 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -10,6 +10,7 @@ const { HorizontalNavBar, Button, useFullscreen, useBinaryState, useToast, useSt const Icon = require('@stremio/stremio-icons/dom'); const BufferingLoader = require('./BufferingLoader'); const ControlBar = require('./ControlBar'); +const NextVideoPopup = require('./NextVideoPopup'); const InfoMenu = require('./InfoMenu'); const VideosMenu = require('./VideosMenu'); const SubtitlesMenu = require('./SubtitlesMenu'); @@ -40,6 +41,8 @@ const Player = ({ urlParams, queryParams }) => { const [subtitlesMenuOpen, , closeSubtitlesMenu, toggleSubtitlesMenu] = useBinaryState(false); const [infoMenuOpen, , closeInfoMenu, toggleInfoMenu] = useBinaryState(false); const [videosMenuOpen, , closeVideosMenu, toggleVideosMenu] = useBinaryState(false); + const [nextVideoPopupOpen, openNextVideoPopup, closeNextVideoPopup] = useBinaryState(false); + const nextVideoPopupDismissed = React.useRef(false); const [error, setError] = React.useState(null); const [videoState, setVideoState] = React.useReducer( (videoState, nextVideoState) => ({ ...videoState, ...nextVideoState }), @@ -100,16 +103,11 @@ const Player = ({ urlParams, queryParams }) => { ended(); pushToLibrary(); if (player.nextVideo !== null) { - window.location.replace( - typeof player.nextVideo.deepLinks.player === 'string' ? - player.nextVideo.deepLinks.player - : - player.nextVideo.deepLinks.metaDetailsStreams - ); + onPlayNextVideoRequested(); } else { window.history.back(); } - }, [player.libraryItem, player.nextVideo]); + }, [player.libraryItem, player.nextVideo, onPlayNextVideoRequested]); const onError = React.useCallback((error) => { console.error('Player', error); if (error.critical) { @@ -179,6 +177,20 @@ const Player = ({ urlParams, queryParams }) => { const onSubtitlesOffsetChanged = React.useCallback((offset) => { updateSettings({ subtitlesOffset: offset }); }, [updateSettings]); + const onDismissNextVideoPopup = React.useCallback(() => { + closeNextVideoPopup(); + nextVideoPopupDismissed.current = true; + }, []); + const onPlayNextVideoRequested = React.useCallback(() => { + if (player.nextVideo !== null) { + window.location.replace( + typeof player.nextVideo.deepLinks.player === 'string' ? + player.nextVideo.deepLinks.player + : + player.nextVideo.deepLinks.metaDetailsStreams + ); + } + }, [player.nextVideo]); const onVideoClick = React.useCallback(() => { if (videoState.paused !== null) { if (videoState.paused) { @@ -313,6 +325,17 @@ const Player = ({ urlParams, queryParams }) => { pausedChanged(videoState.paused); } }, [videoState.paused]); + React.useEffect(() => { + if (nextVideoPopupDismissed.current === false) { + if (videoState.time !== null && !isNaN(videoState.time) && videoState.duration !== null && !isNaN(videoState.duration)) { + if (videoState.time < videoState.duration && (videoState.duration - videoState.time) <= (35 * 1000)) { + openNextVideoPopup(); + } else { + closeNextVideoPopup(); + } + } + } + }, [videoState.time, videoState.duration]); React.useEffect(() => { if ((!Array.isArray(videoState.subtitlesTracks) || videoState.subtitlesTracks.length === 0) && (!Array.isArray(videoState.extraSubtitlesTracks) || videoState.extraSubtitlesTracks.length === 0) && @@ -439,6 +462,7 @@ const Player = ({ urlParams, queryParams }) => { closeSubtitlesMenu(); closeInfoMenu(); closeVideosMenu(); + onDismissNextVideoPopup(); break; } } @@ -458,7 +482,7 @@ const Player = ({ urlParams, queryParams }) => { }; }, []); return ( -
{ onMouseMove={onBarMouseMove} onMouseOver={onBarMouseMove} /> + { + !subtitlesMenuOpen && !infoMenuOpen && !videosMenuOpen && nextVideoPopupOpen ? + + : + null + } { subtitlesMenuOpen ? Date: Thu, 3 Nov 2022 05:45:39 +0100 Subject: [PATCH 02/16] refactor: move ICON_FOR_TYPE to CONSTANTS --- src/common/CONSTANTS.js | 16 +++++++++++++++- src/common/MetaItem/MetaItem.js | 15 +-------------- .../Player/NextVideoPopup/NextVideoPopup.js | 18 ++---------------- 3 files changed, 18 insertions(+), 31 deletions(-) diff --git a/src/common/CONSTANTS.js b/src/common/CONSTANTS.js index e755790bb..b5ee0b4fc 100644 --- a/src/common/CONSTANTS.js +++ b/src/common/CONSTANTS.js @@ -25,6 +25,19 @@ const TYPE_PRIORITIES = { adult: 1, other: -Infinity }; +const ICON_FOR_TYPE = new Map([ + ['movie', 'ic_movies'], + ['series', 'ic_series'], + ['channel', 'ic_channels'], + ['tv', 'ic_tv'], + ['book', 'ic_book'], + ['game', 'ic_games'], + ['music', 'ic_music'], + ['adult', 'ic_adult'], + ['radio', 'ic_radio'], + ['podcast', 'ic_podcast'], + ['other', 'ic_movies'], +]); module.exports = { CHROMECAST_RECEIVER_APP_ID, @@ -39,5 +52,6 @@ module.exports = { IMDB_LINK_CATEGORY, SHARE_LINK_CATEGORY, WRITERS_LINK_CATEGORY, - TYPE_PRIORITIES + TYPE_PRIORITIES, + ICON_FOR_TYPE }; diff --git a/src/common/MetaItem/MetaItem.js b/src/common/MetaItem/MetaItem.js index 5175b2ed6..0196cbf65 100644 --- a/src/common/MetaItem/MetaItem.js +++ b/src/common/MetaItem/MetaItem.js @@ -10,22 +10,9 @@ const Image = require('stremio/common/Image'); const Multiselect = require('stremio/common/Multiselect'); const PlayIconCircleCentered = require('stremio/common/PlayIconCircleCentered'); const useBinaryState = require('stremio/common/useBinaryState'); +const { ICON_FOR_TYPE } = require('stremio/common/CONSTANTS'); const styles = require('./styles'); -const ICON_FOR_TYPE = new Map([ - ['movie', 'ic_movies'], - ['series', 'ic_series'], - ['channel', 'ic_channels'], - ['tv', 'ic_tv'], - ['book', 'ic_book'], - ['game', 'ic_games'], - ['music', 'ic_music'], - ['adult', 'ic_adult'], - ['radio', 'ic_radio'], - ['podcast', 'ic_podcast'], - ['other', 'ic_movies'], -]); - const MetaItem = React.memo(({ className, type, name, poster, posterShape, playIcon, progress, options, deepLinks, dataset, optionOnSelect, ...props }) => { const [menuOpen, onMenuOpen, onMenuClose] = useBinaryState(false); const href = React.useMemo(() => { diff --git a/src/routes/Player/NextVideoPopup/NextVideoPopup.js b/src/routes/Player/NextVideoPopup/NextVideoPopup.js index 6198a5b2a..d424920a0 100644 --- a/src/routes/Player/NextVideoPopup/NextVideoPopup.js +++ b/src/routes/Player/NextVideoPopup/NextVideoPopup.js @@ -2,23 +2,9 @@ const React = require('react'); const PropTypes = require('prop-types'); const classnames = require('classnames'); const Icon = require('@stremio/stremio-icons/dom'); -const { Image, Button } = require('stremio/common'); +const { Image, Button, CONSTANTS } = require('stremio/common'); const styles = require('./styles'); -const ICON_FOR_TYPE = new Map([ - ['movie', 'ic_movies'], - ['series', 'ic_series'], - ['channel', 'ic_channels'], - ['tv', 'ic_tv'], - ['book', 'ic_book'], - ['game', 'ic_games'], - ['music', 'ic_music'], - ['adult', 'ic_adult'], - ['radio', 'ic_radio'], - ['podcast', 'ic_podcast'], - ['other', 'ic_movies'], -]); - const NextVideoPopup = ({ className, metaItem, nextVideo, onDismiss, onPlayNextVideoRequested }) => { const watchNowButtonRef = React.useRef(null); const [animationEnded, setAnimationEnded] = React.useState(false); @@ -38,7 +24,7 @@ const NextVideoPopup = ({ className, metaItem, nextVideo, onDismiss, onPlayNextV return metaItem !== null && typeof metaItem.type === 'string' ? : null; From d1a028ebaa274fe18fa8da32f4a63e1c9eedbc04 Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 3 Nov 2022 05:55:05 +0100 Subject: [PATCH 03/16] fix(NextVideoPopup): missing copyright headers --- src/routes/Player/NextVideoPopup/NextVideoPopup.js | 2 ++ src/routes/Player/NextVideoPopup/index.js | 2 ++ src/routes/Player/NextVideoPopup/styles.less | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/routes/Player/NextVideoPopup/NextVideoPopup.js b/src/routes/Player/NextVideoPopup/NextVideoPopup.js index d424920a0..2b5d1972d 100644 --- a/src/routes/Player/NextVideoPopup/NextVideoPopup.js +++ b/src/routes/Player/NextVideoPopup/NextVideoPopup.js @@ -1,3 +1,5 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + const React = require('react'); const PropTypes = require('prop-types'); const classnames = require('classnames'); diff --git a/src/routes/Player/NextVideoPopup/index.js b/src/routes/Player/NextVideoPopup/index.js index 9c10ee432..a666bc7e0 100644 --- a/src/routes/Player/NextVideoPopup/index.js +++ b/src/routes/Player/NextVideoPopup/index.js @@ -1,3 +1,5 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + const NextEpisodeModal = require('./NextVideoPopup'); module.exports = NextEpisodeModal; diff --git a/src/routes/Player/NextVideoPopup/styles.less b/src/routes/Player/NextVideoPopup/styles.less index 20bfe08db..81a566a24 100644 --- a/src/routes/Player/NextVideoPopup/styles.less +++ b/src/routes/Player/NextVideoPopup/styles.less @@ -1,3 +1,5 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + @import (reference) '~@stremio/stremio-colors/less/stremio-colors.less'; .next-video-popup-container { From 8775e978a4d838e44926040d5766e7a435555da2 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 28 Nov 2022 11:25:31 +0100 Subject: [PATCH 04/16] fix(Player): reset nextVideoPopupDismissed on stream change --- src/routes/Player/Player.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index f21ec7c5a..d14dc4d55 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -381,6 +381,7 @@ const Player = ({ urlParams, queryParams }) => { React.useEffect(() => { defaultSubtitlesSelected.current = false; defaultAudioTrackSelected.current = false; + nextVideoPopupDismissed.current = false; }, [videoState.stream]); React.useEffect(() => { if ((!Array.isArray(videoState.subtitlesTracks) || videoState.subtitlesTracks.length === 0) && From 44944ce3d09032b4fcbc5d827b6862a32b89d0b6 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 28 Nov 2022 11:26:46 +0100 Subject: [PATCH 05/16] refactor(Player): improve conditions for next video popup --- src/routes/Player/Player.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index d14dc4d55..0eb1c35be 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -341,13 +341,11 @@ const Player = ({ urlParams, queryParams }) => { } }, [videoState.paused]); React.useEffect(() => { - if (nextVideoPopupDismissed.current === false) { - if (videoState.time !== null && !isNaN(videoState.time) && videoState.duration !== null && !isNaN(videoState.duration)) { - if (videoState.time < videoState.duration && (videoState.duration - videoState.time) <= (35 * 1000)) { - openNextVideoPopup(); - } else { - closeNextVideoPopup(); - } + if (!nextVideoPopupDismissed.current) { + if (videoState.time !== null && videoState.duration !== null && videoState.time < videoState.duration && (videoState.duration - videoState.time) <= (35 * 1000)) { + openNextVideoPopup(); + } else { + closeNextVideoPopup(); } } }, [videoState.time, videoState.duration]); @@ -632,7 +630,7 @@ const Player = ({ urlParams, queryParams }) => { onMouseOver={onBarMouseMove} /> { - !subtitlesMenuOpen && !infoMenuOpen && !videosMenuOpen && nextVideoPopupOpen ? + nextVideoPopupOpen ? Date: Mon, 28 Nov 2022 11:29:27 +0100 Subject: [PATCH 06/16] refactor(Player): remove player.libraryItem from onEnded callback deps --- src/routes/Player/Player.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 0eb1c35be..711970aa4 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -113,7 +113,7 @@ const Player = ({ urlParams, queryParams }) => { } else { window.history.back(); } - }, [player.libraryItem, player.nextVideo, onPlayNextVideoRequested]); + }, [player.nextVideo, onPlayNextVideoRequested]); const onError = React.useCallback((error) => { console.error('Player', error); if (error.critical) { From 796ec387aa653cdb1008208f815fb5fcc578736c Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 28 Nov 2022 11:30:43 +0100 Subject: [PATCH 07/16] refactor(Player): incorrect naming for NextVideoPopup index --- src/routes/Player/NextVideoPopup/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/Player/NextVideoPopup/index.js b/src/routes/Player/NextVideoPopup/index.js index a666bc7e0..b79c4bfdd 100644 --- a/src/routes/Player/NextVideoPopup/index.js +++ b/src/routes/Player/NextVideoPopup/index.js @@ -1,5 +1,5 @@ // Copyright (C) 2017-2022 Smart code 203358507 -const NextEpisodeModal = require('./NextVideoPopup'); +const NextVideoPopup = require('./NextVideoPopup'); -module.exports = NextEpisodeModal; +module.exports = NextVideoPopup; From e8f3291c345fe256ec2b3e5213323afd09189d92 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 28 Nov 2022 11:43:26 +0100 Subject: [PATCH 08/16] fix(Player): do not show next video popup if bingeWatching is not enabled --- src/routes/Player/Player.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 711970aa4..90049161c 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -341,7 +341,7 @@ const Player = ({ urlParams, queryParams }) => { } }, [videoState.paused]); React.useEffect(() => { - if (!nextVideoPopupDismissed.current) { + if (!!settings.bingeWatching && !nextVideoPopupDismissed.current) { if (videoState.time !== null && videoState.duration !== null && videoState.time < videoState.duration && (videoState.duration - videoState.time) <= (35 * 1000)) { openNextVideoPopup(); } else { From 166fde909090eb2b58da4b672ea27f10ab75bd18 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 28 Nov 2022 12:00:38 +0100 Subject: [PATCH 09/16] fix(Player): do not show next video popup if nextVideo is null --- src/routes/Player/Player.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 90049161c..ee57a7d27 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -630,7 +630,7 @@ const Player = ({ urlParams, queryParams }) => { onMouseOver={onBarMouseMove} /> { - nextVideoPopupOpen ? + player.nextVideo !== null && nextVideoPopupOpen ? Date: Mon, 28 Nov 2022 12:02:03 +0100 Subject: [PATCH 10/16] chore: remove double entry for langs in package.json --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index f93083d7b..e87c617f7 100755 --- a/package.json +++ b/package.json @@ -24,7 +24,6 @@ "classnames": "2.3.1", "eventemitter3": "4.0.7", "filter-invalid-dom-props": "2.1.0", - "langs": "^2.0.0", "hat": "0.0.3", "langs": "^2.0.0", "lodash.debounce": "4.0.8", From 77282695dace2c5fb80ef8d75479f95f9b78ed14 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 28 Nov 2022 12:26:33 +0100 Subject: [PATCH 11/16] chore: update stremio-core-web --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 586ff67cf..ef6320fc5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@babel/runtime": "7.16.0", "@sentry/browser": "6.13.3", "@stremio/stremio-colors": "5.0.1", - "@stremio/stremio-core-web": "0.44.6", + "@stremio/stremio-core-web": "0.44.7", "@stremio/stremio-icons": "4.0.0", "@stremio/stremio-video": "0.0.24", "a-color-picker": "1.2.1", @@ -2699,9 +2699,9 @@ "integrity": "sha512-Dt3PYmy1DZ473QNs99KYXVWQPHtpIl37VUY0+gCEvvuCqE1fRrZIJtZ9KbysUKonvO7WwdQDztgcW0iGoc1dEA==" }, "node_modules/@stremio/stremio-core-web": { - "version": "0.44.6", - "resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.44.6.tgz", - "integrity": "sha512-Mxc6oRKgTuXU80JEacJIe4TphccZUJkyHTMUZnUx9sotVetGX+EJsyvr+HLKNMDGJHx5xcwGT/BUikdyQR/Lpw==", + "version": "0.44.7", + "resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.44.7.tgz", + "integrity": "sha512-hkeYLfL1On4TMBHn87Onrp93aeRuTh4YXMKdDR1Vz5YikPOiPEq/JRoLLmmSSsFEdifs6Egu+A0qiggTttepOA==", "dependencies": { "@babel/runtime": "7.16.0" } @@ -16716,9 +16716,9 @@ "integrity": "sha512-Dt3PYmy1DZ473QNs99KYXVWQPHtpIl37VUY0+gCEvvuCqE1fRrZIJtZ9KbysUKonvO7WwdQDztgcW0iGoc1dEA==" }, "@stremio/stremio-core-web": { - "version": "0.44.6", - "resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.44.6.tgz", - "integrity": "sha512-Mxc6oRKgTuXU80JEacJIe4TphccZUJkyHTMUZnUx9sotVetGX+EJsyvr+HLKNMDGJHx5xcwGT/BUikdyQR/Lpw==", + "version": "0.44.7", + "resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.44.7.tgz", + "integrity": "sha512-hkeYLfL1On4TMBHn87Onrp93aeRuTh4YXMKdDR1Vz5YikPOiPEq/JRoLLmmSSsFEdifs6Egu+A0qiggTttepOA==", "requires": { "@babel/runtime": "7.16.0" } diff --git a/package.json b/package.json index e87c617f7..2242f5f80 100755 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "@babel/runtime": "7.16.0", "@sentry/browser": "6.13.3", "@stremio/stremio-colors": "5.0.1", - "@stremio/stremio-core-web": "0.44.6", + "@stremio/stremio-core-web": "0.44.7", "@stremio/stremio-icons": "4.0.0", "@stremio/stremio-video": "0.0.24", "a-color-picker": "1.2.1", From b51f607ffe1cb8e6d3378f8c5aba422560558a17 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 28 Nov 2022 12:37:31 +0100 Subject: [PATCH 12/16] feat: add next video popup duration setting --- src/common/CONSTANTS.js | 2 ++ src/routes/Settings/Settings.js | 10 +++++++ .../Settings/useProfileSettingsInputs.js | 26 +++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/src/common/CONSTANTS.js b/src/common/CONSTANTS.js index b5ee0b4fc..af7105214 100644 --- a/src/common/CONSTANTS.js +++ b/src/common/CONSTANTS.js @@ -4,6 +4,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 NEXT_VIDEO_POPUP_DURATIONS = [0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000]; const CATALOG_PREVIEW_SIZE = 10; const CATALOG_PAGE_SIZE = 100; const NONE_EXTRA_VALUE = 'None'; @@ -44,6 +45,7 @@ module.exports = { SUBTITLES_SIZES, SUBTITLES_FONTS, SEEK_TIME_DURATIONS, + NEXT_VIDEO_POPUP_DURATIONS, CATALOG_PREVIEW_SIZE, CATALOG_PAGE_SIZE, NONE_EXTRA_VALUE, diff --git a/src/routes/Settings/Settings.js b/src/routes/Settings/Settings.js index 85c790094..5faf90309 100644 --- a/src/routes/Settings/Settings.js +++ b/src/routes/Settings/Settings.js @@ -30,6 +30,7 @@ const Settings = () => { subtitlesOutlineColorInput, audioLanguageSelect, seekTimeDurationSelect, + nextVideoPopupDurationSelect, bingeWatchingCheckbox, playInBackgroundCheckbox, playInExternalPlayerCheckbox, @@ -338,6 +339,15 @@ const Settings = () => { {...bingeWatchingCheckbox} />
+
+
+
Next video popup duration
+
+ +
Play in background
diff --git a/src/routes/Settings/useProfileSettingsInputs.js b/src/routes/Settings/useProfileSettingsInputs.js index f7bcb9885..e861f15ed 100644 --- a/src/routes/Settings/useProfileSettingsInputs.js +++ b/src/routes/Settings/useProfileSettingsInputs.js @@ -153,6 +153,31 @@ const useProfileSettingsInputs = (profile) => { }); } }), [profile.settings]); + const nextVideoPopupDurationSelect = React.useMemo(() => ({ + options: CONSTANTS.NEXT_VIDEO_POPUP_DURATIONS.map((duration) => ({ + value: `${duration}`, + label: duration === 0 ? 'Disabled' : `${duration / 1000} seconds` + })), + selected: [`${profile.settings.nextVideoNotificationDuration}`], + renderLabelText: () => { + return profile.settings.nextVideoNotificationDuration === 0 ? + 'Disabled' + : + `${profile.settings.nextVideoNotificationDuration / 1000} seconds`; + }, + onSelect: (event) => { + core.transport.dispatch({ + action: 'Ctx', + args: { + action: 'UpdateSettings', + args: { + ...profile.settings, + nextVideoNotificationDuration: parseInt(event.value, 10) + } + } + }); + } + }), [profile.settings]); const bingeWatchingCheckbox = React.useMemo(() => ({ checked: profile.settings.bingeWatching, onClick: () => { @@ -237,6 +262,7 @@ const useProfileSettingsInputs = (profile) => { subtitlesOutlineColorInput, audioLanguageSelect, seekTimeDurationSelect, + nextVideoPopupDurationSelect, bingeWatchingCheckbox, playInBackgroundCheckbox, playInExternalPlayerCheckbox, From 0a7ef22eb6a859134de40ae57da7436e05c56183 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 28 Nov 2022 12:41:00 +0100 Subject: [PATCH 13/16] refactor(Player): use nextVideoNotificationDuration setting to trigger next video popup --- src/routes/Player/Player.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index ee57a7d27..7df74bc6a 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -342,7 +342,7 @@ const Player = ({ urlParams, queryParams }) => { }, [videoState.paused]); React.useEffect(() => { if (!!settings.bingeWatching && !nextVideoPopupDismissed.current) { - if (videoState.time !== null && videoState.duration !== null && videoState.time < videoState.duration && (videoState.duration - videoState.time) <= (35 * 1000)) { + if (videoState.time !== null && videoState.duration !== null && videoState.time < videoState.duration && (videoState.duration - videoState.time) <= settings.nextVideoNotificationDuration) { openNextVideoPopup(); } else { closeNextVideoPopup(); From 1612343d7395667d09eda9fc9a8259c906f72634 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 28 Nov 2022 13:12:56 +0100 Subject: [PATCH 14/16] refactor(Button): set lower opacity when disabled --- src/common/Button/styles.less | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/Button/styles.less b/src/common/Button/styles.less index 734368666..c34d67ad3 100644 --- a/src/common/Button/styles.less +++ b/src/common/Button/styles.less @@ -14,5 +14,6 @@ &:global(.disabled) { pointer-events: none; + opacity: 0.25; } } \ No newline at end of file From 262fbbdf1134250564e14b78a466ce0877d0b049 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 28 Nov 2022 13:15:05 +0100 Subject: [PATCH 15/16] refactor(Settings): disable next video popup setting when auto-play is unchecked --- src/routes/Settings/Settings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/routes/Settings/Settings.js b/src/routes/Settings/Settings.js index 5faf90309..3b99b20fb 100644 --- a/src/routes/Settings/Settings.js +++ b/src/routes/Settings/Settings.js @@ -345,6 +345,7 @@ const Settings = () => {
From d138753b8f2935ca5211aa64a26c376bce809f86 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 28 Nov 2022 18:15:48 +0100 Subject: [PATCH 16/16] refactor(Player): move nextVideo check in useEffect --- src/routes/Player/Player.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 7df74bc6a..e797c28cb 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -341,14 +341,14 @@ const Player = ({ urlParams, queryParams }) => { } }, [videoState.paused]); React.useEffect(() => { - if (!!settings.bingeWatching && !nextVideoPopupDismissed.current) { + if (!!settings.bingeWatching && player.nextVideo !== null && !nextVideoPopupDismissed.current) { if (videoState.time !== null && videoState.duration !== null && videoState.time < videoState.duration && (videoState.duration - videoState.time) <= settings.nextVideoNotificationDuration) { openNextVideoPopup(); } else { closeNextVideoPopup(); } } - }, [videoState.time, videoState.duration]); + }, [player.nextVideo, videoState.time, videoState.duration]); React.useEffect(() => { if (!defaultSubtitlesSelected.current) { const findTrackByLang = (tracks, lang) => tracks.find((track) => track.lang === lang || langs.where('1', track.lang)?.[2] === lang); @@ -630,7 +630,7 @@ const Player = ({ urlParams, queryParams }) => { onMouseOver={onBarMouseMove} /> { - player.nextVideo !== null && nextVideoPopupOpen ? + nextVideoPopupOpen ?