From 39db18046f3914c8c24778c553dafea236cca676 Mon Sep 17 00:00:00 2001 From: infiinte-persistence Date: Mon, 22 Jun 2020 14:55:52 +0800 Subject: [PATCH] Pause 'Autoplay' when scrolled off screen. Fixes #-4021. ## Changes: When the autoplay overlay gets partially off-screen, the timer will be stopped. We can tweak how much down it needs to be scrolled. When timer is paused, the countdown resets. The pausing mechanism has no effect on the floating player (since the 'top' can never go negative). This behavior is the same as another big video platform. --- static/app-strings.json | 2 + ui/component/autoplayCountdown/view.jsx | 65 ++++++++++++++++++++----- 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/static/app-strings.json b/static/app-strings.json index 290d773c8..af3a61203 100644 --- a/static/app-strings.json +++ b/static/app-strings.json @@ -1199,6 +1199,8 @@ "No information will be sent directly to LBRY, Inc. or third-parties about your usage. Note that as\n peer-to-peer software, your IP address and potentially other system information can be sent to other\n users, though this information is not stored permanently.": "No information will be sent directly to LBRY, Inc. or third-parties about your usage. Note that as\n peer-to-peer software, your IP address and potentially other system information can be sent to other\n users, though this information is not stored permanently.", "%view_count% Views": "%view_count% Views", "Tap to unmute": "Tap to unmute", + "Playing in %seconds_left% seconds...": "Playing in %seconds_left% seconds...", + "Autoplay timer paused.": "Autoplay timer paused.", "0 Bytes": "0 Bytes", "Bytes": "Bytes", "KB": "KB", diff --git a/ui/component/autoplayCountdown/view.jsx b/ui/component/autoplayCountdown/view.jsx index cb680cc62..6c7825b83 100644 --- a/ui/component/autoplayCountdown/view.jsx +++ b/ui/component/autoplayCountdown/view.jsx @@ -31,6 +31,7 @@ function AutoplayCountdown(props: Props) { const [timer, setTimer] = React.useState(countdownTime); const [timerCanceled, setTimerCanceled] = React.useState(false); + const [timerPaused, setTimerPaused] = React.useState(false); let navigateUrl; if (nextTitle) { @@ -52,22 +53,53 @@ function AutoplayCountdown(props: Props) { } }, [navigateUrl, nextRecommendedUri, isFloating, doSetPlayingUri, doPlayUri]); + function debounce(fn, time) { + let timeoutId; + return wrapper; + function wrapper(...args) { + if (timeoutId) { + clearTimeout(timeoutId); + } + timeoutId = setTimeout(() => { + timeoutId = null; + fn(...args); + }, time); + } + } + + React.useEffect(() => { + const handleScroll = debounce(e => { + const elm = document.querySelector('.autoplay-countdown'); + if (elm) { + setTimerPaused(elm.getBoundingClientRect().top < 0); + } + }, 150); + + window.addEventListener('scroll', handleScroll); + return () => window.removeEventListener('scroll', handleScroll); + }, []); + React.useEffect(() => { let interval; if (!timerCanceled && nextRecommendedUri) { - interval = setInterval(() => { - const newTime = timer - 1; - if (newTime === 0) { - doNavigate(); - } else { - setTimer(timer - 1); - } - }, 1000); + if (timerPaused) { + clearInterval(interval); + setTimer(countdownTime); + } else { + interval = setInterval(() => { + const newTime = timer - 1; + if (newTime === 0) { + doNavigate(); + } else { + setTimer(timer - 1); + } + }, 1000); + } } return () => { clearInterval(interval); }; - }, [timer, doNavigate, navigateUrl, push, timerCanceled, nextRecommendedUri]); + }, [timer, doNavigate, navigateUrl, push, timerCanceled, timerPaused, nextRecommendedUri]); if (timerCanceled || !nextRecommendedUri) { return null; @@ -87,10 +119,17 @@ function AutoplayCountdown(props: Props) {
-
- {__('Playing in %seconds_left% seconds...', { seconds_left: timer })}{' '} -
+ {timerPaused && ( +
+ {__('Autoplay timer paused.')}{' '} +
+ )} + {!timerPaused && ( +
+ {__('Playing in %seconds_left% seconds...', { seconds_left: timer })}{' '} +
+ )}