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:
parent
8ab0bcd545
commit
d279d70770
5 changed files with 55 additions and 36 deletions
|
@ -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));
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
Loading…
Reference in a new issue