From 843f9925f5d0773db321e617c1bd0be6a308ef7f Mon Sep 17 00:00:00 2001 From: Hailey Date: Fri, 13 Sep 2024 14:07:13 -0700 Subject: [PATCH] [Video] Remember mute state while scrolling (#5331) --- package.json | 2 +- src/App.native.tsx | 72 +++++++++--------- src/App.web.tsx | 75 ++++++++++--------- .../VideoEmbedInner/VideoEmbedInnerNative.tsx | 15 ++-- .../util/post-embeds/VideoVolumeContext.tsx | 32 ++++++++ yarn.lock | 8 +- 6 files changed, 121 insertions(+), 83 deletions(-) create mode 100644 src/view/com/util/post-embeds/VideoVolumeContext.tsx diff --git a/package.json b/package.json index 5401d5f7..1cff0d45 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 04fea126..2ec666e2 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() { - - - - - {/* LabelDefsProvider MUST come before ModerationOptsProvider */} - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + {/* LabelDefsProvider MUST come before ModerationOptsProvider */} + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/App.web.tsx b/src/App.web.tsx index ff9944fa..bef32082 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() { - - - - - - {/* LabelDefsProvider MUST come before ModerationOptsProvider */} - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + {/* LabelDefsProvider MUST come before ModerationOptsProvider */} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx b/src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative.tsx index 39ed990a..ee71daa8 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(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() @@ -66,7 +67,7 @@ export const VideoEmbedInnerNative = React.forwardRef( { 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({ - {isMuted ? ( + {muted ? ( ) : ( 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 00000000..cccb93ba --- /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 {children} +} + +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 5fd07230..16cfb340 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"