Fix autoplay in floating mode

Closes 5000: AutoPlay in Floating Player only works one time

Factor out the code that queries the recommendation. It needs to be called in two places:
(1) `RecommendedContent` - need to cover the case of floating player + visit another video page.
(2) When video is floating and autoplayed the next video.
This commit is contained in:
infinite-persistence 2021-03-19 23:04:12 +08:00 committed by Sean Yesmunt
parent 8ab0bcd545
commit d279d70770
5 changed files with 55 additions and 36 deletions

View file

@ -1,5 +1,11 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeSelectFileInfoForUri, makeSelectTitleForUri, makeSelectStreamingUrlForUri, SETTINGS } from 'lbry-redux'; import {
makeSelectFileInfoForUri,
makeSelectTitleForUri,
makeSelectStreamingUrlForUri,
makeSelectClaimIsNsfw,
SETTINGS,
} from 'lbry-redux';
import { import {
makeSelectIsPlayerFloating, makeSelectIsPlayerFloating,
selectPrimaryUri, selectPrimaryUri,
@ -8,6 +14,7 @@ import {
} from 'redux/selectors/content'; } from 'redux/selectors/content';
import { makeSelectClientSetting } from 'redux/selectors/settings'; import { makeSelectClientSetting } from 'redux/selectors/settings';
import { doSetPlayingUri } from 'redux/actions/content'; import { doSetPlayingUri } from 'redux/actions/content';
import { doFetchRecommendedContent } from 'redux/actions/search';
import { withRouter } from 'react-router'; import { withRouter } from 'react-router';
import FileRenderFloating from './view'; import FileRenderFloating from './view';
@ -22,6 +29,7 @@ const select = (state, props) => {
playingUri, playingUri,
title: makeSelectTitleForUri(uri)(state), title: makeSelectTitleForUri(uri)(state),
fileInfo: makeSelectFileInfoForUri(uri)(state), fileInfo: makeSelectFileInfoForUri(uri)(state),
mature: makeSelectClaimIsNsfw(props.uri)(state),
isFloating: makeSelectIsPlayerFloating(props.location)(state), isFloating: makeSelectIsPlayerFloating(props.location)(state),
streamingUrl: makeSelectStreamingUrlForUri(uri)(state), streamingUrl: makeSelectStreamingUrlForUri(uri)(state),
floatingPlayerEnabled: makeSelectClientSetting(SETTINGS.FLOATING_PLAYER)(state), floatingPlayerEnabled: makeSelectClientSetting(SETTINGS.FLOATING_PLAYER)(state),
@ -30,8 +38,9 @@ const select = (state, props) => {
}; };
}; };
const perform = dispatch => ({ const perform = (dispatch) => ({
closeFloatingPlayer: () => dispatch(doSetPlayingUri({ uri: null })), closeFloatingPlayer: () => dispatch(doSetPlayingUri({ uri: null })),
doFetchRecommendedContent: (uri, mature) => dispatch(doFetchRecommendedContent(uri, mature)),
}); });
export default withRouter(connect(select, perform)(FileRenderFloating)); export default withRouter(connect(select, perform)(FileRenderFloating));

View file

@ -22,6 +22,7 @@ export const INLINE_PLAYER_WRAPPER_CLASS = 'inline-player__wrapper';
type Props = { type Props = {
isFloating: boolean, isFloating: boolean,
fileInfo: FileListItem, fileInfo: FileListItem,
mature: boolean,
uri: string, uri: string,
streamingUrl?: string, streamingUrl?: string,
title: ?string, title: ?string,
@ -31,11 +32,13 @@ type Props = {
playingUri: ?PlayingUri, playingUri: ?PlayingUri,
primaryUri: ?string, primaryUri: ?string,
videoTheaterMode: boolean, videoTheaterMode: boolean,
doFetchRecommendedContent: (string, boolean) => void,
}; };
export default function FileRenderFloating(props: Props) { export default function FileRenderFloating(props: Props) {
const { const {
fileInfo, fileInfo,
mature,
uri, uri,
streamingUrl, streamingUrl,
title, title,
@ -46,6 +49,7 @@ export default function FileRenderFloating(props: Props) {
playingUri, playingUri,
primaryUri, primaryUri,
videoTheaterMode, videoTheaterMode,
doFetchRecommendedContent,
} = props; } = props;
const { const {
location: { pathname }, location: { pathname },
@ -201,6 +205,12 @@ export default function FileRenderFloating(props: Props) {
}; };
}, [uri]); }, [uri]);
useEffect(() => {
if (isFloating) {
doFetchRecommendedContent(uri, mature);
}
}, [uri, mature, isFloating]);
if (!isPlayable || !uri || (isFloating && (isMobile || !floatingPlayerEnabled))) { if (!isPlayable || !uri || (isFloating && (isMobile || !floatingPlayerEnabled))) {
return null; return null;
} }

View file

@ -1,13 +1,12 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeSelectClaimForUri, makeSelectClaimIsNsfw } from 'lbry-redux'; import { makeSelectClaimIsNsfw } from 'lbry-redux';
import { doSearch } from 'redux/actions/search'; import { doFetchRecommendedContent } from 'redux/actions/search';
import { makeSelectRecommendedContentForUri, selectIsSearching } from 'redux/selectors/search'; import { makeSelectRecommendedContentForUri, selectIsSearching } from 'redux/selectors/search';
import { selectUserVerifiedEmail } from 'redux/selectors/user'; import { selectUserVerifiedEmail } from 'redux/selectors/user';
import { makeSelectNextUnplayedRecommended } from 'redux/selectors/content'; import { makeSelectNextUnplayedRecommended } from 'redux/selectors/content';
import RecommendedVideos from './view'; import RecommendedVideos from './view';
const select = (state, props) => ({ const select = (state, props) => ({
claim: makeSelectClaimForUri(props.uri)(state),
mature: makeSelectClaimIsNsfw(props.uri)(state), mature: makeSelectClaimIsNsfw(props.uri)(state),
recommendedContent: makeSelectRecommendedContentForUri(props.uri)(state), recommendedContent: makeSelectRecommendedContentForUri(props.uri)(state),
nextRecommendedUri: makeSelectNextUnplayedRecommended(props.uri)(state), nextRecommendedUri: makeSelectNextUnplayedRecommended(props.uri)(state),
@ -16,7 +15,7 @@ const select = (state, props) => ({
}); });
const perform = (dispatch) => ({ const perform = (dispatch) => ({
search: (query, options) => dispatch(doSearch(query, options)), doFetchRecommendedContent: (uri, mature) => dispatch(doFetchRecommendedContent(uri, mature)),
}); });
export default connect(select, perform)(RecommendedVideos); export default connect(select, perform)(RecommendedVideos);

View file

@ -6,44 +6,29 @@ import Ads from 'web/component/ads';
import Card from 'component/common/card'; import Card from 'component/common/card';
import { useIsMobile, useIsMediumScreen } from 'effects/use-screensize'; import { useIsMobile, useIsMediumScreen } from 'effects/use-screensize';
type Options = {
related_to: string,
nsfw?: boolean,
};
type Props = { type Props = {
uri: string, uri: string,
claim: ?StreamClaim,
recommendedContent: Array<string>, recommendedContent: Array<string>,
nextRecommendedUri: string, nextRecommendedUri: string,
isSearching: boolean, isSearching: boolean,
search: (string, Options) => void, doFetchRecommendedContent: (string, boolean) => void,
mature: boolean, mature: boolean,
isAuthenticated: boolean, isAuthenticated: boolean,
}; };
export default function RecommendedContent(props: Props) { export default function RecommendedContent(props: Props) {
const { uri, claim, search, mature, recommendedContent, nextRecommendedUri, isSearching, isAuthenticated } = props; const {
uri,
doFetchRecommendedContent,
mature,
recommendedContent,
nextRecommendedUri,
isSearching,
isAuthenticated,
} = props;
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const isMedium = useIsMediumScreen(); const isMedium = useIsMediumScreen();
const stringifiedClaim = JSON.stringify(claim);
const getRecommendedContent = React.useCallback(() => {
if (stringifiedClaim) {
const jsonClaim = JSON.parse(stringifiedClaim);
if (jsonClaim && jsonClaim.value && jsonClaim.claim_id) {
const options: Options = { size: 20, related_to: jsonClaim.claim_id, isBackgroundSearch: true };
if (jsonClaim && !mature) {
options['nsfw'] = false;
}
const { title } = jsonClaim.value;
if (title && options) {
search(title, options);
}
}
}
}, [stringifiedClaim, mature, search]);
function reorderList(recommendedContent) { function reorderList(recommendedContent) {
let newList = recommendedContent; let newList = recommendedContent;
if (newList) { if (newList) {
@ -61,8 +46,8 @@ export default function RecommendedContent(props: Props) {
} }
React.useEffect(() => { React.useEffect(() => {
getRecommendedContent(); doFetchRecommendedContent(uri, mature);
}, [uri, getRecommendedContent]); }, [uri, mature, doFetchRecommendedContent]);
return ( return (
<Card <Card

View file

@ -1,6 +1,6 @@
// @flow // @flow
import * as ACTIONS from 'constants/action_types'; import * as ACTIONS from 'constants/action_types';
import { buildURI, doResolveUris, batchActions, isURIValid } from 'lbry-redux'; import { buildURI, doResolveUris, batchActions, isURIValid, makeSelectClaimForUri } from 'lbry-redux';
import { makeSelectSearchUris, makeSelectQueryWithOptions, selectSearchValue } from 'redux/selectors/search'; import { makeSelectSearchUris, makeSelectQueryWithOptions, selectSearchValue } from 'redux/selectors/search';
import handleFetchResponse from 'util/handle-fetch'; import handleFetchResponse from 'util/handle-fetch';
@ -57,7 +57,7 @@ export const doSearch = (rawQuery: string, searchOptions: SearchOptions) => (
const uris = []; const uris = [];
const actions = []; const actions = [];
data.forEach(result => { data.forEach((result) => {
if (result) { if (result) {
const { name, claimId } = result; const { name, claimId } = result;
const urlObj: LbryUrlObj = {}; const urlObj: LbryUrlObj = {};
@ -88,7 +88,7 @@ export const doSearch = (rawQuery: string, searchOptions: SearchOptions) => (
}); });
dispatch(batchActions(...actions)); dispatch(batchActions(...actions));
}) })
.catch(e => { .catch((e) => {
dispatch({ dispatch({
type: ACTIONS.SEARCH_FAIL, type: ACTIONS.SEARCH_FAIL,
}); });
@ -113,4 +113,20 @@ export const doUpdateSearchOptions = (newOptions: SearchOptions, additionalOptio
} }
}; };
export const doFetchRecommendedContent = (uri: string, mature: boolean) => (dispatch: Dispatch, getState: GetState) => {
const state = getState();
const claim = makeSelectClaimForUri(uri)(state);
if (claim && claim.value && claim.claim_id) {
const options: SearchOptions = { size: 20, related_to: claim.claim_id, isBackgroundSearch: true };
if (!mature) {
options['nsfw'] = false;
}
const { title } = claim.value;
if (title && options) {
dispatch(doSearch(title, options));
}
}
};
export { lighthouse }; export { lighthouse };