Fix List playback on Floating Player
This commit is contained in:
parent
7d4cc58def
commit
9869980e6b
8 changed files with 64 additions and 38 deletions
|
@ -4,6 +4,7 @@ import { withRouter } from 'react-router';
|
||||||
import {
|
import {
|
||||||
makeSelectIsPlayerFloating,
|
makeSelectIsPlayerFloating,
|
||||||
makeSelectNextUnplayedRecommended,
|
makeSelectNextUnplayedRecommended,
|
||||||
|
selectPlayingUri,
|
||||||
} from 'redux/selectors/content';
|
} from 'redux/selectors/content';
|
||||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
import { doSetPlayingUri, doPlayUri } from 'redux/actions/content';
|
import { doSetPlayingUri, doPlayUri } from 'redux/actions/content';
|
||||||
|
@ -18,7 +19,8 @@ const select = (state, props) => {
|
||||||
const { location } = props;
|
const { location } = props;
|
||||||
const { search } = location;
|
const { search } = location;
|
||||||
const urlParams = new URLSearchParams(search);
|
const urlParams = new URLSearchParams(search);
|
||||||
const collectionId = urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID);
|
const playingUri = selectPlayingUri(state);
|
||||||
|
const collectionId = urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID) || (playingUri && playingUri.collectionId);
|
||||||
|
|
||||||
let nextRecommendedUri;
|
let nextRecommendedUri;
|
||||||
if (collectionId) {
|
if (collectionId) {
|
||||||
|
|
|
@ -17,7 +17,7 @@ type Props = {
|
||||||
nextRecommendedClaim: ?StreamClaim,
|
nextRecommendedClaim: ?StreamClaim,
|
||||||
nextRecommendedUri: string,
|
nextRecommendedUri: string,
|
||||||
isFloating: boolean,
|
isFloating: boolean,
|
||||||
doSetPlayingUri: ({ uri: ?string }) => void,
|
doSetPlayingUri: ({ uri: ?string, collectionId: ?string }) => void,
|
||||||
doPlayUri: (string) => void,
|
doPlayUri: (string) => void,
|
||||||
modal: { id: string, modalProps: {} },
|
modal: { id: string, modalProps: {} },
|
||||||
collectionId?: string,
|
collectionId?: string,
|
||||||
|
@ -58,19 +58,14 @@ function AutoplayCountdown(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const doNavigate = useCallback(() => {
|
const doNavigate = useCallback(() => {
|
||||||
if (!isFloating) {
|
if (!isFloating && navigateUrl) {
|
||||||
if (navigateUrl) {
|
push(navigateUrl);
|
||||||
push(navigateUrl);
|
|
||||||
doSetPlayingUri({ uri: nextRecommendedUri });
|
|
||||||
doPlayUri(nextRecommendedUri);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (nextRecommendedUri) {
|
|
||||||
doSetPlayingUri({ uri: nextRecommendedUri });
|
|
||||||
doPlayUri(nextRecommendedUri);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [navigateUrl, nextRecommendedUri, isFloating, doSetPlayingUri, doPlayUri, push]);
|
if (nextRecommendedUri) {
|
||||||
|
doSetPlayingUri({ uri: nextRecommendedUri, collectionId });
|
||||||
|
doPlayUri(nextRecommendedUri);
|
||||||
|
}
|
||||||
|
}, [isFloating, navigateUrl, nextRecommendedUri, push, doSetPlayingUri, collectionId, doPlayUri]);
|
||||||
|
|
||||||
function shouldPauseAutoplay() {
|
function shouldPauseAutoplay() {
|
||||||
const elm = document.querySelector(`.${CLASSNAME_AUTOPLAY_COUNTDOWN}`);
|
const elm = document.querySelector(`.${CLASSNAME_AUTOPLAY_COUNTDOWN}`);
|
||||||
|
|
|
@ -22,6 +22,7 @@ const select = (state, props) => {
|
||||||
const playingUri = selectPlayingUri(state);
|
const playingUri = selectPlayingUri(state);
|
||||||
const primaryUri = selectPrimaryUri(state);
|
const primaryUri = selectPrimaryUri(state);
|
||||||
const uri = playingUri && playingUri.uri;
|
const uri = playingUri && playingUri.uri;
|
||||||
|
const collectionId = playingUri && playingUri.collectionId;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
uri,
|
uri,
|
||||||
|
@ -35,6 +36,7 @@ const select = (state, props) => {
|
||||||
floatingPlayerEnabled: makeSelectClientSetting(SETTINGS.FLOATING_PLAYER)(state),
|
floatingPlayerEnabled: makeSelectClientSetting(SETTINGS.FLOATING_PLAYER)(state),
|
||||||
renderMode: makeSelectFileRenderModeForUri(uri)(state),
|
renderMode: makeSelectFileRenderModeForUri(uri)(state),
|
||||||
videoTheaterMode: makeSelectClientSetting(SETTINGS.VIDEO_THEATER_MODE)(state),
|
videoTheaterMode: makeSelectClientSetting(SETTINGS.VIDEO_THEATER_MODE)(state),
|
||||||
|
collectionId,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { onFullscreenChange } from 'util/full-screen';
|
||||||
import { useIsMobile } from 'effects/use-screensize';
|
import { useIsMobile } from 'effects/use-screensize';
|
||||||
import debounce from 'util/debounce';
|
import debounce from 'util/debounce';
|
||||||
import { useHistory } from 'react-router';
|
import { useHistory } from 'react-router';
|
||||||
import { isURIEqual } from 'lbry-redux';
|
import { isURIEqual, COLLECTIONS_CONSTS } from 'lbry-redux';
|
||||||
|
|
||||||
const IS_DESKTOP_MAC = typeof process === 'object' ? process.platform === 'darwin' : false;
|
const IS_DESKTOP_MAC = typeof process === 'object' ? process.platform === 'darwin' : false;
|
||||||
const DEBOUNCE_WINDOW_RESIZE_HANDLER_MS = 60;
|
const DEBOUNCE_WINDOW_RESIZE_HANDLER_MS = 60;
|
||||||
|
@ -34,6 +34,7 @@ type Props = {
|
||||||
primaryUri: ?string,
|
primaryUri: ?string,
|
||||||
videoTheaterMode: boolean,
|
videoTheaterMode: boolean,
|
||||||
doFetchRecommendedContent: (string, boolean) => void,
|
doFetchRecommendedContent: (string, boolean) => void,
|
||||||
|
collectionId: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function FileRenderFloating(props: Props) {
|
export default function FileRenderFloating(props: Props) {
|
||||||
|
@ -51,6 +52,7 @@ export default function FileRenderFloating(props: Props) {
|
||||||
primaryUri,
|
primaryUri,
|
||||||
videoTheaterMode,
|
videoTheaterMode,
|
||||||
doFetchRecommendedContent,
|
doFetchRecommendedContent,
|
||||||
|
collectionId,
|
||||||
} = props;
|
} = props;
|
||||||
const {
|
const {
|
||||||
location: { pathname },
|
location: { pathname },
|
||||||
|
@ -69,6 +71,13 @@ export default function FileRenderFloating(props: Props) {
|
||||||
y: 0,
|
y: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let navigateUrl;
|
||||||
|
if (collectionId) {
|
||||||
|
const collectionParams = new URLSearchParams();
|
||||||
|
collectionParams.set(COLLECTIONS_CONSTS.COLLECTION_ID, collectionId);
|
||||||
|
navigateUrl = uri + `?` + collectionParams.toString();
|
||||||
|
}
|
||||||
|
|
||||||
const playingUriSource = playingUri && playingUri.source;
|
const playingUriSource = playingUri && playingUri.source;
|
||||||
const isPlayable = RENDER_MODES.FLOATING_MODES.includes(renderMode);
|
const isPlayable = RENDER_MODES.FLOATING_MODES.includes(renderMode);
|
||||||
const isReadyToPlay = isPlayable && (streamingUrl || (fileInfo && fileInfo.completed));
|
const isReadyToPlay = isPlayable && (streamingUrl || (fileInfo && fileInfo.completed));
|
||||||
|
@ -303,7 +312,12 @@ export default function FileRenderFloating(props: Props) {
|
||||||
{isFloating && (
|
{isFloating && (
|
||||||
<div className="draggable content__info">
|
<div className="draggable content__info">
|
||||||
<div className="claim-preview__title" title={title || uri}>
|
<div className="claim-preview__title" title={title || uri}>
|
||||||
<Button label={title || uri} navigate={uri} button="link" className="content__floating-link" />
|
<Button
|
||||||
|
label={title || uri}
|
||||||
|
navigate={navigateUrl || uri}
|
||||||
|
button="link"
|
||||||
|
className="content__floating-link"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<UriIndicator link uri={uri} />
|
<UriIndicator link uri={uri} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
makeSelectStreamingUrlForUri,
|
makeSelectStreamingUrlForUri,
|
||||||
makeSelectClaimWasPurchased,
|
makeSelectClaimWasPurchased,
|
||||||
SETTINGS,
|
SETTINGS,
|
||||||
|
COLLECTIONS_CONSTS,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { makeSelectCostInfoForUri } from 'lbryinc';
|
import { makeSelectCostInfoForUri } from 'lbryinc';
|
||||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||||
|
@ -22,27 +23,34 @@ import {
|
||||||
import FileRenderInitiator from './view';
|
import FileRenderInitiator from './view';
|
||||||
import { doAnaltyicsPurchaseEvent } from 'redux/actions/app';
|
import { doAnaltyicsPurchaseEvent } from 'redux/actions/app';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => {
|
||||||
claimThumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
const { search } = props.location;
|
||||||
fileInfo: makeSelectFileInfoForUri(props.uri)(state),
|
const urlParams = new URLSearchParams(search);
|
||||||
obscurePreview: makeSelectShouldObscurePreview(props.uri)(state),
|
const collectionId = urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID);
|
||||||
isPlaying: makeSelectIsPlaying(props.uri)(state),
|
|
||||||
playingUri: selectPlayingUri(state),
|
return {
|
||||||
insufficientCredits: makeSelectInsufficientCreditsForUri(props.uri)(state),
|
claimThumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||||
streamingUrl: makeSelectStreamingUrlForUri(props.uri)(state),
|
fileInfo: makeSelectFileInfoForUri(props.uri)(state),
|
||||||
autoplay: makeSelectClientSetting(SETTINGS.AUTOPLAY)(state),
|
obscurePreview: makeSelectShouldObscurePreview(props.uri)(state),
|
||||||
hasCostInfo: Boolean(makeSelectCostInfoForUri(props.uri)(state)),
|
isPlaying: makeSelectIsPlaying(props.uri)(state),
|
||||||
costInfo: makeSelectCostInfoForUri(props.uri)(state),
|
playingUri: selectPlayingUri(state),
|
||||||
renderMode: makeSelectFileRenderModeForUri(props.uri)(state),
|
insufficientCredits: makeSelectInsufficientCreditsForUri(props.uri)(state),
|
||||||
claim: makeSelectClaimForUri(props.uri)(state),
|
streamingUrl: makeSelectStreamingUrlForUri(props.uri)(state),
|
||||||
claimWasPurchased: makeSelectClaimWasPurchased(props.uri)(state),
|
autoplay: makeSelectClientSetting(SETTINGS.AUTOPLAY)(state),
|
||||||
authenticated: selectUserVerifiedEmail(state),
|
hasCostInfo: Boolean(makeSelectCostInfoForUri(props.uri)(state)),
|
||||||
});
|
costInfo: makeSelectCostInfoForUri(props.uri)(state),
|
||||||
|
renderMode: makeSelectFileRenderModeForUri(props.uri)(state),
|
||||||
|
claim: makeSelectClaimForUri(props.uri)(state),
|
||||||
|
claimWasPurchased: makeSelectClaimWasPurchased(props.uri)(state),
|
||||||
|
authenticated: selectUserVerifiedEmail(state),
|
||||||
|
collectionId,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const perform = (dispatch) => ({
|
const perform = (dispatch) => ({
|
||||||
play: (uri) => {
|
play: (uri, collectionId) => {
|
||||||
dispatch(doSetPrimaryUri(uri));
|
dispatch(doSetPrimaryUri(uri));
|
||||||
dispatch(doSetPlayingUri({ uri }));
|
dispatch(doSetPlayingUri({ uri, collectionId }));
|
||||||
dispatch(doPlayUri(uri, undefined, undefined, (fileInfo) => dispatch(doAnaltyicsPurchaseEvent(fileInfo))));
|
dispatch(doPlayUri(uri, undefined, undefined, (fileInfo) => dispatch(doAnaltyicsPurchaseEvent(fileInfo))));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,7 +17,7 @@ import FileRenderPlaceholder from 'static/img/fileRenderPlaceholder.png';
|
||||||
const SPACE_BAR_KEYCODE = 32;
|
const SPACE_BAR_KEYCODE = 32;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
play: (string) => void,
|
play: (string, string) => void,
|
||||||
isLoading: boolean,
|
isLoading: boolean,
|
||||||
isPlaying: boolean,
|
isPlaying: boolean,
|
||||||
fileInfo: FileListItem,
|
fileInfo: FileListItem,
|
||||||
|
@ -36,6 +36,7 @@ type Props = {
|
||||||
claimWasPurchased: boolean,
|
claimWasPurchased: boolean,
|
||||||
authenticated: boolean,
|
authenticated: boolean,
|
||||||
videoTheaterMode: boolean,
|
videoTheaterMode: boolean,
|
||||||
|
collectionId: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function FileRenderInitiator(props: Props) {
|
export default function FileRenderInitiator(props: Props) {
|
||||||
|
@ -55,6 +56,7 @@ export default function FileRenderInitiator(props: Props) {
|
||||||
claimWasPurchased,
|
claimWasPurchased,
|
||||||
authenticated,
|
authenticated,
|
||||||
videoTheaterMode,
|
videoTheaterMode,
|
||||||
|
collectionId,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
// force autoplay if a timestamp is present
|
// force autoplay if a timestamp is present
|
||||||
|
@ -109,9 +111,9 @@ export default function FileRenderInitiator(props: Props) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
play(uri);
|
play(uri, collectionId);
|
||||||
},
|
},
|
||||||
[play, uri]
|
[play, uri, collectionId]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -112,16 +112,18 @@ export function doSetPlayingUri({
|
||||||
source,
|
source,
|
||||||
pathname,
|
pathname,
|
||||||
commentId,
|
commentId,
|
||||||
|
collectionId,
|
||||||
}: {
|
}: {
|
||||||
uri: ?string,
|
uri: ?string,
|
||||||
source?: string,
|
source?: string,
|
||||||
commentId?: string,
|
commentId?: string,
|
||||||
pathname: string,
|
pathname: string,
|
||||||
|
collectionId: string,
|
||||||
}) {
|
}) {
|
||||||
return (dispatch: Dispatch) => {
|
return (dispatch: Dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.SET_PLAYING_URI,
|
type: ACTIONS.SET_PLAYING_URI,
|
||||||
data: { uri, source, pathname, commentId },
|
data: { uri, source, pathname, commentId, collectionId },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ reducers[ACTIONS.SET_PLAYING_URI] = (state, action) =>
|
||||||
source: action.data.source,
|
source: action.data.source,
|
||||||
pathname: action.data.pathname,
|
pathname: action.data.pathname,
|
||||||
commentId: action.data.commentId,
|
commentId: action.data.commentId,
|
||||||
|
collectionId: action.data.collectionId,
|
||||||
primaryUri: state.primaryUri,
|
primaryUri: state.primaryUri,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue