fullscreen API

This commit is contained in:
Samuel Newman
2024-07-30 20:04:32 +02:00
parent 92664f57d5
commit e7d269e692
@@ -1,4 +1,4 @@
import React, {useEffect, useRef, useState} from 'react'
import React, {useCallback, useEffect, useRef, useState} from 'react'
import {View} from 'react-native'
import Animated, {FadeIn, FadeOut} from 'react-native-reanimated'
import {msg} from '@lingui/macro'
@@ -86,6 +86,7 @@ export function VideoPlayer({
onScreen: boolean
}) {
const [hls] = useState(() => new Hls())
const containerRef = useRef<HTMLDivElement>(null)
const ref = useRef<HTMLVideoElement>(null)
const [focused, setFocused] = useState(false)
@@ -115,6 +116,12 @@ export function VideoPlayer({
}
}, [source, hls])
const enterFullscreen = useCallback(() => {
if (containerRef.current) {
containerRef.current.requestFullscreen()
}
}, [])
return (
<View
style={[
@@ -136,6 +143,7 @@ export function VideoPlayer({
pointerEvents: 'none',
}}
/>
<div ref={containerRef} style={{flex: 1}}>
<Controls
videoRef={ref}
active={active}
@@ -143,6 +151,7 @@ export function VideoPlayer({
focused={focused}
setFocused={setFocused}
onScreen={onScreen}
enterFullscreen={enterFullscreen}
/>
<video
src={source}
@@ -153,6 +162,7 @@ export function VideoPlayer({
loop
muted={!focused}
/>
</div>
</View>
)
}
@@ -164,6 +174,7 @@ function Controls({
focused,
setFocused,
onScreen,
enterFullscreen,
}: {
videoRef: React.RefObject<HTMLVideoElement>
active: boolean
@@ -171,6 +182,7 @@ function Controls({
focused: boolean
setFocused: (focused: boolean) => void
onScreen: boolean
enterFullscreen: () => void
}) {
const {play, pause, playing, muted, togglePlayPause, currentTime, duration} =
useVideoUtils(videoRef)
@@ -217,6 +229,7 @@ function Controls({
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}>
{hovered && (
<>
<View
style={[
a.w_full,
@@ -237,6 +250,7 @@ function Controls({
size="medium">
<ButtonIcon icon={playing ? PauseIcon : PlayIcon} />
</Button>
<View style={a.flex_1} />
<Button
label={_(muted ? msg`Unmute` : msg`Mute`)}
onPress={() => {
@@ -247,12 +261,15 @@ function Controls({
size="medium">
<ButtonIcon icon={muted ? MuteIcon : UnmuteIcon} />
</Button>
<View style={a.flex_1} />
{/* TODO: find workaround for iOS Safari */}
<Button
label={_(muted ? msg`Unmute` : msg`Mute`)}
onPress={() => {
console.log('clicked fullscreen btn')
if (document.fullscreenElement) {
document.exitFullscreen()
} else {
enterFullscreen()
}
}}
variant="ghost"
shape="round"
@@ -260,6 +277,7 @@ function Controls({
<ButtonIcon icon={FullscreenIcon} />
</Button>
</View>
</>
)}
{(hovered || !focused) && (
<Animated.View
@@ -305,6 +323,13 @@ function useVideoUtils(ref: React.RefObject<HTMLVideoElement>) {
if (!ref.current) return
let current = ref.current
// Initial values
setCurrentTime(current.currentTime || 0)
setDuration(current.duration || 0)
setCanPlay(current.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA)
setMuted(current.muted)
setPlaying(!current.paused)
const handleTimeUpdate = () => {
if (!current) return
setCurrentTime(current.currentTime || 0)
@@ -384,11 +409,7 @@ function useVideoUtils(ref: React.RefObject<HTMLVideoElement>) {
}
const togglePlayPause = () => {
if (playing) {
play()
} else {
pause()
}
setPlaying(p => !p)
}
return {play, pause, togglePlayPause, duration, currentTime, playing, muted}