From 3b1393de138950133a2e9dbe1b931c070b6e2e4b Mon Sep 17 00:00:00 2001 From: Mirlan Date: Wed, 13 Oct 2021 18:04:29 +0600 Subject: [PATCH] fix(1783): controls visibility in fullscreen (#537) --- .../components/ProgressBar/stories.tsx | 2 +- .../MultiSourcePlayer/hooks/index.tsx | 12 +++++- src/features/MultiSourcePlayer/index.tsx | 13 +++++- .../components/ProgressBar/stories.tsx | 2 +- src/features/StreamPlayer/hooks/index.tsx | 12 +++++- .../hooks/useControlsVisibility.tsx | 40 +++++++++++++++++++ src/features/StreamPlayer/index.tsx | 13 +++++- src/features/StreamPlayer/styled.tsx | 39 +++++++++--------- 8 files changed, 108 insertions(+), 25 deletions(-) create mode 100644 src/features/StreamPlayer/hooks/useControlsVisibility.tsx diff --git a/src/features/MultiSourcePlayer/components/ProgressBar/stories.tsx b/src/features/MultiSourcePlayer/components/ProgressBar/stories.tsx index 373d3608..807640f6 100644 --- a/src/features/MultiSourcePlayer/components/ProgressBar/stories.tsx +++ b/src/features/MultiSourcePlayer/components/ProgressBar/stories.tsx @@ -31,7 +31,7 @@ const callback = () => {} const renderInControls = (progressBarElement: ReactElement) => ( - + ( getActiveChapter(index)?.urls[quality] ), [selectedQuality, getActiveChapter]) @@ -204,12 +211,14 @@ export const useMultiSourcePlayer = ({ chapters, duration, isFirstChapterPlaying, + isFullscreen, isLastChapterPlaying, loadedProgress, nextSrc: getChapterUrl((activeChapterIndex + 1) % numberOfChapters), numberOfChapters, onEnded, onError: handleError, + onFullscreenClick, onLoadedProgress, onPause, onPlayedProgress, @@ -230,7 +239,8 @@ export const useMultiSourcePlayer = ({ video1Ref, video2Ref, videoQualities, - ...useFullscreen(), + wrapperRef, + ...useControlsVisibility(isFullscreen), ...useVolume(), } } diff --git a/src/features/MultiSourcePlayer/index.tsx b/src/features/MultiSourcePlayer/index.tsx index 18011175..ed6b7746 100644 --- a/src/features/MultiSourcePlayer/index.tsx +++ b/src/features/MultiSourcePlayer/index.tsx @@ -40,6 +40,7 @@ export const MultiSourcePlayer = (props: Props) => { activeSrc, allPlayedProgress, chapters, + controlsVisible, duration, isFirstChapterPlaying, isFullscreen, @@ -52,12 +53,17 @@ export const MultiSourcePlayer = (props: Props) => { onError, onFullscreenClick, onLoadedProgress, + onMouseEnter, + onMouseLeave, + onMouseMove, onPause, onPlayedProgress, onPlayerClick, onProgressChange, onQualitySelect, onReady, + onTouchEnd, + onTouchStart, onVolumeChange, onVolumeClick, playedProgress, @@ -85,6 +91,11 @@ export const MultiSourcePlayer = (props: Props) => { ref={wrapperRef} playing={playing} onClick={onPlayerClick} + onMouseMove={onMouseMove} + onMouseEnter={onMouseEnter} + onMouseLeave={onMouseLeave} + onTouchStart={onTouchStart} + onTouchEnd={onTouchEnd} > { !ready && ( @@ -137,7 +148,7 @@ export const MultiSourcePlayer = (props: Props) => { {REWIND_SECONDS} )} - + {} const renderInControls = (progressBarElement: ReactElement) => ( - + seconds * 1000 @@ -55,6 +56,12 @@ export const useVideoPlayer = ({ onPlayingChange(true) }), [onPlayingChange, setPlayerState]) + const { + isFullscreen, + onFullscreenClick, + wrapperRef, + } = useFullscreen() + const togglePlaying = () => { if (ready) { setPlayerState({ playing: !playing }) @@ -104,9 +111,11 @@ export const useVideoPlayer = ({ return { backToLive, duration, + isFullscreen, loadedProgress, onDuration, onError, + onFullscreenClick, onLoadedProgress, onPlayedProgress, onPlayerClick, @@ -120,7 +129,8 @@ export const useVideoPlayer = ({ startPlaying, togglePlaying, videoRef, - ...useFullscreen(), + wrapperRef, + ...useControlsVisibility(isFullscreen), ...useVolume(), ...useVideoQuality(hls), } diff --git a/src/features/StreamPlayer/hooks/useControlsVisibility.tsx b/src/features/StreamPlayer/hooks/useControlsVisibility.tsx new file mode 100644 index 00000000..efead7dd --- /dev/null +++ b/src/features/StreamPlayer/hooks/useControlsVisibility.tsx @@ -0,0 +1,40 @@ +import { + useMemo, + useState, + useCallback, +} from 'react' + +import debounce from 'lodash/debounce' + +export const useControlsVisibility = (isFullscreen: boolean) => { + const [controlsVisible, setControlsVisibility] = useState(true) + + const show = useCallback(() => { + setControlsVisibility(true) + }, []) + + const hide = useCallback(() => { + setControlsVisibility(false) + }, []) + + const hideDebounced = useMemo( + () => debounce(hide, 3000), + [hide], + ) + + const onMouseMove = () => { + show() + if (isFullscreen) { + hideDebounced() + } + } + + return { + controlsVisible, + onMouseEnter: show, + onMouseLeave: hide, + onMouseMove, + onTouchEnd: hideDebounced, + onTouchStart: show, + } +} diff --git a/src/features/StreamPlayer/index.tsx b/src/features/StreamPlayer/index.tsx index 4da75837..21881831 100644 --- a/src/features/StreamPlayer/index.tsx +++ b/src/features/StreamPlayer/index.tsx @@ -30,6 +30,7 @@ export const StreamPlayer = (props: Props) => { const { url } = props const { backToLive, + controlsVisible, duration, isFullscreen, loadedProgress, @@ -38,10 +39,15 @@ export const StreamPlayer = (props: Props) => { onError, onFullscreenClick, onLoadedProgress, + onMouseEnter, + onMouseLeave, + onMouseMove, onPlayedProgress, onPlayerClick, onProgressChange, onQualitySelect, + onTouchEnd, + onTouchStart, onVolumeChange, onVolumeClick, playedProgress, @@ -65,6 +71,11 @@ export const StreamPlayer = (props: Props) => { ref={wrapperRef} playing={playing} onClick={onPlayerClick} + onMouseMove={onMouseMove} + onMouseEnter={onMouseEnter} + onMouseLeave={onMouseLeave} + onTouchStart={onTouchStart} + onTouchEnd={onTouchEnd} > { !ready && ( @@ -103,7 +114,7 @@ export const StreamPlayer = (props: Props) => { {REWIND_SECONDS} )} - + ` + transition: opacity 0.3s ease-in-out; + ${({ visible }) => (visible + ? css`opacity: 1;` + : css`opacity: 0;` + )} +` + export const Controls = styled.div` z-index: 50; position: absolute; @@ -27,17 +39,18 @@ export const Controls = styled.div` display: flex; flex-direction: column; align-items: center; - transition: opacity 0.3s ease-in-out; filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25)); + ${hoverStyles} + ${isMobileDevice ? css` - bottom: 5px; - @media (orientation: landscape){ - width: 100%; - left: 50%; - transform: translateX(-50%); - } + bottom: 5px; + @media (orientation: landscape){ + width: 100%; + left: 50%; + transform: translateX(-50%); + } ` : ''}; ` @@ -96,18 +109,6 @@ export const PlayerWrapper = styled.div` :fullscreen { padding-top: 0; } - - :hover ${Controls} { - opacity: 1; - } - - ${Controls} { - opacity: ${({ playing }) => ( - playing - ? '0' - : '1' - )}; - } ` export const LoaderWrapper = styled.div`