diff options
author | Hailey <me@haileyok.com> | 2024-09-13 14:07:13 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-13 14:07:13 -0700 |
commit | 843f9925f5d0773db321e617c1bd0be6a308ef7f (patch) | |
tree | 1233962c59d92247f64e7dd299910653a76bf78a /src | |
parent | 791bc7afbe0efd9519740b999799e6002b0fc835 (diff) | |
download | voidsky-843f9925f5d0773db321e617c1bd0be6a308ef7f.tar.zst |
[Video] Remember mute state while scrolling (#5331)
Diffstat (limited to 'src')
-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 |
4 files changed, 116 insertions, 78 deletions
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 +} |