lbry-desktop/ui/component/fileRenderMobile/view.jsx
Rafael baf51f9c32 Create swipeableDrawer component
- CommentsList needs to return a title with comment amounts
- mobile player dimensions needed to fill in the cover
- hid livestream header for now until figuring out a better presentation
- ~colum-reverse~ was causing problems with MUI's drawer scrolling, so reversed the chat order and made it ~column~ by default
- Hid bottom expand navigation if component not yet opened
- some other style changes in the middle
2022-02-08 12:35:40 -05:00

191 lines
5.8 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';
export const HEADER_HEIGHT_MOBILE = 56;
// ****************************************************************************
// ****************************************************************************
type Props = {
claimId?: string,
uri: string,
streamingUrl?: string,
renderMode: string,
collectionId: string,
costInfo: any,
claimWasPurchased: boolean,
nextListUri: string,
previousListUri: string,
activeLivestreamForChannel?: any,
channelClaimId?: any,
playingUri?: PlayingUri,
mobilePlayerDimensions?: any,
doPlayUri: (string) => void,
doSetMobilePlayerDimensions: (height: number, width: number) => void,
};
export default function FileRenderMobile(props: Props) {
const {
claimId,
uri,
streamingUrl,
renderMode,
collectionId,
costInfo,
claimWasPurchased,
nextListUri,
previousListUri,
activeLivestreamForChannel,
channelClaimId,
playingUri,
mobilePlayerDimensions,
doPlayUri,
doSetMobilePlayerDimensions,
} = 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 isCurrentMediaPlaying = playingUri && playingUri.uri === uri;
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 });
if (doSetMobilePlayerDimensions && (!mobilePlayerDimensions || mobilePlayerDimensions.height !== rect.height)) {
doSetMobilePlayerDimensions(rect.height, rect.width);
}
}, [doSetMobilePlayerDimensions, mobilePlayerDimensions]);
// 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 (
!isCurrentMediaPlaying ||
!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">
{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>
) : (
<LoadingScreen status={__('Loading')} />
)}
</div>
</div>
);
}