rework fullscreen API
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import React, {useCallback, useEffect, useRef, useState} from 'react'
|
import React, {useEffect, useRef, useState} from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import Hls from 'hls.js'
|
import Hls from 'hls.js'
|
||||||
|
|
||||||
@@ -49,12 +49,6 @@ export function VideoEmbedInner({
|
|||||||
}
|
}
|
||||||
}, [source])
|
}, [source])
|
||||||
|
|
||||||
const enterFullscreen = useCallback(() => {
|
|
||||||
if (containerRef.current) {
|
|
||||||
containerRef.current.requestFullscreen()
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
@@ -84,7 +78,7 @@ export function VideoEmbedInner({
|
|||||||
focused={focused}
|
focused={focused}
|
||||||
setFocused={setFocused}
|
setFocused={setFocused}
|
||||||
onScreen={onScreen}
|
onScreen={onScreen}
|
||||||
enterFullscreen={enterFullscreen}
|
fullscreenRef={containerRef}
|
||||||
hasSubtitleTrack={hasSubtitleTrack}
|
hasSubtitleTrack={hasSubtitleTrack}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export function Controls({}: {
|
|||||||
focused: boolean
|
focused: boolean
|
||||||
setFocused: (focused: boolean) => void
|
setFocused: (focused: boolean) => void
|
||||||
onScreen: boolean
|
onScreen: boolean
|
||||||
enterFullscreen: () => void
|
fullscreenRef: React.RefObject<HTMLDivElement>
|
||||||
hasSubtitleTrack: boolean
|
hasSubtitleTrack: boolean
|
||||||
}): React.ReactElement {
|
}): React.ReactElement {
|
||||||
throw new Error('Web-only component')
|
throw new Error('Web-only component')
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
import React, {useCallback, useEffect, useRef, useState} from 'react'
|
import React, {
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
useSyncExternalStore,
|
||||||
|
} from 'react'
|
||||||
import {Pressable, View} from 'react-native'
|
import {Pressable, View} from 'react-native'
|
||||||
import Animated, {FadeIn, FadeOut} from 'react-native-reanimated'
|
import Animated, {FadeIn, FadeOut} from 'react-native-reanimated'
|
||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
@@ -36,7 +42,7 @@ export function Controls({
|
|||||||
focused,
|
focused,
|
||||||
setFocused,
|
setFocused,
|
||||||
onScreen,
|
onScreen,
|
||||||
enterFullscreen,
|
fullscreenRef,
|
||||||
hasSubtitleTrack,
|
hasSubtitleTrack,
|
||||||
}: {
|
}: {
|
||||||
videoRef: React.RefObject<HTMLVideoElement>
|
videoRef: React.RefObject<HTMLVideoElement>
|
||||||
@@ -46,7 +52,7 @@ export function Controls({
|
|||||||
focused: boolean
|
focused: boolean
|
||||||
setFocused: (focused: boolean) => void
|
setFocused: (focused: boolean) => void
|
||||||
onScreen: boolean
|
onScreen: boolean
|
||||||
enterFullscreen: () => void
|
fullscreenRef: React.RefObject<HTMLDivElement>
|
||||||
hasSubtitleTrack: boolean
|
hasSubtitleTrack: boolean
|
||||||
}) {
|
}) {
|
||||||
const {
|
const {
|
||||||
@@ -71,7 +77,7 @@ export function Controls({
|
|||||||
onIn: onMouseEnter,
|
onIn: onMouseEnter,
|
||||||
onOut: onMouseLeave,
|
onOut: onMouseLeave,
|
||||||
} = useInteractionState()
|
} = useInteractionState()
|
||||||
const isFullscreen = useFullscreen()
|
const [isFullscreen, toggleFullscreen] = useFullscreen(fullscreenRef)
|
||||||
const {state: hasFocus, onIn: onFocus, onOut: onBlur} = useInteractionState()
|
const {state: hasFocus, onIn: onFocus, onOut: onBlur} = useInteractionState()
|
||||||
const [interactingViaKeypress, setInteractingViaKeypress] = useState(false)
|
const [interactingViaKeypress, setInteractingViaKeypress] = useState(false)
|
||||||
|
|
||||||
@@ -163,12 +169,8 @@ export function Controls({
|
|||||||
|
|
||||||
const onPressFullscreen = useCallback(() => {
|
const onPressFullscreen = useCallback(() => {
|
||||||
drawFocus()
|
drawFocus()
|
||||||
if (document.fullscreenElement) {
|
toggleFullscreen()
|
||||||
document.exitFullscreen()
|
}, [drawFocus, toggleFullscreen])
|
||||||
} else {
|
|
||||||
enterFullscreen()
|
|
||||||
}
|
|
||||||
}, [drawFocus, enterFullscreen])
|
|
||||||
|
|
||||||
const showControls =
|
const showControls =
|
||||||
(focused && !playing) || (interactingViaKeypress ? hasFocus : hovered)
|
(focused && !playing) || (interactingViaKeypress ? hasFocus : hovered)
|
||||||
@@ -536,22 +538,24 @@ function useVideoUtils(ref: React.RefObject<HTMLVideoElement>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function useFullscreen() {
|
function fullscreenSubscribe(onChange: () => void) {
|
||||||
const [isFullscreen, setIsFullscreen] = useState(
|
document.addEventListener('fullscreenchange', onChange)
|
||||||
|
return () => document.removeEventListener('fullscreenchange', onChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
function useFullscreen(ref: React.RefObject<HTMLElement>) {
|
||||||
|
const isFullscreen = useSyncExternalStore(fullscreenSubscribe, () =>
|
||||||
Boolean(document.fullscreenElement),
|
Boolean(document.fullscreenElement),
|
||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
const toggleFullscreen = useCallback(() => {
|
||||||
const handleFullscreenChange = () => {
|
if (isFullscreen) {
|
||||||
setIsFullscreen(Boolean(document.fullscreenElement))
|
document.exitFullscreen()
|
||||||
|
} else {
|
||||||
|
if (!ref.current) return
|
||||||
|
ref.current.requestFullscreen()
|
||||||
}
|
}
|
||||||
|
}, [isFullscreen, ref])
|
||||||
|
|
||||||
document.addEventListener('fullscreenchange', handleFullscreenChange)
|
return [isFullscreen, toggleFullscreen] as const
|
||||||
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener('fullscreenchange', handleFullscreenChange)
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return isFullscreen
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user