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
}