diff --git a/ui/component/autoplayCountdown/index.js b/ui/component/autoplayCountdown/index.js
new file mode 100644
index 000000000..e7e53d559
--- /dev/null
+++ b/ui/component/autoplayCountdown/index.js
@@ -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);
diff --git a/ui/component/autoplayCountdown/view.jsx b/ui/component/autoplayCountdown/view.jsx
new file mode 100644
index 000000000..645cbed1f
--- /dev/null
+++ b/ui/component/autoplayCountdown/view.jsx
@@ -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 (
+
+
Up Next
+
{nextTitle}
+
+
+
+
Playing in {timer} seconds
+
+
+
+
+ );
+}
+
+export default withRouter(AutoplayCountdown);
diff --git a/ui/component/fileRender/index.js b/ui/component/fileRender/index.js
index f99740d5a..99f1979e1 100644
--- a/ui/component/fileRender/index.js
+++ b/ui/component/fileRender/index.js
@@ -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),
});
diff --git a/ui/component/fileRender/view.jsx b/ui/component/fileRender/view.jsx
index cf00f12f8..e2250db0b 100644
--- a/ui/component/fileRender/view.jsx
+++ b/ui/component/fileRender/view.jsx
@@ -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 {
+type State = {
+ showAutoplayCountdown: boolean,
+};
+
+class FileRender extends React.PureComponent {
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 {
}
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 {
}
render() {
- const { isText } = this.props;
+ const { isText, uri } = this.props;
+ const { showAutoplayCountdown } = this.state;
return (
+ {showAutoplayCountdown &&
}
}>{this.renderViewer()}
);
diff --git a/ui/component/viewers/videoViewer/view.jsx b/ui/component/viewers/videoViewer/view.jsx
index b54858be9..cd48c50ed 100644
--- a/ui/component/viewers/videoViewer/view.jsx
+++ b/ui/component/viewers/videoViewer/view.jsx
@@ -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);
diff --git a/ui/scss/component/_file-render.scss b/ui/scss/component/_file-render.scss
index c96698934..1613db1d5 100644
--- a/ui/scss/component/_file-render.scss
+++ b/ui/scss/component/_file-render.scss
@@ -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);
+}
diff --git a/ui/scss/component/section.scss b/ui/scss/component/section.scss
index bfe266c44..16c3584c5 100644
--- a/ui/scss/component/section.scss
+++ b/ui/scss/component/section.scss
@@ -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;