diff options
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | src/App.native.tsx | 72 | ||||
-rw-r--r-- | src/App.web.tsx | 75 | ||||
-rw-r--r-- | src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx | 15 | ||||
-rw-r--r-- | src/view/com/util/post-embeds/VideoVolumeContext.tsx | 32 | ||||
-rw-r--r-- | yarn.lock | 8 |
6 files changed, 121 insertions, 83 deletions
diff --git a/package.json b/package.json index 5401d5f7d..1cff0d453 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "@fortawesome/free-regular-svg-icons": "^6.1.1", "@fortawesome/free-solid-svg-icons": "^6.1.1", "@fortawesome/react-native-fontawesome": "^0.3.2", - "@haileyok/bluesky-video": "0.1.2", + "@haileyok/bluesky-video": "0.1.4", "@lingui/react": "^4.5.0", "@mattermost/react-native-paste-input": "^0.7.1", "@miblanchard/react-native-slider": "^2.3.1", diff --git a/src/App.native.tsx b/src/App.native.tsx index 04fea126c..2ec666e2c 100644 --- a/src/App.native.tsx +++ b/src/App.native.tsx @@ -52,6 +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 {Provider as VideoVolumeProvider} from '#/view/com/util/post-embeds/VideoVolumeContext' import * as Toast from '#/view/com/util/Toast' import {Shell} from '#/view/shell' import {ThemeProvider as Alf} from '#/alf' @@ -109,40 +110,43 @@ function InnerApp() { <ThemeProvider theme={theme}> <Splash isReady={isReady && hasCheckedReferrer}> <RootSiblingParent> - <React.Fragment - // Resets the entire tree below when it changes: - key={currentAccount?.did}> - <QueryProvider currentDid={currentAccount?.did}> - <StatsigProvider> - <MessagesProvider> - {/* LabelDefsProvider MUST come before ModerationOptsProvider */} - <LabelDefsProvider> - <ModerationOptsProvider> - <LoggedOutViewProvider> - <SelectedFeedProvider> - <HiddenRepliesProvider> - <UnreadNotifsProvider> - <BackgroundNotificationPreferencesProvider> - <MutedThreadsProvider> - <ProgressGuideProvider> - <GestureHandlerRootView style={s.h100pct}> - <TestCtrls /> - <Shell /> - <NuxDialogs /> - </GestureHandlerRootView> - </ProgressGuideProvider> - </MutedThreadsProvider> - </BackgroundNotificationPreferencesProvider> - </UnreadNotifsProvider> - </HiddenRepliesProvider> - </SelectedFeedProvider> - </LoggedOutViewProvider> - </ModerationOptsProvider> - </LabelDefsProvider> - </MessagesProvider> - </StatsigProvider> - </QueryProvider> - </React.Fragment> + <VideoVolumeProvider> + <React.Fragment + // Resets the entire tree below when it changes: + key={currentAccount?.did}> + <QueryProvider currentDid={currentAccount?.did}> + <StatsigProvider> + <MessagesProvider> + {/* LabelDefsProvider MUST come before ModerationOptsProvider */} + <LabelDefsProvider> + <ModerationOptsProvider> + <LoggedOutViewProvider> + <SelectedFeedProvider> + <HiddenRepliesProvider> + <UnreadNotifsProvider> + <BackgroundNotificationPreferencesProvider> + <MutedThreadsProvider> + <ProgressGuideProvider> + <GestureHandlerRootView + style={s.h100pct}> + <TestCtrls /> + <Shell /> + <NuxDialogs /> + </GestureHandlerRootView> + </ProgressGuideProvider> + </MutedThreadsProvider> + </BackgroundNotificationPreferencesProvider> + </UnreadNotifsProvider> + </HiddenRepliesProvider> + </SelectedFeedProvider> + </LoggedOutViewProvider> + </ModerationOptsProvider> + </LabelDefsProvider> + </MessagesProvider> + </StatsigProvider> + </QueryProvider> + </React.Fragment> + </VideoVolumeProvider> </RootSiblingParent> </Splash> </ThemeProvider> diff --git a/src/App.web.tsx b/src/App.web.tsx index ff9944fa4..bef320826 100644 --- a/src/App.web.tsx +++ b/src/App.web.tsx @@ -41,6 +41,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 {Provider as ActiveVideoProvider} from '#/view/com/util/post-embeds/ActiveVideoWebContext' +import {Provider as VideoVolumeProvider} from '#/view/com/util/post-embeds/VideoVolumeContext' import * as Toast from '#/view/com/util/Toast' import {ToastContainer} from '#/view/com/util/Toast.web' import {Shell} from '#/view/shell/index' @@ -95,42 +96,44 @@ function InnerApp() { <Alf theme={theme}> <ThemeProvider theme={theme}> <RootSiblingParent> - <ActiveVideoProvider> - <React.Fragment - // Resets the entire tree below when it changes: - key={currentAccount?.did}> - <QueryProvider currentDid={currentAccount?.did}> - <StatsigProvider> - <MessagesProvider> - {/* LabelDefsProvider MUST come before ModerationOptsProvider */} - <LabelDefsProvider> - <ModerationOptsProvider> - <LoggedOutViewProvider> - <SelectedFeedProvider> - <HiddenRepliesProvider> - <UnreadNotifsProvider> - <BackgroundNotificationPreferencesProvider> - <MutedThreadsProvider> - <SafeAreaProvider> - <ProgressGuideProvider> - <Shell /> - <NuxDialogs /> - </ProgressGuideProvider> - </SafeAreaProvider> - </MutedThreadsProvider> - </BackgroundNotificationPreferencesProvider> - </UnreadNotifsProvider> - </HiddenRepliesProvider> - </SelectedFeedProvider> - </LoggedOutViewProvider> - </ModerationOptsProvider> - </LabelDefsProvider> - </MessagesProvider> - </StatsigProvider> - </QueryProvider> - </React.Fragment> - <ToastContainer /> - </ActiveVideoProvider> + <VideoVolumeProvider> + <ActiveVideoProvider> + <React.Fragment + // Resets the entire tree below when it changes: + key={currentAccount?.did}> + <QueryProvider currentDid={currentAccount?.did}> + <StatsigProvider> + <MessagesProvider> + {/* LabelDefsProvider MUST come before ModerationOptsProvider */} + <LabelDefsProvider> + <ModerationOptsProvider> + <LoggedOutViewProvider> + <SelectedFeedProvider> + <HiddenRepliesProvider> + <UnreadNotifsProvider> + <BackgroundNotificationPreferencesProvider> + <MutedThreadsProvider> + <SafeAreaProvider> + <ProgressGuideProvider> + <Shell /> + <NuxDialogs /> + </ProgressGuideProvider> + </SafeAreaProvider> + </MutedThreadsProvider> + </BackgroundNotificationPreferencesProvider> + </UnreadNotifsProvider> + </HiddenRepliesProvider> + </SelectedFeedProvider> + </LoggedOutViewProvider> + </ModerationOptsProvider> + </LabelDefsProvider> + </MessagesProvider> + </StatsigProvider> + </QueryProvider> + </React.Fragment> + <ToastContainer /> + </ActiveVideoProvider> + </VideoVolumeProvider> </RootSiblingParent> </ThemeProvider> </Alf> diff --git a/src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx b/src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx index 39ed990ab..ee71daa83 100644 --- a/src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx +++ b/src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx @@ -9,6 +9,7 @@ import {useLingui} from '@lingui/react' import {HITSLOP_30} from '#/lib/constants' import {clamp} from '#/lib/numbers' import {useAutoplayDisabled} from '#/state/preferences' +import {useVideoVolumeState} from 'view/com/util/post-embeds/VideoVolumeContext' import {atoms as a, useTheme} from '#/alf' import {useIsWithinMessage} from '#/components/dms/MessageContext' import {Mute_Stroke2_Corner0_Rounded as MuteIcon} from '#/components/icons/Mute' @@ -37,8 +38,8 @@ export const VideoEmbedInnerNative = React.forwardRef( const videoRef = useRef<BlueskyVideoView>(null) const autoplayDisabled = useAutoplayDisabled() const isWithinMessage = useIsWithinMessage() + const {muted, setMuted} = useVideoVolumeState() - const [isMuted, setIsMuted] = React.useState(true) const [isPlaying, setIsPlaying] = React.useState(false) const [timeRemaining, setTimeRemaining] = React.useState(0) const [error, setError] = React.useState<string>() @@ -66,7 +67,7 @@ export const VideoEmbedInnerNative = React.forwardRef( <BlueskyVideoView url={embed.playlist} autoplay={!autoplayDisabled && !isWithinMessage} - beginMuted={true} + beginMuted={autoplayDisabled ? false : muted} style={[a.rounded_sm]} onActiveChange={e => { setIsActive(e.nativeEvent.isActive) @@ -75,7 +76,7 @@ export const VideoEmbedInnerNative = React.forwardRef( setIsLoading(e.nativeEvent.isLoading) }} onMutedChange={e => { - setIsMuted(e.nativeEvent.isMuted) + setMuted(e.nativeEvent.isMuted) }} onStatusChange={e => { setStatus(e.nativeEvent.status) @@ -103,7 +104,6 @@ export const VideoEmbedInnerNative = React.forwardRef( togglePlayback={() => { videoRef.current?.togglePlayback() }} - isMuted={isMuted} isPlaying={isPlaying} timeRemaining={timeRemaining} /> @@ -119,17 +119,16 @@ function VideoControls({ togglePlayback, timeRemaining, isPlaying, - isMuted, }: { enterFullscreen: () => void toggleMuted: () => void togglePlayback: () => void timeRemaining: number isPlaying: boolean - isMuted: boolean }) { const {_} = useLingui() const t = useTheme() + const {muted} = useVideoVolumeState() // show countdown when: // 1. timeRemaining is a number - was seeing NaNs @@ -161,10 +160,10 @@ function VideoControls({ <ControlButton onPress={toggleMuted} - label={isMuted ? _(msg`Unmute`) : _(msg`Mute`)} + label={muted ? _(msg`Unmute`) : _(msg`Mute`)} accessibilityHint={_(msg`Tap to toggle sound`)} style={{right: 6}}> - {isMuted ? ( + {muted ? ( <MuteIcon width={13} fill={t.palette.white} /> ) : ( <UnmuteIcon width={13} fill={t.palette.white} /> diff --git a/src/view/com/util/post-embeds/VideoVolumeContext.tsx b/src/view/com/util/post-embeds/VideoVolumeContext.tsx new file mode 100644 index 000000000..cccb93ba8 --- /dev/null +++ b/src/view/com/util/post-embeds/VideoVolumeContext.tsx @@ -0,0 +1,32 @@ +import React from 'react' + +const Context = React.createContext( + {} as { + muted: boolean + setMuted: (muted: boolean) => void + }, +) + +export function Provider({children}: {children: React.ReactNode}) { + const [muted, setMuted] = React.useState(true) + + const value = React.useMemo( + () => ({ + muted, + setMuted, + }), + [muted, setMuted], + ) + + return <Context.Provider value={value}>{children}</Context.Provider> +} + +export function useVideoVolumeState() { + const context = React.useContext(Context) + if (!context) { + throw new Error( + 'useVideoVolumeState must be used within a VideoVolumeProvider', + ) + } + return context +} diff --git a/yarn.lock b/yarn.lock index 5fd07230a..16cfb3406 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4104,10 +4104,10 @@ resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== -"@haileyok/bluesky-video@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@haileyok/bluesky-video/-/bluesky-video-0.1.2.tgz#53abb04c22885fcf8a1d8a7510d2cfbe7d45ff91" - integrity sha512-OPltVPNhjrm/+d4YYbaSsKLK7VQWC62ci8J05GO4I/PhWsYLWsAu79CGfZ1YTpfpIjYXyo0HjMmiig5X/hhOsQ== +"@haileyok/bluesky-video@0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@haileyok/bluesky-video/-/bluesky-video-0.1.4.tgz#76acad0dffb9c80745bb752577be23cb566e4562" + integrity sha512-ggpk6E6U3giT+tmTc4GPraViA3ssnP32/Bty61UbZ3LiCQuc694LX+AOt01SfQ0B0fyd63J9DtT5rfaEJyjuzg== "@hapi/accept@^6.0.3": version "6.0.3" |