split into inner component again

This commit is contained in:
Samuel Newman
2024-07-04 17:41:27 +01:00
parent d3d235023e
commit bf71a5c80a
4 changed files with 97 additions and 45 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ export function VideoEmbed({source}: {source: string}) {
a.my_xs, a.my_xs,
]}> ]}>
{active ? ( {active ? (
<VideoEmbedInner source={source} /> <VideoEmbedInner source={source} active={active} />
) : ( ) : (
<Button <Button
style={[a.flex_1, t.atoms.bg_contrast_25]} style={[a.flex_1, t.atoms.bg_contrast_25]}
@@ -1,47 +1,35 @@
import React, {useCallback, useEffect, useRef, useState} from 'react' import React, {useCallback, useEffect, useRef, useState} from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import Hls from 'hls.js' import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {atoms as a, useTheme} from '#/alf' import {atoms as a, useTheme} from '#/alf'
import {Button, ButtonIcon} from '#/components/Button'
import {Play_Filled_Corner2_Rounded as PlayIcon} from '#/components/icons/Play'
import {useActiveVideoView} from './ActiveVideoContext' import {useActiveVideoView} from './ActiveVideoContext'
import {VideoEmbedInner} from './VideoEmbedInner'
export function VideoEmbed({source}: {source: string}) { export function VideoEmbed({source}: {source: string}) {
const [hls] = useState(() => new Hls()) const t = useTheme()
const hasLoaded = useRef(false) const ref = useRef<HTMLDivElement>(null)
const ref = useRef<HTMLVideoElement>(null)
const {active, setActive} = useActiveVideoView({ const {active, setActive} = useActiveVideoView({
source, source,
measure: useCallback(() => { measure: () => {
if (ref.current) { if (ref.current) {
return ref.current.getBoundingClientRect() return ref.current.getBoundingClientRect()
} }
}, []), },
}) })
const t = useTheme() const [hasBeenActive, setHasBeenActive] = useState(false)
const {_} = useLingui()
const onPress = useCallback(() => setActive(), [setActive])
useEffect(() => { useEffect(() => {
if (ref.current && active && !hasLoaded.current) { if (active) {
hasLoaded.current = true setHasBeenActive(true)
if (ref.current.canPlayType('application/vnd.apple.mpegurl')) {
ref.current.src = source
} else if (Hls.isSupported()) {
hls.loadSource(source)
} else {
// TODO: fallback
}
} }
}, [source, active, hls]) }, [active])
useEffect(() => {
if (ref.current) {
if (
!ref.current.canPlayType('application/vnd.apple.mpegurl') &&
Hls.isSupported()
) {
hls.attachMedia(ref.current)
}
}
}, [source, active, hls])
return ( return (
<View <View
@@ -50,23 +38,24 @@ export function VideoEmbed({source}: {source: string}) {
a.rounded_sm, a.rounded_sm,
{aspectRatio: 16 / 9}, {aspectRatio: 16 / 9},
a.overflow_hidden, a.overflow_hidden,
active ? t.atoms.bg_contrast_25 : t.atoms.bg_contrast_200, t.atoms.bg_contrast_25,
a.my_xs, a.my_xs,
]}> ]}>
<video <div ref={ref} style={{display: 'flex', flex: 1}}>
ref={ref} {hasBeenActive ? (
style={a.flex_1} <VideoEmbedInner source={source} active={active} />
playsInline ) : (
preload="none" <Button
loop style={[a.flex_1, t.atoms.bg_contrast_25]}
muted onPress={onPress}
autoPlay={active} label={_(msg`Play video`)}
onClick={() => { variant="ghost"
if (!active) { color="secondary"
setActive() size="large">
} <ButtonIcon icon={PlayIcon} />
}} </Button>
/> )}
</div>
</View> </View>
) )
} }
@@ -13,7 +13,7 @@ import {atoms as a} from '#/alf'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import {useVideoPlayer} from './VideoPlayerContext' import {useVideoPlayer} from './VideoPlayerContext'
export const VideoEmbedInner = ({}: {source: string}) => { export function VideoEmbedInner({}: {source: string; active: boolean}) {
const player = useVideoPlayer() const player = useVideoPlayer()
const aref = useAnimatedRef<Animated.View>() const aref = useAnimatedRef<Animated.View>()
const {height: windowHeight} = useWindowDimensions() const {height: windowHeight} = useWindowDimensions()
@@ -0,0 +1,63 @@
import React, {useEffect, useRef, useState} from 'react'
import {View} from 'react-native'
import Hls from 'hls.js'
import {atoms as a, useTheme} from '#/alf'
export function VideoEmbedInner({
source,
active,
}: {
source: string
active: boolean
}) {
const [hls] = useState(() => new Hls())
const ref = useRef<HTMLVideoElement>(null)
const t = useTheme()
useEffect(() => {
if (ref.current) {
if (ref.current.canPlayType('application/vnd.apple.mpegurl')) {
ref.current.src = source
} else if (Hls.isSupported()) {
hls.loadSource(source)
} else {
// TODO: fallback
}
}
}, [source, hls])
useEffect(() => {
if (ref.current) {
if (
!ref.current.canPlayType('application/vnd.apple.mpegurl') &&
Hls.isSupported()
) {
hls.attachMedia(ref.current)
}
}
}, [source, hls])
return (
<View
style={[
a.w_full,
a.rounded_sm,
{aspectRatio: 16 / 9},
a.overflow_hidden,
t.atoms.bg_contrast_25,
a.my_xs,
]}>
<video
src={source}
ref={ref}
style={a.flex_1}
playsInline
preload="none"
loop
muted
autoPlay={active}
/>
</View>
)
}