Skip to content

Commit

Permalink
feat: 🎸 improve useFullscreen hook
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Mar 28, 2019
1 parent 0f0d7fb commit 7c38165
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 53 deletions.
26 changes: 20 additions & 6 deletions src/__stories__/useFullscreen.story.tsx
Original file line number Diff line number Diff line change
@@ -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>
);
};
Expand Down
97 changes: 50 additions & 47 deletions src/useFullscreen.ts
Original file line number Diff line number Diff line change
@@ -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) {
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;

0 comments on commit 7c38165

Please sign in to comment.