diff --git a/lbrytv/component/fileViewerEmbeddedEnded/index.js b/lbrytv/component/fileViewerEmbeddedEnded/index.js
new file mode 100644
index 000000000..159805381
--- /dev/null
+++ b/lbrytv/component/fileViewerEmbeddedEnded/index.js
@@ -0,0 +1,7 @@
+import { connect } from 'react-redux';
+import fileViewerEmbeddedEnded from './view';
+import { selectUserVerifiedEmail } from 'lbryinc';
+
+export default connect(state => ({
+ isAuthenticated: selectUserVerifiedEmail(state),
+}))(fileViewerEmbeddedEnded);
diff --git a/lbrytv/component/fileViewerEmbeddedEnded/view.jsx b/lbrytv/component/fileViewerEmbeddedEnded/view.jsx
new file mode 100644
index 000000000..ec190deff
--- /dev/null
+++ b/lbrytv/component/fileViewerEmbeddedEnded/view.jsx
@@ -0,0 +1,55 @@
+// @flow
+import React from 'react';
+import Button from 'component/button';
+import { formatLbryUrlForWeb } from 'util/url';
+import { withRouter } from 'react-router';
+import { URL } from 'config';
+import * as ICONS from 'constants/icons';
+
+type Props = {
+ uri: string,
+ isAuthenticated: boolean,
+};
+
+function fileViewerEmbeddedEnded(props: Props) {
+ const { uri, isAuthenticated } = props;
+
+ const prompts = isAuthenticated
+ ? {
+ discuss_auth: 'Continue the discussion on lbry.tv',
+ tip_auth: 'Always tip your creators',
+ }
+ : {
+ bigtech_unauth: 'Together, we can take back control from big tech',
+ discuss_unauth: 'Continue the discussion on lbry.tv',
+ find_unauth: 'Find more great content on lbry.tv',
+ a_b_unauth: "We test a lot of messages here. Wouldn't it be funny if the one telling you that did the best?",
+ earn_unauth: 'Join lbry.tv and earn to watch.',
+ blockchain_unauth: "Now if anyone asks, you can say you've used a blockchain.",
+ };
+
+ const promptKeys = Object.keys(prompts);
+ const promptKey = promptKeys[Math.floor(Math.random() * promptKeys.length)];
+ const prompt = prompts[promptKey];
+ const lbrytvLink = `${URL}${formatLbryUrlForWeb(uri)}?src=${promptKey}`;
+
+ return (
+
+
+
+
+
{prompt}
+
+
+ {!isAuthenticated && }
+
+
+ );
+}
+
+export default withRouter(fileViewerEmbeddedEnded);
diff --git a/lbrytv/component/fileViewerEmbeddedTitle/index.js b/lbrytv/component/fileViewerEmbeddedTitle/index.js
new file mode 100644
index 000000000..513d9dd95
--- /dev/null
+++ b/lbrytv/component/fileViewerEmbeddedTitle/index.js
@@ -0,0 +1,9 @@
+import { connect } from 'react-redux';
+import fileViewerEmbeddedTitle from './view';
+import { makeSelectTitleForUri } from 'lbry-redux';
+
+export default connect((state, props) => {
+ return {
+ title: makeSelectTitleForUri(props.uri)(state),
+ };
+})(fileViewerEmbeddedTitle);
diff --git a/lbrytv/component/fileViewerEmbeddedTitle/view.jsx b/lbrytv/component/fileViewerEmbeddedTitle/view.jsx
new file mode 100644
index 000000000..db65ba6f5
--- /dev/null
+++ b/lbrytv/component/fileViewerEmbeddedTitle/view.jsx
@@ -0,0 +1,27 @@
+// @flow
+import React from 'react';
+import Button from 'component/button';
+import { formatLbryUrlForWeb } from 'util/url';
+import { withRouter } from 'react-router';
+import { URL } from 'config';
+import * as ICONS from 'constants/icons';
+
+type Props = {
+ uri: string,
+ title: ?string,
+};
+
+function fileViewerEmbeddedTitle(props: Props) {
+ const { uri, title } = props;
+
+ const lbrytvLink = `${URL}${formatLbryUrlForWeb(uri)}?src=embed`;
+
+ return (
+
+
+
+
+ );
+}
+
+export default withRouter(fileViewerEmbeddedTitle);
diff --git a/package.json b/package.json
index 3e7978aeb..880eb4a55 100644
--- a/package.json
+++ b/package.json
@@ -51,7 +51,8 @@
"electron-notarize": "^0.1.1",
"electron-updater": "^4.2.4",
"express": "^4.17.1",
- "if-env": "^1.0.4"
+ "if-env": "^1.0.4",
+ "videojs-logo": "^2.0.0"
},
"devDependencies": {
"@babel/core": "^7.0.0",
diff --git a/ui/component/app/view.jsx b/ui/component/app/view.jsx
index 10b5e17b7..a1d5fef0c 100644
--- a/ui/component/app/view.jsx
+++ b/ui/component/app/view.jsx
@@ -284,7 +284,7 @@ function App(props: Props) {
-
+
{isEnhancedLayout && }
{/* @if TARGET='app' */}
diff --git a/ui/component/autoplayCountdown/index.js b/ui/component/autoplayCountdown/index.js
index e965abcc3..8683ad57e 100644
--- a/ui/component/autoplayCountdown/index.js
+++ b/ui/component/autoplayCountdown/index.js
@@ -1,16 +1,17 @@
import * as SETTINGS from 'constants/settings';
import { connect } from 'react-redux';
import { makeSelectClaimForUri } from 'lbry-redux';
-import { makeSelectNextUnplayedRecommended } from 'redux/selectors/content';
+import { makeSelectIsPlayerFloating, makeSelectNextUnplayedRecommended } from 'redux/selectors/content';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import { doSetPlayingUri } from 'redux/actions/content';
-import RecommendedVideos from './view';
+import AutoplayCountdown from './view';
const select = (state, props) => {
const nextRecommendedUri = makeSelectNextUnplayedRecommended(props.uri)(state);
return {
nextRecommendedUri,
nextRecommendedClaim: makeSelectClaimForUri(nextRecommendedUri)(state),
+ isFloating: makeSelectIsPlayerFloating(props.location)(state),
autoplay: makeSelectClientSetting(SETTINGS.AUTOPLAY)(state),
};
};
@@ -19,7 +20,4 @@ const perform = dispatch => ({
setPlayingUri: uri => dispatch(doSetPlayingUri(uri)),
});
-export default connect(
- select,
- perform
-)(RecommendedVideos);
+export default connect(select, perform)(AutoplayCountdown);
diff --git a/ui/component/autoplayCountdown/view.jsx b/ui/component/autoplayCountdown/view.jsx
index 83121d136..2813807cd 100644
--- a/ui/component/autoplayCountdown/view.jsx
+++ b/ui/component/autoplayCountdown/view.jsx
@@ -10,6 +10,7 @@ type Props = {
history: { push: string => void },
nextRecommendedClaim: ?StreamClaim,
nextRecommendedUri: string,
+ isFloating: boolean,
setPlayingUri: (string | null) => void,
};
@@ -18,10 +19,15 @@ function AutoplayCountdown(props: Props) {
nextRecommendedUri,
nextRecommendedClaim,
setPlayingUri,
+ isFloating,
history: { push },
} = props;
const nextTitle = nextRecommendedClaim && nextRecommendedClaim.value && nextRecommendedClaim.value.title;
- const [timer, setTimer] = React.useState(5);
+
+ /* this value is coupled with CSS timing variables on .autoplay-countdown__timer */
+ const countdownTime = 1000;
+
+ const [timer, setTimer] = React.useState(countdownTime);
const [timerCanceled, setTimerCanceled] = React.useState(false);
let navigateUrl;
@@ -29,15 +35,24 @@ function AutoplayCountdown(props: Props) {
navigateUrl = formatLbryUrlForWeb(nextRecommendedUri);
}
+ function doNavigate() {
+ // FIXME: make autoplay continue in floating player
+ if (!isFloating) {
+ // if not floating
+ setPlayingUri(null);
+ push(navigateUrl);
+ } else {
+ setPlayingUri(nextRecommendedUri);
+ }
+ }
+
React.useEffect(() => {
let interval;
if (!timerCanceled) {
interval = setInterval(() => {
const newTime = timer - 1;
if (newTime === 0) {
- // Set the playingUri to null so the app doesn't try to make a floating window with the video that just finished
- setPlayingUri(null);
- push(navigateUrl);
+ doNavigate();
} else {
setTimer(timer - 1);
}
@@ -46,28 +61,31 @@ function AutoplayCountdown(props: Props) {
return () => {
clearInterval(interval);
};
- }, [timer, navigateUrl, push, timerCanceled, setPlayingUri, nextRecommendedUri]);
+ }, [timer, doNavigate, navigateUrl, push, timerCanceled, setPlayingUri, nextRecommendedUri]);
- if (timerCanceled) {
+ if (timerCanceled || !nextRecommendedUri) {
return null;
}
return (
-
-
- }}>
- Up Next by %channel%
-
-
-
{nextTitle}
+
+
+
+ }}>
+ Up Next by %channel%
+
+
-
-
- {__('Playing in %seconds_left% seconds', { seconds_left: timer })}
-
{title || uri}
diff --git a/ui/component/fileRenderInitiator/view.jsx b/ui/component/fileRenderInitiator/view.jsx
index 2d5ef9ae6..88d1c71d1 100644
--- a/ui/component/fileRenderInitiator/view.jsx
+++ b/ui/component/fileRenderInitiator/view.jsx
@@ -1,6 +1,6 @@
// @flow
// This component is entirely for triggering the start of a file view
-// The actual viewer for a file exists in TextViewer and FloatingViewer
+// The actual viewer for a file exists in TextViewer and FileRenderFloating
// They can't exist in one component because we need to handle/listen for the start of a new file view
// while a file is currently being viewed
import React, { useEffect, useCallback } from 'react';
@@ -89,7 +89,7 @@ export default function FileRenderInitiator(props: Props) {
if (isFree && ((autoplay && !videoOnPage && isPlayable) || RENDER_MODES.AUTO_RENDER_MODES.includes(renderMode))) {
viewFile();
}
- }, [autoplay, viewFile, isFree, renderMode]);
+ }, [autoplay, viewFile, isFree, renderMode, isPlayable]);
/*
once content is playing, let the appropriate take care of it...
diff --git a/ui/component/fileRenderInline/view.jsx b/ui/component/fileRenderInline/view.jsx
index ca11075a1..417a704b0 100644
--- a/ui/component/fileRenderInline/view.jsx
+++ b/ui/component/fileRenderInline/view.jsx
@@ -35,6 +35,9 @@ export default function FileRenderInline(props: Props) {
}, [isPlaying, setPlayTime, uri]);
useEffect(() => {
+ /*
+ note: code can currently double fire with videoViewer logic if a video is rendered by FileRenderInline (currently this never happens)
+ */
if (playTime && isReadyToPlay) {
const timeToStart = Date.now() - playTime;
diff --git a/ui/component/viewers/appViewer/view.jsx b/ui/component/viewers/appViewer/view.jsx
index ceebbd253..f4358d26e 100644
--- a/ui/component/viewers/appViewer/view.jsx
+++ b/ui/component/viewers/appViewer/view.jsx
@@ -48,7 +48,7 @@ function AppViewer(props: Props) {
);
// return (
- //
+ //
// {!appUrl && (
// {
const errorMessage = __("Sorry, looks like we can't load the document.");
return (
-
+
{loading && !error && }
{error && }
{isReady && this.renderDocument()}
diff --git a/ui/component/viewers/docxViewer.jsx b/ui/component/viewers/docxViewer.jsx
index c8a69590b..b3e9fba16 100644
--- a/ui/component/viewers/docxViewer.jsx
+++ b/ui/component/viewers/docxViewer.jsx
@@ -58,7 +58,7 @@ class DocxViewer extends React.PureComponent {
const errorMessage = __("Sorry, looks like we can't load the document.");
return (
-