lbry-desktop/ui/component/autoplayCountdown/view.jsx

134 lines
4.2 KiB
React
Raw Normal View History

2020-01-27 19:52:25 +01:00
// @flow
2020-04-16 23:43:09 +02:00
import React, { useCallback } from 'react';
2020-01-27 19:52:25 +01:00
import Button from 'component/button';
import UriIndicator from 'component/uriIndicator';
2020-01-27 21:02:58 +01:00
import I18nMessage from 'component/i18nMessage';
2020-01-27 19:52:25 +01:00
import { formatLbryUrlForWeb } from 'util/url';
import { withRouter } from 'react-router';
import debounce from 'util/debounce';
const DEBOUNCE_SCROLL_HANDLER_MS = 150;
const CLASSNAME_AUTOPLAY_COUNTDOWN = 'autoplay-countdown';
2020-01-27 19:52:25 +01:00
type Props = {
history: { push: string => void },
nextRecommendedClaim: ?StreamClaim,
nextRecommendedUri: string,
2020-04-14 01:48:11 +02:00
isFloating: boolean,
2020-05-26 19:11:01 +02:00
doSetPlayingUri: (string | null) => void,
doPlayUri: string => void,
modal: { id: string, modalProps: {} },
2020-01-27 19:52:25 +01:00
};
function AutoplayCountdown(props: Props) {
const {
nextRecommendedUri,
nextRecommendedClaim,
2020-05-26 19:11:01 +02:00
doSetPlayingUri,
doPlayUri,
2020-04-14 01:48:11 +02:00
isFloating,
2020-01-27 19:52:25 +01:00
history: { push },
modal,
2020-01-27 19:52:25 +01:00
} = props;
const nextTitle = nextRecommendedClaim && nextRecommendedClaim.value && nextRecommendedClaim.value.title;
2020-04-14 01:48:11 +02:00
/* this value is coupled with CSS timing variables on .autoplay-countdown__timer */
2020-04-14 01:50:52 +02:00
const countdownTime = 5;
2020-04-14 01:48:11 +02:00
const [timer, setTimer] = React.useState(countdownTime);
2020-01-27 19:52:25 +01:00
const [timerCanceled, setTimerCanceled] = React.useState(false);
const [timerPaused, setTimerPaused] = React.useState(false);
const anyModalPresent = modal !== undefined && modal !== null;
const isTimerPaused = timerPaused || anyModalPresent;
2020-01-27 19:52:25 +01:00
let navigateUrl;
if (nextTitle) {
navigateUrl = formatLbryUrlForWeb(nextRecommendedUri);
}
2020-04-16 23:43:09 +02:00
const doNavigate = useCallback(() => {
2020-04-14 01:48:11 +02:00
if (!isFloating) {
2020-04-16 23:43:09 +02:00
if (navigateUrl) {
push(navigateUrl);
2020-05-26 19:11:01 +02:00
doSetPlayingUri(nextRecommendedUri);
doPlayUri(nextRecommendedUri);
2020-04-16 23:43:09 +02:00
}
2020-04-14 01:48:11 +02:00
} else {
2020-04-16 23:43:09 +02:00
if (nextRecommendedUri) {
2020-05-26 19:11:01 +02:00
doSetPlayingUri(nextRecommendedUri);
doPlayUri(nextRecommendedUri);
2020-04-16 23:43:09 +02:00
}
2020-04-14 01:48:11 +02:00
}
2020-05-26 19:11:01 +02:00
}, [navigateUrl, nextRecommendedUri, isFloating, doSetPlayingUri, doPlayUri]);
2020-04-14 01:48:11 +02:00
React.useEffect(() => {
const handleScroll = debounce(e => {
const elm = document.querySelector(`.${CLASSNAME_AUTOPLAY_COUNTDOWN}`);
if (elm) {
setTimerPaused(elm.getBoundingClientRect().top < 0);
}
}, DEBOUNCE_SCROLL_HANDLER_MS);
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
2020-01-27 19:52:25 +01:00
React.useEffect(() => {
let interval;
2020-04-16 23:43:09 +02:00
if (!timerCanceled && nextRecommendedUri) {
if (isTimerPaused) {
clearInterval(interval);
setTimer(countdownTime);
} else {
interval = setInterval(() => {
const newTime = timer - 1;
if (newTime === 0) {
doNavigate();
} else {
setTimer(timer - 1);
}
}, 1000);
}
2020-01-27 19:52:25 +01:00
}
return () => {
clearInterval(interval);
};
}, [timer, doNavigate, navigateUrl, push, timerCanceled, isTimerPaused, nextRecommendedUri]);
2020-01-27 19:52:25 +01:00
2020-04-14 01:48:11 +02:00
if (timerCanceled || !nextRecommendedUri) {
2020-01-27 19:52:25 +01:00
return null;
}
return (
2020-04-14 01:48:11 +02:00
<div className="file-viewer__overlay">
<div className={CLASSNAME_AUTOPLAY_COUNTDOWN}>
2020-04-14 01:48:11 +02:00
<div className="file-viewer__overlay-secondary">
<I18nMessage tokens={{ channel: <UriIndicator link uri={nextRecommendedUri} /> }}>
Up Next by %channel%
</I18nMessage>
2020-01-27 20:32:20 +01:00
</div>
2020-04-14 01:48:11 +02:00
<div className="file-viewer__overlay-title">{nextTitle}</div>
<div className="autoplay-countdown__timer">
<div className={'autoplay-countdown__button autoplay-countdown__button--' + (timer % 5)}>
<Button onClick={doNavigate} iconSize={30} title={__('Play')} className="button--icon button--play" />
</div>
{isTimerPaused && (
<div className="file-viewer__overlay-secondary autoplay-countdown__counter">
{__('Autoplay timer paused.')}{' '}
</div>
)}
{!isTimerPaused && (
<div className="file-viewer__overlay-secondary autoplay-countdown__counter">
{__('Playing in %seconds_left% seconds...', { seconds_left: timer })}{' '}
<Button label={__('Cancel')} button="link" onClick={() => setTimerCanceled(true)} />
</div>
)}
2020-01-27 19:52:25 +01:00
</div>
</div>
</div>
);
}
export default withRouter(AutoplayCountdown);