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}
+
+
+
+
+
+ {!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;