Skip to content

Commit 5ae0d40

Browse files
authored
[Video] 🫧 Move logic around by platform (#5003)
1 parent 9aa2b2d commit 5ae0d40

File tree

9 files changed

+77
-95
lines changed

9 files changed

+77
-95
lines changed

src/App.native.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ import {Provider as SelectedFeedProvider} from '#/state/shell/selected-feed'
5252
import {Provider as StarterPackProvider} from '#/state/shell/starter-pack'
5353
import {Provider as HiddenRepliesProvider} from '#/state/threadgate-hidden-replies'
5454
import {TestCtrls} from '#/view/com/testing/TestCtrls'
55-
import {ActiveVideoProvider} from '#/view/com/util/post-embeds/ActiveVideoContext'
55+
import {Provider as ActiveVideoProvider} from '#/view/com/util/post-embeds/ActiveVideoNativeContext'
5656
import * as Toast from '#/view/com/util/Toast'
5757
import {Shell} from '#/view/shell'
5858
import {ThemeProvider as Alf} from '#/alf'

src/App.web.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import {Provider as ProgressGuideProvider} from '#/state/shell/progress-guide'
4040
import {Provider as SelectedFeedProvider} from '#/state/shell/selected-feed'
4141
import {Provider as StarterPackProvider} from '#/state/shell/starter-pack'
4242
import {Provider as HiddenRepliesProvider} from '#/state/threadgate-hidden-replies'
43-
import {ActiveVideoProvider} from '#/view/com/util/post-embeds/ActiveVideoContext'
43+
import {Provider as ActiveVideoProvider} from '#/view/com/util/post-embeds/ActiveVideoWebContext'
4444
import * as Toast from '#/view/com/util/Toast'
4545
import {ToastContainer} from '#/view/com/util/Toast.web'
4646
import {Shell} from '#/view/shell/index'
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from 'react'
2+
import {useVideoPlayer, VideoPlayer} from 'expo-video'
3+
4+
import {isNative} from '#/platform/detection'
5+
6+
const Context = React.createContext<{
7+
activeSource: string | null
8+
setActiveSource: (src: string) => void
9+
player: VideoPlayer
10+
} | null>(null)
11+
12+
export function Provider({children}: {children: React.ReactNode}) {
13+
if (!isNative) {
14+
throw new Error('ActiveVideoProvider may only be used on native.')
15+
}
16+
17+
const [activeSource, setActiveSource] = React.useState('')
18+
19+
const player = useVideoPlayer(activeSource, p => {
20+
p.muted = true
21+
p.loop = true
22+
p.play()
23+
})
24+
25+
return (
26+
<Context.Provider value={{activeSource, setActiveSource, player}}>
27+
{children}
28+
</Context.Provider>
29+
)
30+
}
31+
32+
export function useActiveVideoNative() {
33+
const context = React.useContext(Context)
34+
if (!context) {
35+
throw new Error(
36+
'useActiveVideoNative must be used within a ActiveVideoNativeProvider',
37+
)
38+
}
39+
return context
40+
}

src/view/com/util/post-embeds/ActiveVideoContext.tsx renamed to src/view/com/util/post-embeds/ActiveVideoWebContext.tsx

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,21 @@ import React, {
88
} from 'react'
99
import {useWindowDimensions} from 'react-native'
1010

11-
import {isNative} from '#/platform/detection'
12-
import {VideoPlayerProvider} from './VideoPlayerContext'
11+
import {isNative, isWeb} from '#/platform/detection'
1312

14-
const ActiveVideoContext = React.createContext<{
13+
const Context = React.createContext<{
1514
activeViewId: string | null
16-
setActiveView: (viewId: string, src: string) => void
15+
setActiveView: (viewId: string) => void
1716
sendViewPosition: (viewId: string, y: number) => void
1817
} | null>(null)
1918

20-
export function ActiveVideoProvider({children}: {children: React.ReactNode}) {
19+
export function Provider({children}: {children: React.ReactNode}) {
20+
if (!isWeb) {
21+
throw new Error('ActiveVideoWebContext may onl be used on web.')
22+
}
23+
2124
const [activeViewId, setActiveViewId] = useState<string | null>(null)
2225
const activeViewLocationRef = useRef(Infinity)
23-
const [source, setSource] = useState<string | null>(null)
2426
const {height: windowHeight} = useWindowDimensions()
2527

2628
// minimising re-renders by using refs
@@ -31,9 +33,8 @@ export function ActiveVideoProvider({children}: {children: React.ReactNode}) {
3133
}, [activeViewId])
3234

3335
const setActiveView = useCallback(
34-
(viewId: string, src: string) => {
36+
(viewId: string) => {
3537
setActiveViewId(viewId)
36-
setSource(src)
3738
manuallySetRef.current = true
3839
// we don't know the exact position, but it's definitely on screen
3940
// so just guess that it's in the middle. Any value is fine
@@ -88,32 +89,26 @@ export function ActiveVideoProvider({children}: {children: React.ReactNode}) {
8889
[activeViewId, setActiveView, sendViewPosition],
8990
)
9091

91-
return (
92-
<ActiveVideoContext.Provider value={value}>
93-
<VideoPlayerProvider source={source ?? ''}>
94-
{children}
95-
</VideoPlayerProvider>
96-
</ActiveVideoContext.Provider>
97-
)
92+
return <Context.Provider value={value}>{children}</Context.Provider>
9893
}
9994

100-
export function useActiveVideoView({source}: {source: string}) {
101-
const context = React.useContext(ActiveVideoContext)
95+
export function useActiveVideoWeb() {
96+
const context = React.useContext(Context)
10297
if (!context) {
103-
throw new Error('useActiveVideo must be used within a ActiveVideoProvider')
98+
throw new Error(
99+
'useActiveVideoWeb must be used within a ActiveVideoWebProvider',
100+
)
104101
}
102+
103+
const {activeViewId, setActiveView, sendViewPosition} = context
105104
const id = useId()
106105

107106
return {
108-
active: context.activeViewId === id,
109-
setActive: useCallback(
110-
() => context.setActiveView(id, source),
111-
[context, id, source],
112-
),
113-
currentActiveView: context.activeViewId,
114-
sendPosition: useCallback(
115-
(y: number) => context.sendViewPosition(id, y),
116-
[context, id],
117-
),
107+
active: activeViewId === id,
108+
setActive: () => {
109+
setActiveView(id)
110+
},
111+
currentActiveView: activeViewId,
112+
sendPosition: (y: number) => sendViewPosition(id, y),
118113
}
119114
}

src/view/com/util/post-embeds/VideoEmbed.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ import {Button, ButtonIcon} from '#/components/Button'
99
import {Play_Filled_Corner2_Rounded as PlayIcon} from '#/components/icons/Play'
1010
import {VisibilityView} from '../../../../../modules/expo-bluesky-swiss-army'
1111
import {ErrorBoundary} from '../ErrorBoundary'
12-
import {useActiveVideoView} from './ActiveVideoContext'
12+
import {useActiveVideoNative} from './ActiveVideoNativeContext'
1313
import * as VideoFallback from './VideoEmbedInner/VideoFallback'
1414

1515
export function VideoEmbed({source}: {source: string}) {
1616
const t = useTheme()
17-
const {active, setActive} = useActiveVideoView({source})
17+
const {activeSource, setActiveSource} = useActiveVideoNative()
18+
const isActive = source === activeSource
1819
const {_} = useLingui()
1920

2021
const [key, setKey] = useState(0)
@@ -40,15 +41,17 @@ export function VideoEmbed({source}: {source: string}) {
4041
enabled={true}
4142
onChangeStatus={isActive => {
4243
if (isActive) {
43-
setActive()
44+
setActiveSource(source)
4445
}
4546
}}>
46-
{active ? (
47+
{isActive ? (
4748
<VideoEmbedInnerNative />
4849
) : (
4950
<Button
5051
style={[a.flex_1, t.atoms.bg_contrast_25]}
51-
onPress={setActive}
52+
onPress={() => {
53+
setActiveSource(source)
54+
}}
5255
label={_(msg`Play video`)}
5356
variant="ghost"
5457
color="secondary"

src/view/com/util/post-embeds/VideoEmbed.web.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import {
88
} from 'view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerWeb'
99
import {atoms as a, useTheme} from '#/alf'
1010
import {ErrorBoundary} from '../ErrorBoundary'
11-
import {useActiveVideoView} from './ActiveVideoContext'
11+
import {useActiveVideoWeb} from './ActiveVideoWebContext'
1212
import * as VideoFallback from './VideoEmbedInner/VideoFallback'
1313

1414
export function VideoEmbed({source}: {source: string}) {
1515
const t = useTheme()
1616
const ref = useRef<HTMLDivElement>(null)
1717
const {active, setActive, sendPosition, currentActiveView} =
18-
useActiveVideoView({source})
18+
useActiveVideoWeb()
1919
const [onScreen, setOnScreen] = useState(false)
2020

2121
useEffect(() => {

src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {useIsFocused} from '@react-navigation/native'
99
import {HITSLOP_30} from '#/lib/constants'
1010
import {useAppState} from '#/lib/hooks/useAppState'
1111
import {logger} from '#/logger'
12-
import {useVideoPlayer} from '#/view/com/util/post-embeds/VideoPlayerContext'
12+
import {useActiveVideoNative} from 'view/com/util/post-embeds/ActiveVideoNativeContext'
1313
import {atoms as a, useTheme} from '#/alf'
1414
import {Mute_Stroke2_Corner0_Rounded as MuteIcon} from '#/components/icons/Mute'
1515
import {SpeakerVolumeFull_Stroke2_Corner0_Rounded as UnmuteIcon} from '#/components/icons/Speaker'
@@ -20,7 +20,7 @@ import {
2020
import {TimeIndicator} from './TimeIndicator'
2121

2222
export function VideoEmbedInnerNative() {
23-
const player = useVideoPlayer()
23+
const {player} = useActiveVideoNative()
2424
const ref = useRef<VideoView>(null)
2525
const isScreenFocused = useIsFocused()
2626
const isAppFocused = useAppState()

src/view/com/util/post-embeds/VideoPlayerContext.tsx

Lines changed: 0 additions & 47 deletions
This file was deleted.

src/view/com/util/post-embeds/VideoPlayerContext.web.tsx

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)