From bca7635ca4c09dae4e38940f5f72edd95921fbac Mon Sep 17 00:00:00 2001 From: Samuel Newman <10959775+mozzius@users.noreply.github.com> Date: Mon, 5 Aug 2024 12:01:32 +0100 Subject: [PATCH] rework fullscreen API --- .../util/post-embeds/VideoEmbedInner.web.tsx | 10 +--- .../com/util/post-embeds/VideoWebControls.tsx | 2 +- .../util/post-embeds/VideoWebControls.web.tsx | 50 ++++++++++--------- 3 files changed, 30 insertions(+), 32 deletions(-) diff --git a/src/view/com/util/post-embeds/VideoEmbedInner.web.tsx b/src/view/com/util/post-embeds/VideoEmbedInner.web.tsx index b5e4f9954b..f5f47db506 100644 --- a/src/view/com/util/post-embeds/VideoEmbedInner.web.tsx +++ b/src/view/com/util/post-embeds/VideoEmbedInner.web.tsx @@ -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 Hls from 'hls.js' @@ -49,12 +49,6 @@ export function VideoEmbedInner({ } }, [source]) - const enterFullscreen = useCallback(() => { - if (containerRef.current) { - containerRef.current.requestFullscreen() - } - }, []) - return ( diff --git a/src/view/com/util/post-embeds/VideoWebControls.tsx b/src/view/com/util/post-embeds/VideoWebControls.tsx index 5fb8343013..11e0867e43 100644 --- a/src/view/com/util/post-embeds/VideoWebControls.tsx +++ b/src/view/com/util/post-embeds/VideoWebControls.tsx @@ -9,7 +9,7 @@ export function Controls({}: { focused: boolean setFocused: (focused: boolean) => void onScreen: boolean - enterFullscreen: () => void + fullscreenRef: React.RefObject hasSubtitleTrack: boolean }): React.ReactElement { throw new Error('Web-only component') diff --git a/src/view/com/util/post-embeds/VideoWebControls.web.tsx b/src/view/com/util/post-embeds/VideoWebControls.web.tsx index 5b8a392f56..bfe6f71a22 100644 --- a/src/view/com/util/post-embeds/VideoWebControls.web.tsx +++ b/src/view/com/util/post-embeds/VideoWebControls.web.tsx @@ -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 Animated, {FadeIn, FadeOut} from 'react-native-reanimated' import {msg, Trans} from '@lingui/macro' @@ -36,7 +42,7 @@ export function Controls({ focused, setFocused, onScreen, - enterFullscreen, + fullscreenRef, hasSubtitleTrack, }: { videoRef: React.RefObject @@ -46,7 +52,7 @@ export function Controls({ focused: boolean setFocused: (focused: boolean) => void onScreen: boolean - enterFullscreen: () => void + fullscreenRef: React.RefObject hasSubtitleTrack: boolean }) { const { @@ -71,7 +77,7 @@ export function Controls({ onIn: onMouseEnter, onOut: onMouseLeave, } = useInteractionState() - const isFullscreen = useFullscreen() + const [isFullscreen, toggleFullscreen] = useFullscreen(fullscreenRef) const {state: hasFocus, onIn: onFocus, onOut: onBlur} = useInteractionState() const [interactingViaKeypress, setInteractingViaKeypress] = useState(false) @@ -163,12 +169,8 @@ export function Controls({ const onPressFullscreen = useCallback(() => { drawFocus() - if (document.fullscreenElement) { - document.exitFullscreen() - } else { - enterFullscreen() - } - }, [drawFocus, enterFullscreen]) + toggleFullscreen() + }, [drawFocus, toggleFullscreen]) const showControls = (focused && !playing) || (interactingViaKeypress ? hasFocus : hovered) @@ -536,22 +538,24 @@ function useVideoUtils(ref: React.RefObject) { } } -function useFullscreen() { - const [isFullscreen, setIsFullscreen] = useState( +function fullscreenSubscribe(onChange: () => void) { + document.addEventListener('fullscreenchange', onChange) + return () => document.removeEventListener('fullscreenchange', onChange) +} + +function useFullscreen(ref: React.RefObject) { + const isFullscreen = useSyncExternalStore(fullscreenSubscribe, () => Boolean(document.fullscreenElement), ) - useEffect(() => { - const handleFullscreenChange = () => { - setIsFullscreen(Boolean(document.fullscreenElement)) + const toggleFullscreen = useCallback(() => { + if (isFullscreen) { + document.exitFullscreen() + } else { + if (!ref.current) return + ref.current.requestFullscreen() } + }, [isFullscreen, ref]) - document.addEventListener('fullscreenchange', handleFullscreenChange) - - return () => { - document.removeEventListener('fullscreenchange', handleFullscreenChange) - } - }, []) - - return isFullscreen + return [isFullscreen, toggleFullscreen] as const }