[Video] Only allow one `VideoView` to be active at a time, regardless of source (#5131)

zio/stable
Hailey 2024-09-04 08:06:45 -07:00 committed by GitHub
parent 21e48bb2d8
commit dee28f378a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 26 additions and 10 deletions

View File

@ -4,8 +4,9 @@ import {useVideoPlayer, VideoPlayer} from 'expo-video'
import {isNative} from '#/platform/detection' import {isNative} from '#/platform/detection'
const Context = React.createContext<{ const Context = React.createContext<{
activeSource: string | null activeSource: string
setActiveSource: (src: string) => void activeViewId: string | undefined
setActiveSource: (src: string, viewId: string) => void
player: VideoPlayer player: VideoPlayer
} | null>(null) } | null>(null)
@ -15,6 +16,7 @@ export function Provider({children}: {children: React.ReactNode}) {
} }
const [activeSource, setActiveSource] = React.useState('') const [activeSource, setActiveSource] = React.useState('')
const [activeViewId, setActiveViewId] = React.useState<string>()
const player = useVideoPlayer(activeSource, p => { const player = useVideoPlayer(activeSource, p => {
p.muted = true p.muted = true
@ -22,8 +24,19 @@ export function Provider({children}: {children: React.ReactNode}) {
p.play() p.play()
}) })
const setActiveSourceOuter = (src: string, viewId: string) => {
setActiveSource(src)
setActiveViewId(viewId)
}
return ( return (
<Context.Provider value={{activeSource, setActiveSource, player}}> <Context.Provider
value={{
activeSource,
setActiveSource: setActiveSourceOuter,
activeViewId,
player,
}}>
{children} {children}
</Context.Provider> </Context.Provider>
) )

View File

@ -1,4 +1,4 @@
import React, {useCallback, useState} from 'react' import React, {useCallback, useId, useState} from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {Image} from 'expo-image' import {Image} from 'expo-image'
import {AppBskyEmbedVideo} from '@atproto/api' import {AppBskyEmbedVideo} from '@atproto/api'
@ -17,11 +17,14 @@ import {useActiveVideoNative} from './ActiveVideoNativeContext'
import * as VideoFallback from './VideoEmbedInner/VideoFallback' import * as VideoFallback from './VideoEmbedInner/VideoFallback'
export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) { export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) {
const t = useTheme()
const {activeSource, setActiveSource, player} = useActiveVideoNative()
const [isFullscreen, setIsFullscreen] = React.useState(false)
const isActive = embed.playlist === activeSource
const {_} = useLingui() const {_} = useLingui()
const t = useTheme()
const {activeSource, activeViewId, setActiveSource, player} =
useActiveVideoNative()
const viewId = useId()
const [isFullscreen, setIsFullscreen] = React.useState(false)
const isActive = embed.playlist === activeSource && activeViewId === viewId
const [key, setKey] = useState(0) const [key, setKey] = useState(0)
const renderError = useCallback( const renderError = useCallback(
@ -34,7 +37,7 @@ export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) {
const onChangeStatus = (isVisible: boolean) => { const onChangeStatus = (isVisible: boolean) => {
if (isVisible) { if (isVisible) {
setActiveSource(embed.playlist) setActiveSource(embed.playlist, viewId)
if (!player.playing) { if (!player.playing) {
player.play() player.play()
} }
@ -88,7 +91,7 @@ export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) {
<Button <Button
style={[a.absolute, a.inset_0]} style={[a.absolute, a.inset_0]}
onPress={() => { onPress={() => {
setActiveSource(embed.playlist) setActiveSource(embed.playlist, viewId)
}} }}
label={_(msg`Play video`)} label={_(msg`Play video`)}
color="secondary"> color="secondary">