From 17f5d0980acb635a9cb58a3e2ad6f8d96b360853 Mon Sep 17 00:00:00 2001 From: Samuel Newman <10959775+mozzius@users.noreply.github.com> Date: Fri, 2 Aug 2024 21:19:23 +0200 Subject: [PATCH] rework hls into a ref --- .../util/post-embeds/VideoEmbedInner.web.tsx | 55 ++++++++++--------- .../com/util/post-embeds/VideoWebControls.tsx | 2 +- .../util/post-embeds/VideoWebControls.web.tsx | 18 +++--- 3 files changed, 41 insertions(+), 34 deletions(-) diff --git a/src/view/com/util/post-embeds/VideoEmbedInner.web.tsx b/src/view/com/util/post-embeds/VideoEmbedInner.web.tsx index e8ea5c1b99..37ddc3f5b3 100644 --- a/src/view/com/util/post-embeds/VideoEmbedInner.web.tsx +++ b/src/view/com/util/post-embeds/VideoEmbedInner.web.tsx @@ -82,39 +82,38 @@ export function VideoPlayer({ setActive: () => void onScreen: boolean }) { - const [hls] = useState(() => new Hls({capLevelToPlayerSize: true})) const containerRef = useRef(null) const ref = useRef(null) const [focused, setFocused] = useState(false) const [hasSubtitleTrack, setHasSubtitleTrack] = useState(false) - useEffect(() => { - if (ref.current && Hls.isSupported()) { - hls.attachMedia(ref.current) - // initial value, later on it's managed by Controls - hls.autoLevelCapping = 0 - - hls.on(Hls.Events.SUBTITLE_TRACKS_UPDATED, (event, data) => { - if (data.subtitleTracks.length > 0) { - setHasSubtitleTrack(true) - } - }) - - return () => { - hls.detachMedia() - } - } - }, [hls]) + const hlsRef = useRef(undefined) useEffect(() => { - if (ref.current) { - if (Hls.isSupported()) { - hls.loadSource(source) - } else { - // TODO: fallback + if (!ref.current) return + if (!Hls.isSupported()) throw new UnsupportedError() + + const hls = new Hls({capLevelToPlayerSize: true}) + hlsRef.current = hls + + hls.attachMedia(ref.current) + hls.loadSource(source) + + // initial value, later on it's managed by Controls + hls.autoLevelCapping = 0 + + hls.on(Hls.Events.SUBTITLE_TRACKS_UPDATED, (event, data) => { + if (data.subtitleTracks.length > 0) { + setHasSubtitleTrack(true) } + }) + + return () => { + hlsRef.current = undefined + hls.detachMedia() + hls.destroy() } - }, [source, hls]) + }, [source]) const enterFullscreen = useCallback(() => { if (containerRef.current) { @@ -145,7 +144,7 @@ export function VideoPlayer({ /> ) } + +export class UnsupportedError extends Error { + constructor() { + super('HLS is not supported') + } +} diff --git a/src/view/com/util/post-embeds/VideoWebControls.tsx b/src/view/com/util/post-embeds/VideoWebControls.tsx index a37b07243f..dc092fb230 100644 --- a/src/view/com/util/post-embeds/VideoWebControls.tsx +++ b/src/view/com/util/post-embeds/VideoWebControls.tsx @@ -3,7 +3,7 @@ import type Hls from 'hls.js' export function Controls({}: { videoRef: React.RefObject - hls: Hls + hlsRef: React.RefObject active: boolean setActive: () => void focused: boolean diff --git a/src/view/com/util/post-embeds/VideoWebControls.web.tsx b/src/view/com/util/post-embeds/VideoWebControls.web.tsx index 8787fa8d17..9be64f2d17 100644 --- a/src/view/com/util/post-embeds/VideoWebControls.web.tsx +++ b/src/view/com/util/post-embeds/VideoWebControls.web.tsx @@ -30,7 +30,7 @@ import {Text} from '#/components/Typography' export function Controls({ videoRef, - hls, + hlsRef, active, setActive, focused, @@ -40,7 +40,7 @@ export function Controls({ hasSubtitleTrack, }: { videoRef: React.RefObject - hls: Hls + hlsRef: React.RefObject active: boolean setActive: () => void focused: boolean @@ -112,21 +112,23 @@ export function Controls({ // use minimal quality when not focused useEffect(() => { + if (!hlsRef.current) return if (focused) { // auto decide quality based on network conditions - hls.autoLevelCapping = -1 + hlsRef.current.autoLevelCapping = -1 } else { - hls.autoLevelCapping = 0 + hlsRef.current.autoLevelCapping = 0 } - }, [hls, focused]) + }, [hlsRef, focused]) useEffect(() => { + if (!hlsRef.current) return if (hasSubtitleTrack && subtitlesEnabled && canPlay) { - hls.subtitleTrack = 0 + hlsRef.current.subtitleTrack = 0 } else { - hls.subtitleTrack = -1 + hlsRef.current.subtitleTrack = -1 } - }, [hasSubtitleTrack, subtitlesEnabled, hls, canPlay]) + }, [hasSubtitleTrack, subtitlesEnabled, hlsRef, canPlay]) // clicking on any button should focus the player, if it's not already focused const drawFocus = useCallback(() => {