diff --git a/src/App.native.tsx b/src/App.native.tsx
index 69c7629b..a4282e7f 100644
--- a/src/App.native.tsx
+++ b/src/App.native.tsx
@@ -52,7 +52,7 @@ import {Provider as SelectedFeedProvider} from '#/state/shell/selected-feed'
import {Provider as StarterPackProvider} from '#/state/shell/starter-pack'
import {Provider as HiddenRepliesProvider} from '#/state/threadgate-hidden-replies'
import {TestCtrls} from '#/view/com/testing/TestCtrls'
-import {ActiveVideoProvider} from '#/view/com/util/post-embeds/ActiveVideoContext'
+import {Provider as ActiveVideoProvider} from '#/view/com/util/post-embeds/ActiveVideoNativeContext'
import * as Toast from '#/view/com/util/Toast'
import {Shell} from '#/view/shell'
import {ThemeProvider as Alf} from '#/alf'
diff --git a/src/App.web.tsx b/src/App.web.tsx
index 9ec79253..69a8020c 100644
--- a/src/App.web.tsx
+++ b/src/App.web.tsx
@@ -40,7 +40,7 @@ import {Provider as ProgressGuideProvider} from '#/state/shell/progress-guide'
import {Provider as SelectedFeedProvider} from '#/state/shell/selected-feed'
import {Provider as StarterPackProvider} from '#/state/shell/starter-pack'
import {Provider as HiddenRepliesProvider} from '#/state/threadgate-hidden-replies'
-import {ActiveVideoProvider} from '#/view/com/util/post-embeds/ActiveVideoContext'
+import {Provider as ActiveVideoProvider} from '#/view/com/util/post-embeds/ActiveVideoWebContext'
import * as Toast from '#/view/com/util/Toast'
import {ToastContainer} from '#/view/com/util/Toast.web'
import {Shell} from '#/view/shell/index'
diff --git a/src/view/com/util/post-embeds/ActiveVideoNativeContext.tsx b/src/view/com/util/post-embeds/ActiveVideoNativeContext.tsx
new file mode 100644
index 00000000..77616d78
--- /dev/null
+++ b/src/view/com/util/post-embeds/ActiveVideoNativeContext.tsx
@@ -0,0 +1,40 @@
+import React from 'react'
+import {useVideoPlayer, VideoPlayer} from 'expo-video'
+
+import {isNative} from '#/platform/detection'
+
+const Context = React.createContext<{
+ activeSource: string | null
+ setActiveSource: (src: string) => void
+ player: VideoPlayer
+} | null>(null)
+
+export function Provider({children}: {children: React.ReactNode}) {
+ if (!isNative) {
+ throw new Error('ActiveVideoProvider may only be used on native.')
+ }
+
+ const [activeSource, setActiveSource] = React.useState('')
+
+ const player = useVideoPlayer(activeSource, p => {
+ p.muted = true
+ p.loop = true
+ p.play()
+ })
+
+ return (
+
+ {children}
+
+ )
+}
+
+export function useActiveVideoNative() {
+ const context = React.useContext(Context)
+ if (!context) {
+ throw new Error(
+ 'useActiveVideoNative must be used within a ActiveVideoNativeProvider',
+ )
+ }
+ return context
+}
diff --git a/src/view/com/util/post-embeds/ActiveVideoContext.tsx b/src/view/com/util/post-embeds/ActiveVideoWebContext.tsx
similarity index 66%
rename from src/view/com/util/post-embeds/ActiveVideoContext.tsx
rename to src/view/com/util/post-embeds/ActiveVideoWebContext.tsx
index d18dfc09..bc43e997 100644
--- a/src/view/com/util/post-embeds/ActiveVideoContext.tsx
+++ b/src/view/com/util/post-embeds/ActiveVideoWebContext.tsx
@@ -8,19 +8,21 @@ import React, {
} from 'react'
import {useWindowDimensions} from 'react-native'
-import {isNative} from '#/platform/detection'
-import {VideoPlayerProvider} from './VideoPlayerContext'
+import {isNative, isWeb} from '#/platform/detection'
-const ActiveVideoContext = React.createContext<{
+const Context = React.createContext<{
activeViewId: string | null
- setActiveView: (viewId: string, src: string) => void
+ setActiveView: (viewId: string) => void
sendViewPosition: (viewId: string, y: number) => void
} | null>(null)
-export function ActiveVideoProvider({children}: {children: React.ReactNode}) {
+export function Provider({children}: {children: React.ReactNode}) {
+ if (!isWeb) {
+ throw new Error('ActiveVideoWebContext may onl be used on web.')
+ }
+
const [activeViewId, setActiveViewId] = useState(null)
const activeViewLocationRef = useRef(Infinity)
- const [source, setSource] = useState(null)
const {height: windowHeight} = useWindowDimensions()
// minimising re-renders by using refs
@@ -31,9 +33,8 @@ export function ActiveVideoProvider({children}: {children: React.ReactNode}) {
}, [activeViewId])
const setActiveView = useCallback(
- (viewId: string, src: string) => {
+ (viewId: string) => {
setActiveViewId(viewId)
- setSource(src)
manuallySetRef.current = true
// we don't know the exact position, but it's definitely on screen
// so just guess that it's in the middle. Any value is fine
@@ -88,32 +89,26 @@ export function ActiveVideoProvider({children}: {children: React.ReactNode}) {
[activeViewId, setActiveView, sendViewPosition],
)
- return (
-
-
- {children}
-
-
- )
+ return {children}
}
-export function useActiveVideoView({source}: {source: string}) {
- const context = React.useContext(ActiveVideoContext)
+export function useActiveVideoWeb() {
+ const context = React.useContext(Context)
if (!context) {
- throw new Error('useActiveVideo must be used within a ActiveVideoProvider')
+ throw new Error(
+ 'useActiveVideoWeb must be used within a ActiveVideoWebProvider',
+ )
}
+
+ const {activeViewId, setActiveView, sendViewPosition} = context
const id = useId()
return {
- active: context.activeViewId === id,
- setActive: useCallback(
- () => context.setActiveView(id, source),
- [context, id, source],
- ),
- currentActiveView: context.activeViewId,
- sendPosition: useCallback(
- (y: number) => context.sendViewPosition(id, y),
- [context, id],
- ),
+ active: activeViewId === id,
+ setActive: () => {
+ setActiveView(id)
+ },
+ currentActiveView: activeViewId,
+ sendPosition: (y: number) => sendViewPosition(id, y),
}
}
diff --git a/src/view/com/util/post-embeds/VideoEmbed.tsx b/src/view/com/util/post-embeds/VideoEmbed.tsx
index 4e2909f4..b2bcd851 100644
--- a/src/view/com/util/post-embeds/VideoEmbed.tsx
+++ b/src/view/com/util/post-embeds/VideoEmbed.tsx
@@ -9,12 +9,13 @@ import {Button, ButtonIcon} from '#/components/Button'
import {Play_Filled_Corner2_Rounded as PlayIcon} from '#/components/icons/Play'
import {VisibilityView} from '../../../../../modules/expo-bluesky-swiss-army'
import {ErrorBoundary} from '../ErrorBoundary'
-import {useActiveVideoView} from './ActiveVideoContext'
+import {useActiveVideoNative} from './ActiveVideoNativeContext'
import * as VideoFallback from './VideoEmbedInner/VideoFallback'
export function VideoEmbed({source}: {source: string}) {
const t = useTheme()
- const {active, setActive} = useActiveVideoView({source})
+ const {activeSource, setActiveSource} = useActiveVideoNative()
+ const isActive = source === activeSource
const {_} = useLingui()
const [key, setKey] = useState(0)
@@ -40,15 +41,17 @@ export function VideoEmbed({source}: {source: string}) {
enabled={true}
onChangeStatus={isActive => {
if (isActive) {
- setActive()
+ setActiveSource(source)
}
}}>
- {active ? (
+ {isActive ? (
) : (