basic autoplay timer working

This commit is contained in:
Sean Yesmunt 2020-01-27 13:52:25 -05:00
parent 28f2a9da0a
commit d312a8e8b6
7 changed files with 146 additions and 31 deletions

View file

@ -0,0 +1,22 @@
import * as SETTINGS from 'constants/settings';
import { connect } from 'react-redux';
import { makeSelectClaimForUri } from 'lbry-redux';
import { makeSelectNextUnplayedRecommended } from 'redux/selectors/content';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import RecommendedVideos from './view';
const select = (state, props) => {
const nextRecommendedUri = makeSelectNextUnplayedRecommended(props.uri)(state);
return {
nextRecommendedUri,
nextRecommendedClaim: makeSelectClaimForUri(nextRecommendedUri)(state),
autoplay: makeSelectClientSetting(SETTINGS.AUTOPLAY)(state),
};
};
const perform = (dispatch, ownProps) => ({});
export default connect(
select,
perform
)(RecommendedVideos);

View file

@ -0,0 +1,66 @@
// @flow
import React from 'react';
import Button from 'component/button';
import UriIndicator from 'component/uriIndicator';
import { formatLbryUrlForWeb } from 'util/url';
import { withRouter } from 'react-router';
type Props = {
history: { push: string => void },
nextRecommendedClaim: ?StreamClaim,
nextRecommendedUri: string,
};
function AutoplayCountdown(props: Props) {
const {
nextRecommendedUri,
nextRecommendedClaim,
history: { push },
} = props;
const nextTitle = nextRecommendedClaim && nextRecommendedClaim.value && nextRecommendedClaim.value.title;
const [timer, setTimer] = React.useState(5);
const [timerCanceled, setTimerCanceled] = React.useState(false);
let navigateUrl;
if (nextTitle) {
navigateUrl = formatLbryUrlForWeb(nextRecommendedUri);
}
React.useEffect(() => {
let interval;
if (!timerCanceled) {
interval = setInterval(() => {
const newTime = timer - 1;
if (newTime === 0) {
push(navigateUrl);
} else {
setTimer(timer - 1);
}
}, 1000);
}
return () => {
clearInterval(interval);
};
}, [timer, navigateUrl, push, timerCanceled]);
if (timerCanceled) {
return null;
}
return (
<div className="video-overlay__wrapper">
<div className="video-overlay__subtitle">Up Next</div>
<div className="video-overlay__title">{nextTitle}</div>
<UriIndicator link uri={nextRecommendedUri} />
<div className="video-overlay__actions">
<div className="video-overlay__subtitle">Playing in {timer} seconds</div>
<div className="section__actions--centered">
<Button label={__('Cancel')} button="secondary" onClick={() => setTimerCanceled(true)} />
</div>
</div>
</div>
);
}
export default withRouter(AutoplayCountdown);

View file

@ -8,13 +8,13 @@ import {
makeSelectDownloadPathForUri,
makeSelectFileNameForUri,
} from 'lbry-redux';
import { THEME, AUTOPLAY } from 'constants/settings';
import * as SETTINGS from 'constants/settings';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import { makeSelectNextUnplayedRecommended, makeSelectIsText } from 'redux/selectors/content';
import { makeSelectIsText } from 'redux/selectors/content';
import FileRender from './view';
const select = (state, props) => ({
currentTheme: makeSelectClientSetting(THEME)(state),
currentTheme: makeSelectClientSetting(SETTINGS.THEME)(state),
claim: makeSelectClaimForUri(props.uri)(state),
mediaType: makeSelectMediaTypeForUri(props.uri)(state),
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
@ -22,8 +22,6 @@ const select = (state, props) => ({
downloadPath: makeSelectDownloadPathForUri(props.uri)(state),
fileName: makeSelectFileNameForUri(props.uri)(state),
streamingUrl: makeSelectStreamingUrlForUri(props.uri)(state),
autoplay: makeSelectClientSetting(AUTOPLAY)(state),
nextUnplayed: makeSelectNextUnplayedRecommended(props.uri)(state),
isText: makeSelectIsText(props.uri)(state),
});

View file

@ -8,7 +8,7 @@ import ImageViewer from 'component/viewers/imageViewer';
import AppViewer from 'component/viewers/appViewer';
import Button from 'component/button';
import { withRouter } from 'react-router-dom';
import { formatLbryUrlForWeb } from 'util/url';
import AutoplayCountdown from 'component/autoplayCountdown';
// @if TARGET='web'
import { generateStreamUrl } from 'util/lbrytv';
// @endif
@ -36,16 +36,20 @@ type Props = {
currentTheme: string,
downloadPath: string,
fileName: string,
autoplay: boolean,
nextFileToPlay: string,
nextUnplayed: string,
history: { push: string => void },
};
class FileRender extends React.PureComponent<Props> {
type State = {
showAutoplayCountdown: boolean,
};
class FileRender extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
showAutoplayCountdown: false,
};
(this: any).escapeListener = this.escapeListener.bind(this);
(this: any).onEndedCb = this.onEndedCb.bind(this);
}
@ -73,10 +77,7 @@ class FileRender extends React.PureComponent<Props> {
}
onEndedCb() {
const { autoplay, nextUnplayed, history } = this.props;
if (autoplay && nextUnplayed) {
history.push(formatLbryUrlForWeb(nextUnplayed));
}
this.setState({ showAutoplayCountdown: true });
}
renderViewer() {
@ -188,10 +189,12 @@ class FileRender extends React.PureComponent<Props> {
}
render() {
const { isText } = this.props;
const { isText, uri } = this.props;
const { showAutoplayCountdown } = this.state;
return (
<div className={classnames('file-render', { 'file-render--document': isText })}>
{showAutoplayCountdown && <AutoplayCountdown uri={uri} />}
<Suspense fallback={<div />}>{this.renderViewer()}</Suspense>
</div>
);

View file

@ -38,7 +38,6 @@ type Props = {
changeVolume: number => void,
savePosition: (string, number) => void,
changeMute: boolean => void,
setPlayingUri: (string | null) => void,
source: string,
contentType: string,
thumbnail: string,
@ -48,18 +47,7 @@ type Props = {
};
function VideoViewer(props: Props) {
const {
contentType,
source,
setPlayingUri,
onEndedCB,
changeVolume,
changeMute,
volume,
muted,
thumbnail,
claim,
} = props;
const { contentType, source, onEndedCB, changeVolume, changeMute, volume, muted, thumbnail, claim } = props;
const claimId = claim && claim.claim_id;
const videoRef = useRef();
const isAudio = contentType.includes('audio');
@ -85,13 +73,13 @@ function VideoViewer(props: Props) {
}
function doEnded() {
// clear position
setPlayingUri(null);
onEndedCB();
}
function doPause(e: Event) {
// store position e.target.currentTime
}
function doVolume(e: Event) {
// $FlowFixMe volume is missing in EventTarget
changeVolume(e.target.volume);

View file

@ -153,3 +153,36 @@
}
}
}
.video-overlay__wrapper {
position: absolute;
left: auto;
right: auto;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.9);
z-index: 999;
color: var(--color-white);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.button--uri-indicator {
color: var(--color-gray-3);
}
}
.video-overlay__title {
@extend .section__title;
margin-top: var(--spacing-medium);
margin-bottom: var(--spacing-small);
}
.video-overlay__subtitle {
color: var(--color-gray-3);
margin: var(--spacing-medium) 0;
}
.video-overlay__actions {
margin-top: var(--spacing-large);
}

View file

@ -92,6 +92,11 @@
margin-top: var(--spacing-medium);
}
.section__actions--centered {
@extend .section__actions;
justify-content: center;
}
@media (max-width: $breakpoint-small) {
.section__actions {
flex-wrap: wrap;