From 7c38165ac8bde6ea1bf50579370e17a6977bd626 Mon Sep 17 00:00:00 2001 From: streamich Date: Thu, 28 Mar 2019 22:26:38 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20improve=20useFullscreen?= =?UTF-8?q?=20hook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/__stories__/useFullscreen.story.tsx | 26 +++++-- src/useFullscreen.ts | 97 +++++++++++++------------ 2 files changed, 70 insertions(+), 53 deletions(-) diff --git a/src/__stories__/useFullscreen.story.tsx b/src/__stories__/useFullscreen.story.tsx index 7f4d9ece9f..bc55e40115 100644 --- a/src/__stories__/useFullscreen.story.tsx +++ b/src/__stories__/useFullscreen.story.tsx @@ -1,20 +1,34 @@ import * as React from 'react'; import {storiesOf} from '@storybook/react'; -import {useFullscreen} from '..'; +import {useFullscreen, useToggle} from '..'; import ShowDocs from '../util/ShowDocs'; const Demo = () => { + const [show, toggle] = useToggle(false); const ref = React.useRef(null) const videoRef = React.useRef(null) - const [fullscreen, toggle] = useFullscreen(ref, videoRef); + const isFullScreen = useFullscreen(ref, show, {onClose: () => toggle(false)}); - return ( -
-
{fullscreen ? 'Fullscreen' : 'Not fullscreen'}
+ const controls = ( +
+
{isFullScreen ? 'is full screen' : 'not full screen'}
-
+ ); + + return ( +
+
+
+ +
+
+ + {!isFullScreen && controls}
); }; diff --git a/src/useFullscreen.ts b/src/useFullscreen.ts index 55f3003bb1..cd5c21d676 100644 --- a/src/useFullscreen.ts +++ b/src/useFullscreen.ts @@ -1,68 +1,71 @@ -import {useEffect, RefObject, useCallback} from 'react'; +import {useLayoutEffect, RefObject, useState} from 'react'; import screenfull from 'screenfull'; -import useToggle from './useToggle' -export interface State { - fullscreen: boolean +export interface FullScreenOptions { + video?: HTMLVideoElement; + onClose?: (error?: Error) => void; } -const useFullscreen = (ref: RefObject, videoRef?: RefObject): [boolean, (value?: boolean) => void] => { - const [fullscreen, toggle] = useToggle(false); +const noop = () => {}; + +const useFullscreen = (ref: RefObject, on: boolean, options: FullScreenOptions = {}): boolean => { + const {video, onClose = noop} = options; + const [isFullscreen, setIsFullscreen] = useState(on); + + useLayoutEffect(() => { + if (!on) return; + if (!ref.current) return; + + const onWebkitEndFullscreen = () => { + video!.removeEventListener('webkitendfullscreen', onWebkitEndFullscreen); + onClose(); + }; - useEffect(() => { const onChange = () => { if (screenfull) { - toggle(screenfull.isFullscreen) + const isFullscreen = screenfull.isFullscreen; + setIsFullscreen(isFullscreen); + if (!isFullscreen) { + onClose(); + } } - } + }; if (screenfull && screenfull.enabled) { + try { + screenfull.request(ref.current); + setIsFullscreen(true); + } catch (error) { + onClose(error); + setIsFullscreen(false); + } screenfull.on('change', onChange); + } else { + if (video && video.webkitEnterFullscreen) { + video.webkitEnterFullscreen(); + video.addEventListener('webkitendfullscreen', onWebkitEndFullscreen); + setIsFullscreen(true); + } else { + onClose(); + setIsFullscreen(false); + } } return () => { + setIsFullscreen(false); if (screenfull && screenfull.enabled) { - screenfull.off('change', onChange); - } - } - }, []); - - const toggleFullscreen = useCallback(async (nextValue?: boolean) => { - nextValue = typeof nextValue === 'undefined' ? !fullscreen : nextValue; - - if (screenfull && screenfull.enabled) { - try { - if (nextValue) { - await screenfull.request(ref.current || undefined); - } else { - await screenfull.exit(); - } - toggle(nextValue); - } catch {} - } else { - if (videoRef && videoRef.current) { - if (nextValue) { - if (videoRef.current.webkitEnterFullscreen) { - const onWebkitEndFullscreen = () => { - if (videoRef.current) { - videoRef.current.removeEventListener('webkitendfullscreen', onWebkitEndFullscreen); - toggle(false) - } - }; - - videoRef.current.webkitEnterFullscreen(); - toggle(true) - videoRef.current.addEventListener('webkitendfullscreen', onWebkitEndFullscreen); - } - } else if (videoRef.current.webkitExitFullscreen) { - videoRef.current.webkitExitFullscreen(); - toggle(false) - } + try { + screenfull.off('change', onChange); + screenfull.exit(); + } catch {} + } else if (video && video.webkitExitFullscreen) { + video.removeEventListener('webkitendfullscreen', onWebkitEndFullscreen); + video.webkitExitFullscreen(); } } - }, [fullscreen, toggle]) + }, [ref.current, video, on]); - return [fullscreen, toggleFullscreen] + return isFullscreen; }; export default useFullscreen;