Mobile file page, comments and player improvements for rotated landscape view
undo plugin changes
This commit is contained in:
parent
35c933e7e4
commit
800e735115
7 changed files with 78 additions and 17 deletions
|
@ -85,3 +85,20 @@ export function getPossiblePlayerHeight(height: number, isMobile: boolean) {
|
||||||
|
|
||||||
return forceMinHeight;
|
return forceMinHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getWindowAngle(cb?: () => void) {
|
||||||
|
// iOS
|
||||||
|
if (typeof window.orientation === 'number') {
|
||||||
|
return window.orientation;
|
||||||
|
}
|
||||||
|
// Android
|
||||||
|
if (screen && screen.orientation && screen.orientation.angle) {
|
||||||
|
return window.orientation;
|
||||||
|
}
|
||||||
|
if (cb) cb();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isWindowLandscapeForAngle(angle: number) {
|
||||||
|
return angle === 90 || angle === 270 || angle === -90;
|
||||||
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { PRIMARY_PLAYER_WRAPPER_CLASS } from 'page/file/view';
|
||||||
import Draggable from 'react-draggable';
|
import Draggable from 'react-draggable';
|
||||||
import { onFullscreenChange } from 'util/full-screen';
|
import { onFullscreenChange } from 'util/full-screen';
|
||||||
import { generateListSearchUrlParams, formatLbryChannelName } from 'util/url';
|
import { generateListSearchUrlParams, formatLbryChannelName } from 'util/url';
|
||||||
import { useIsMobile } from 'effects/use-screensize';
|
import { useIsMobile, useIsMobileLandscape } 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 'util/lbryURI';
|
import { isURIEqual } from 'util/lbryURI';
|
||||||
|
@ -111,6 +111,7 @@ export default function FileRenderFloating(props: Props) {
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
const isLandscapeRotated = useIsMobileLandscape();
|
||||||
|
|
||||||
const initialMobileState = React.useRef(isMobile);
|
const initialMobileState = React.useRef(isMobile);
|
||||||
const initialPlayerHeight = React.useRef();
|
const initialPlayerHeight = React.useRef();
|
||||||
|
@ -368,7 +369,7 @@ export default function FileRenderFloating(props: Props) {
|
||||||
'content__viewer--secondary': isComment,
|
'content__viewer--secondary': isComment,
|
||||||
'content__viewer--theater-mode': videoTheaterMode && mainFilePlaying && !isCurrentClaimLive && !isMobile,
|
'content__viewer--theater-mode': videoTheaterMode && mainFilePlaying && !isCurrentClaimLive && !isMobile,
|
||||||
'content__viewer--disable-click': wasDragging,
|
'content__viewer--disable-click': wasDragging,
|
||||||
'content__viewer--mobile': isMobile && !playingUriSource,
|
'content__viewer--mobile': isMobile && !isLandscapeRotated && !playingUriSource,
|
||||||
})}
|
})}
|
||||||
style={
|
style={
|
||||||
!isFloating && fileViewerRect
|
!isFloating && fileViewerRect
|
||||||
|
@ -388,11 +389,12 @@ export default function FileRenderFloating(props: Props) {
|
||||||
<PlayerGlobalStyles
|
<PlayerGlobalStyles
|
||||||
videoAspectRatio={videoAspectRatio}
|
videoAspectRatio={videoAspectRatio}
|
||||||
videoTheaterMode={videoTheaterMode}
|
videoTheaterMode={videoTheaterMode}
|
||||||
appDrawerOpen={appDrawerOpen}
|
appDrawerOpen={appDrawerOpen && !isLandscapeRotated}
|
||||||
initialPlayerHeight={initialPlayerHeight}
|
initialPlayerHeight={initialPlayerHeight}
|
||||||
isFloating={isFloating}
|
isFloating={isFloating}
|
||||||
fileViewerRect={fileViewerRect}
|
fileViewerRect={fileViewerRect}
|
||||||
mainFilePlaying={mainFilePlaying}
|
mainFilePlaying={mainFilePlaying}
|
||||||
|
isLandscapeRotated={isLandscapeRotated}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
@ -450,6 +452,7 @@ type GlobalStylesProps = {
|
||||||
isFloating: boolean,
|
isFloating: boolean,
|
||||||
fileViewerRect: any,
|
fileViewerRect: any,
|
||||||
mainFilePlaying: boolean,
|
mainFilePlaying: boolean,
|
||||||
|
isLandscapeRotated: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
const PlayerGlobalStyles = (props: GlobalStylesProps) => {
|
const PlayerGlobalStyles = (props: GlobalStylesProps) => {
|
||||||
|
@ -461,6 +464,7 @@ const PlayerGlobalStyles = (props: GlobalStylesProps) => {
|
||||||
isFloating,
|
isFloating,
|
||||||
fileViewerRect,
|
fileViewerRect,
|
||||||
mainFilePlaying,
|
mainFilePlaying,
|
||||||
|
isLandscapeRotated,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
@ -481,7 +485,7 @@ const PlayerGlobalStyles = (props: GlobalStylesProps) => {
|
||||||
// Handles video shrink + center on mobile view
|
// Handles video shrink + center on mobile view
|
||||||
// direct DOM manipulation due to performance for every scroll
|
// direct DOM manipulation due to performance for every scroll
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!isMobilePlayer || !mainFilePlaying || appDrawerOpen) return;
|
if (!isMobilePlayer || !mainFilePlaying || appDrawerOpen || isLandscapeRotated) return;
|
||||||
|
|
||||||
const viewer = document.querySelector(`.${CONTENT_VIEWER_CLASS}`);
|
const viewer = document.querySelector(`.${CONTENT_VIEWER_CLASS}`);
|
||||||
if (viewer) viewer.style.height = `${heightForViewer}px`;
|
if (viewer) viewer.style.height = `${heightForViewer}px`;
|
||||||
|
@ -527,7 +531,15 @@ const PlayerGlobalStyles = (props: GlobalStylesProps) => {
|
||||||
|
|
||||||
window.removeEventListener('scroll', handleScroll);
|
window.removeEventListener('scroll', handleScroll);
|
||||||
};
|
};
|
||||||
}, [appDrawerOpen, heightForViewer, isMobilePlayer, mainFilePlaying, maxLandscapeHeight, initialPlayerHeight]);
|
}, [
|
||||||
|
appDrawerOpen,
|
||||||
|
heightForViewer,
|
||||||
|
isMobilePlayer,
|
||||||
|
mainFilePlaying,
|
||||||
|
maxLandscapeHeight,
|
||||||
|
initialPlayerHeight,
|
||||||
|
isLandscapeRotated,
|
||||||
|
]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (appDrawerOpen && videoGreaterThanLandscape && isMobilePlayer) {
|
if (appDrawerOpen && videoGreaterThanLandscape && isMobilePlayer) {
|
||||||
|
@ -594,7 +606,10 @@ const PlayerGlobalStyles = (props: GlobalStylesProps) => {
|
||||||
},
|
},
|
||||||
|
|
||||||
[`.${CONTENT_VIEWER_CLASS}`]: {
|
[`.${CONTENT_VIEWER_CLASS}`]: {
|
||||||
height: !forceDefaults && (!isMobile || isMobilePlayer) ? `${heightResult} !important` : undefined,
|
height:
|
||||||
|
(!forceDefaults || isLandscapeRotated) && (!isMobile || isMobilePlayer)
|
||||||
|
? `${heightResult} !important`
|
||||||
|
: undefined,
|
||||||
...maxHeight,
|
...maxHeight,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import 'scss/component/_swipeable-drawer.scss';
|
import 'scss/component/_swipeable-drawer.scss';
|
||||||
|
|
||||||
import { lazyImport } from 'util/lazyImport';
|
import { lazyImport } from 'util/lazyImport';
|
||||||
import { useIsMobile } from 'effects/use-screensize';
|
import { useIsMobile, useIsMobileLandscape } from 'effects/use-screensize';
|
||||||
import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button';
|
import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button';
|
||||||
import FileTitleSection from 'component/fileTitleSection';
|
import FileTitleSection from 'component/fileTitleSection';
|
||||||
import LivestreamLink from 'component/livestreamLink';
|
import LivestreamLink from 'component/livestreamLink';
|
||||||
|
@ -53,6 +53,7 @@ export default function LivestreamLayout(props: Props) {
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
const isLandscapeRotated = useIsMobileLandscape();
|
||||||
|
|
||||||
const [superchatsHidden, setSuperchatsHidden] = React.useState(false);
|
const [superchatsHidden, setSuperchatsHidden] = React.useState(false);
|
||||||
const [chatViewMode, setChatViewMode] = React.useState(VIEW_MODES.CHAT);
|
const [chatViewMode, setChatViewMode] = React.useState(VIEW_MODES.CHAT);
|
||||||
|
@ -100,7 +101,7 @@ export default function LivestreamLayout(props: Props) {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isMobile && !hideComments && (
|
{isMobile && !isLandscapeRotated && !hideComments && (
|
||||||
<React.Suspense fallback={null}>
|
<React.Suspense fallback={null}>
|
||||||
<SwipeableDrawer
|
<SwipeableDrawer
|
||||||
title={
|
title={
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { lazyImport } from 'util/lazyImport';
|
||||||
import { MAIN_CLASS } from 'constants/classnames';
|
import { MAIN_CLASS } from 'constants/classnames';
|
||||||
import { parseURI } from 'util/lbryURI';
|
import { parseURI } from 'util/lbryURI';
|
||||||
import { useHistory } from 'react-router';
|
import { useHistory } from 'react-router';
|
||||||
import { useIsMobile, useIsMediumScreen } from 'effects/use-screensize';
|
import { useIsMobile, useIsMediumScreen, useIsMobileLandscape } from 'effects/use-screensize';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import Header from 'component/header';
|
import Header from 'component/header';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
@ -65,6 +65,7 @@ function Page(props: Props) {
|
||||||
|
|
||||||
const isMediumScreen = useIsMediumScreen();
|
const isMediumScreen = useIsMediumScreen();
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
const isLandscapeRotated = useIsMobileLandscape();
|
||||||
const [sidebarOpen, setSidebarOpen] = usePersistedState('sidebar', false);
|
const [sidebarOpen, setSidebarOpen] = usePersistedState('sidebar', false);
|
||||||
|
|
||||||
const url = pathname.slice(1).replace(/:/g, '#');
|
const url = pathname.slice(1).replace(/:/g, '#');
|
||||||
|
@ -143,7 +144,7 @@ function Page(props: Props) {
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
||||||
{!isMobile && (!livestream || !chatDisabled) && rightSide}
|
{(!isMobile || isLandscapeRotated) && (!livestream || !chatDisabled) && rightSide}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
{!noFooter && (
|
{!noFooter && (
|
||||||
|
|
|
@ -61,7 +61,7 @@ const onPlayerReady = (player, options) => {
|
||||||
!player.el_.ownerDocument.querySelector('.bc-iframe')
|
!player.el_.ownerDocument.querySelector('.bc-iframe')
|
||||||
) {
|
) {
|
||||||
player.tech_.el_.setAttribute('playsinline', 'playsinline');
|
player.tech_.el_.setAttribute('playsinline', 'playsinline');
|
||||||
player.tech_.supportsFullScreen = function() {
|
player.tech_.supportsFullScreen = function () {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ const onPlayerReady = (player, options) => {
|
||||||
screen.orientation.onchange = rotationHandler;
|
screen.orientation.onchange = rotationHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.on('ended', _ => {
|
player.on('ended', (_) => {
|
||||||
if (locked === true) {
|
if (locked === true) {
|
||||||
screen.orientation.unlock();
|
screen.orientation.unlock();
|
||||||
locked = false;
|
locked = false;
|
||||||
|
@ -150,7 +150,7 @@ const onPlayerReady = (player, options) => {
|
||||||
* Whether to disable when the video ends (e.g., if there is an endscreen)
|
* Whether to disable when the video ends (e.g., if there is an endscreen)
|
||||||
* Never shows if the endscreen plugin is present
|
* Never shows if the endscreen plugin is present
|
||||||
*/
|
*/
|
||||||
const mobileUi = function(options) {
|
const mobileUi = function (options) {
|
||||||
// if (videojs.browser.IS_ANDROID || videojs.browser.IS_IOS) {
|
// if (videojs.browser.IS_ANDROID || videojs.browser.IS_IOS) {
|
||||||
if (videojs.browser.IS_ANDROID) {
|
if (videojs.browser.IS_ANDROID) {
|
||||||
this.ready(() => {
|
this.ready(() => {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
// Widths are taken from "ui/scss/init/vars.scss"
|
// Widths are taken from "ui/scss/init/vars.scss"
|
||||||
import React, { useRef } from 'react';
|
import React, { useRef } from 'react';
|
||||||
|
import { getWindowAngle, isWindowLandscapeForAngle } from 'component/fileRenderFloating/helper-functions';
|
||||||
const DEFAULT_SCREEN_SIZE = 1080;
|
const DEFAULT_SCREEN_SIZE = 1080;
|
||||||
|
|
||||||
export function useWindowSize() {
|
export function useWindowSize() {
|
||||||
|
@ -51,6 +52,33 @@ export function useIsMobile() {
|
||||||
return useHasWindowWidthChangedEnough((windowSize) => windowSize < 901);
|
return useHasWindowWidthChangedEnough((windowSize) => windowSize < 901);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useIsMobileLandscape() {
|
||||||
|
const isWindowClient = typeof window === 'object';
|
||||||
|
const isMobile = useIsMobile();
|
||||||
|
|
||||||
|
const windowAngle = getWindowAngle();
|
||||||
|
const isLandscape = isMobile && isWindowLandscapeForAngle(windowAngle);
|
||||||
|
const [landscape, setLandscape] = React.useState<boolean>(isLandscape);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
function handleResize() {
|
||||||
|
const currAngle = getWindowAngle();
|
||||||
|
const isCurrLandscape = isMobile && isWindowLandscapeForAngle(currAngle);
|
||||||
|
if (landscape !== isCurrLandscape) {
|
||||||
|
setLandscape(isCurrLandscape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isWindowClient) {
|
||||||
|
window.addEventListener('resize', handleResize);
|
||||||
|
|
||||||
|
return () => window.removeEventListener('resize', handleResize);
|
||||||
|
}
|
||||||
|
}, [isWindowClient, landscape]);
|
||||||
|
|
||||||
|
return landscape;
|
||||||
|
}
|
||||||
|
|
||||||
export function useIsMediumScreen() {
|
export function useIsMediumScreen() {
|
||||||
return useHasWindowWidthChangedEnough((windowSize) => windowSize < 1151);
|
return useHasWindowWidthChangedEnough((windowSize) => windowSize < 1151);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import Button from 'component/button';
|
||||||
import Empty from 'component/common/empty';
|
import Empty from 'component/common/empty';
|
||||||
import SwipeableDrawer from 'component/swipeableDrawer';
|
import SwipeableDrawer from 'component/swipeableDrawer';
|
||||||
import DrawerExpandButton from 'component/swipeableDrawerExpand';
|
import DrawerExpandButton from 'component/swipeableDrawerExpand';
|
||||||
import { useIsMobile } from 'effects/use-screensize';
|
import { useIsMobile, useIsMobileLandscape } from 'effects/use-screensize';
|
||||||
|
|
||||||
const CommentsList = lazyImport(() => import('component/commentsList' /* webpackChunkName: "comments" */));
|
const CommentsList = lazyImport(() => import('component/commentsList' /* webpackChunkName: "comments" */));
|
||||||
const PostViewer = lazyImport(() => import('component/postViewer' /* webpackChunkName: "postViewer" */));
|
const PostViewer = lazyImport(() => import('component/postViewer' /* webpackChunkName: "postViewer" */));
|
||||||
|
@ -81,8 +81,7 @@ export default function FilePage(props: Props) {
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
const isLandscapeRotated = useIsMobileLandscape();
|
||||||
// Auto-open the drawer on Mobile view if there is a linked comment
|
|
||||||
|
|
||||||
const channelSettings = channelId ? settingsByChannelId[channelId] : undefined;
|
const channelSettings = channelId ? settingsByChannelId[channelId] : undefined;
|
||||||
const commentSettingDisabled = channelSettings && !channelSettings.comments_enabled;
|
const commentSettingDisabled = channelSettings && !channelSettings.comments_enabled;
|
||||||
|
@ -239,7 +238,7 @@ export default function FilePage(props: Props) {
|
||||||
<Empty {...emptyMsgProps} text={__('The creator of this content has disabled comments.')} />
|
<Empty {...emptyMsgProps} text={__('The creator of this content has disabled comments.')} />
|
||||||
) : commentSettingDisabled ? (
|
) : commentSettingDisabled ? (
|
||||||
<Empty {...emptyMsgProps} text={__('This channel has disabled comments on their page.')} />
|
<Empty {...emptyMsgProps} text={__('This channel has disabled comments on their page.')} />
|
||||||
) : isMobile ? (
|
) : isMobile && !isLandscapeRotated ? (
|
||||||
<>
|
<>
|
||||||
<SwipeableDrawer title={commentsListTitle}>
|
<SwipeableDrawer title={commentsListTitle}>
|
||||||
<CommentsList {...commentsListProps} />
|
<CommentsList {...commentsListProps} />
|
||||||
|
|
Loading…
Reference in a new issue