feat: 🎸 improve useFullscreen hook

This commit is contained in:
streamich 2019-03-28 22:26:38 +01:00
parent 0f0d7fbef4
commit 7c38165ac8
2 changed files with 73 additions and 56 deletions

View File

@ -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 (
<div ref={ref} style={{backgroundColor: 'white'}}>
<div>{fullscreen ? 'Fullscreen' : 'Not fullscreen'}</div>
const controls = (
<div style={{background: 'white', padding: '20px'}}>
<div>{isFullScreen ? 'is full screen' : 'not full screen'}</div>
<button onClick={() => toggle()}>Toggle</button>
<button onClick={() => toggle(true)}>set ON</button>
<button onClick={() => toggle(false)}>set OFF</button>
<video ref={videoRef} src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" autoPlay />
</div>
);
return (
<div>
<div ref={ref} style={{backgroundColor: isFullScreen ? 'black' : 'grey', width: 400, height: 300, display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
<video ref={videoRef} style={{width: '70%'}} src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" autoPlay />
{isFullScreen && controls}
</div>
<br />
<br />
{!isFullScreen && controls}
</div>
);
};

View File

@ -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<Element>, videoRef?: RefObject<HTMLVideoElement>): [boolean, (value?: boolean) => void] => {
const [fullscreen, toggle] = useToggle(false);
const noop = () => {};
const useFullscreen = (ref: RefObject<Element>, 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) {
screenfull.on('change', onChange);
}
return () => {
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 {}
screenfull.request(ref.current);
setIsFullscreen(true);
} catch (error) {
onClose(error);
setIsFullscreen(false);
}
screenfull.on('change', onChange);
} 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)
}
if (video && video.webkitEnterFullscreen) {
video.webkitEnterFullscreen();
video.addEventListener('webkitendfullscreen', onWebkitEndFullscreen);
setIsFullscreen(true);
} else {
onClose();
setIsFullscreen(false);
}
}
}, [fullscreen, toggle])
return [fullscreen, toggleFullscreen]
return () => {
setIsFullscreen(false);
if (screenfull && screenfull.enabled) {
try {
screenfull.off('change', onChange);
screenfull.exit();
} catch {}
} else if (video && video.webkitExitFullscreen) {
video.removeEventListener('webkitendfullscreen', onWebkitEndFullscreen);
video.webkitExitFullscreen();
}
}
}, [ref.current, video, on]);
return isFullscreen;
};
export default useFullscreen;