8c3e376873
- Biggest change: Moved mobile player logic outside of fileRenderFloating into its own component fileRenderMobile, since there is no need for all that extra resizing and dragging code (for now, as mobile doesn't have a floating player) - Moved player to the header height - Removed rounded borders and margins
177 lines
5.4 KiB
JavaScript
177 lines
5.4 KiB
JavaScript
// @flow
|
|
import * as RENDER_MODES from 'constants/file_render_modes';
|
|
import React, { useEffect, useState } from 'react';
|
|
import { onFullscreenChange } from 'util/full-screen';
|
|
import { generateListSearchUrlParams, formatLbryUrlForWeb } from 'util/url';
|
|
import { useHistory } from 'react-router';
|
|
import LoadingScreen from 'component/common/loading-screen';
|
|
import FileRender from 'component/fileRender';
|
|
import AutoplayCountdown from 'component/autoplayCountdown';
|
|
import LivestreamIframeRender from 'component/livestreamLayout/iframe-render';
|
|
|
|
const PRIMARY_PLAYER_WRAPPER_CLASS = 'file-page__video-container';
|
|
export const INLINE_PLAYER_WRAPPER_CLASS = 'inline-player__wrapper';
|
|
|
|
// ****************************************************************************
|
|
// ****************************************************************************
|
|
|
|
type Props = {
|
|
claimId?: string,
|
|
uri: string,
|
|
streamingUrl?: string,
|
|
renderMode: string,
|
|
collectionId: string,
|
|
costInfo: any,
|
|
claimWasPurchased: boolean,
|
|
nextListUri: string,
|
|
previousListUri: string,
|
|
activeLivestreamForChannel?: any,
|
|
channelClaimId?: any,
|
|
doPlayUri: (string) => void,
|
|
};
|
|
|
|
export default function FileRenderMobile(props: Props) {
|
|
const {
|
|
claimId,
|
|
uri,
|
|
streamingUrl,
|
|
renderMode,
|
|
collectionId,
|
|
costInfo,
|
|
claimWasPurchased,
|
|
nextListUri,
|
|
previousListUri,
|
|
activeLivestreamForChannel,
|
|
channelClaimId,
|
|
doPlayUri,
|
|
} = props;
|
|
|
|
const { push } = useHistory();
|
|
|
|
const [fileViewerRect, setFileViewerRect] = useState();
|
|
const [doNavigate, setDoNavigate] = useState(false);
|
|
const [playNextUrl, setPlayNextUrl] = useState(true);
|
|
const [countdownCanceled, setCountdownCanceled] = useState(false);
|
|
|
|
const isCurrentClaimLive = activeLivestreamForChannel && activeLivestreamForChannel.claimId === claimId;
|
|
const isFree = costInfo && costInfo.cost === 0;
|
|
const canViewFile = isFree || claimWasPurchased;
|
|
const isPlayable = RENDER_MODES.FLOATING_MODES.includes(renderMode) || activeLivestreamForChannel;
|
|
const isReadyToPlay = isPlayable && streamingUrl;
|
|
|
|
const handleResize = React.useCallback(() => {
|
|
const element = document.querySelector(`.${PRIMARY_PLAYER_WRAPPER_CLASS}`);
|
|
|
|
if (!element) return;
|
|
|
|
const rect = element.getBoundingClientRect();
|
|
|
|
// getBoundingClientRect returns a DomRect, not an object
|
|
const objectRect = {
|
|
top: rect.top,
|
|
right: rect.right,
|
|
bottom: rect.bottom,
|
|
left: rect.left,
|
|
width: rect.width,
|
|
height: rect.height,
|
|
// $FlowFixMe
|
|
x: rect.x,
|
|
};
|
|
|
|
// $FlowFixMe
|
|
setFileViewerRect({ ...objectRect });
|
|
}, []);
|
|
|
|
// Initial resize, will place the player correctly above the cover when starts playing
|
|
// (remember the URI here is from playingUri). The cover then keeps on the page and kind of serves as a placeholder
|
|
// for the player size and gives the content layered behind the player a "max scroll height"
|
|
useEffect(() => {
|
|
if (uri) {
|
|
handleResize();
|
|
setCountdownCanceled(false);
|
|
}
|
|
}, [handleResize, uri]);
|
|
|
|
useEffect(() => {
|
|
handleResize();
|
|
|
|
window.addEventListener('resize', handleResize);
|
|
onFullscreenChange(window, 'add', handleResize);
|
|
|
|
return () => {
|
|
window.removeEventListener('resize', handleResize);
|
|
onFullscreenChange(window, 'remove', handleResize);
|
|
};
|
|
}, [handleResize]);
|
|
|
|
const doPlay = React.useCallback(
|
|
(playUri) => {
|
|
setDoNavigate(false);
|
|
const navigateUrl = formatLbryUrlForWeb(playUri);
|
|
push({
|
|
pathname: navigateUrl,
|
|
search: collectionId && generateListSearchUrlParams(collectionId),
|
|
state: { collectionId, forceAutoplay: true, hideFloatingPlayer: true },
|
|
});
|
|
},
|
|
[collectionId, push]
|
|
);
|
|
|
|
React.useEffect(() => {
|
|
if (!doNavigate) return;
|
|
|
|
if (playNextUrl && nextListUri) {
|
|
doPlay(nextListUri);
|
|
} else if (previousListUri) {
|
|
doPlay(previousListUri);
|
|
}
|
|
setPlayNextUrl(true);
|
|
}, [doNavigate, doPlay, nextListUri, playNextUrl, previousListUri]);
|
|
|
|
if (!isPlayable || !uri || countdownCanceled || (collectionId && !canViewFile && !nextListUri)) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<div
|
|
className="content__viewer content__viewer--inline content__viewer--mobile"
|
|
style={
|
|
fileViewerRect
|
|
? {
|
|
width: fileViewerRect.width,
|
|
height: fileViewerRect.height,
|
|
left: fileViewerRect.x,
|
|
}
|
|
: {}
|
|
}
|
|
>
|
|
<div className="content__wrapper">
|
|
<React.Suspense fallback={<Loading />}>
|
|
{isCurrentClaimLive && channelClaimId ? (
|
|
<LivestreamIframeRender channelClaimId={channelClaimId} showLivestream mobileVersion />
|
|
) : isReadyToPlay ? (
|
|
<FileRender uri={uri} />
|
|
) : !canViewFile ? (
|
|
<div className="content__loading">
|
|
<AutoplayCountdown
|
|
nextRecommendedUri={nextListUri}
|
|
doNavigate={() => setDoNavigate(true)}
|
|
doReplay={() => doPlayUri(uri)}
|
|
doPrevious={() => {
|
|
setPlayNextUrl(false);
|
|
setDoNavigate(true);
|
|
}}
|
|
onCanceled={() => setCountdownCanceled(true)}
|
|
skipPaid
|
|
/>
|
|
</div>
|
|
) : (
|
|
<Loading />
|
|
)}
|
|
</React.Suspense>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const Loading = () => <LoadingScreen status={__('Loading')} />;
|