my fork of the bluesky client

[🐴] Integrate global event bus (#3904)

* Conditionally run global event bus

* Add current convo id context, bundle providers

authored by

Eric Bailey and committed by
GitHub
165fdb70 37f22ca2

+112 -31
+18 -15
src/App.native.tsx
··· 16 16 17 17 import {Provider as StatsigProvider} from '#/lib/statsig/statsig' 18 18 import {logger} from '#/logger' 19 + import {MessagesProvider} from '#/state/messages' 19 20 import {init as initPersistedState} from '#/state/persisted' 20 21 import {Provider as LabelDefsProvider} from '#/state/preferences/label-defs' 21 22 import {Provider as ModerationOptsProvider} from '#/state/preferences/moderation-opts' ··· 97 98 <QueryProvider currentDid={currentAccount?.did}> 98 99 <PushNotificationsListener> 99 100 <StatsigProvider> 100 - {/* LabelDefsProvider MUST come before ModerationOptsProvider */} 101 - <LabelDefsProvider> 102 - <ModerationOptsProvider> 103 - <LoggedOutViewProvider> 104 - <SelectedFeedProvider> 105 - <UnreadNotifsProvider> 106 - <GestureHandlerRootView style={s.h100pct}> 107 - <TestCtrls /> 108 - <Shell /> 109 - </GestureHandlerRootView> 110 - </UnreadNotifsProvider> 111 - </SelectedFeedProvider> 112 - </LoggedOutViewProvider> 113 - </ModerationOptsProvider> 114 - </LabelDefsProvider> 101 + <MessagesProvider> 102 + {/* LabelDefsProvider MUST come before ModerationOptsProvider */} 103 + <LabelDefsProvider> 104 + <ModerationOptsProvider> 105 + <LoggedOutViewProvider> 106 + <SelectedFeedProvider> 107 + <UnreadNotifsProvider> 108 + <GestureHandlerRootView style={s.h100pct}> 109 + <TestCtrls /> 110 + <Shell /> 111 + </GestureHandlerRootView> 112 + </UnreadNotifsProvider> 113 + </SelectedFeedProvider> 114 + </LoggedOutViewProvider> 115 + </ModerationOptsProvider> 116 + </LabelDefsProvider> 117 + </MessagesProvider> 115 118 </StatsigProvider> 116 119 </PushNotificationsListener> 117 120 </QueryProvider>
+17 -14
src/App.web.tsx
··· 9 9 10 10 import {Provider as StatsigProvider} from '#/lib/statsig/statsig' 11 11 import {logger} from '#/logger' 12 + import {MessagesProvider} from '#/state/messages' 12 13 import {init as initPersistedState} from '#/state/persisted' 13 14 import {Provider as LabelDefsProvider} from '#/state/preferences/label-defs' 14 15 import {Provider as ModerationOptsProvider} from '#/state/preferences/moderation-opts' ··· 84 85 key={currentAccount?.did}> 85 86 <QueryProvider currentDid={currentAccount?.did}> 86 87 <StatsigProvider> 87 - {/* LabelDefsProvider MUST come before ModerationOptsProvider */} 88 - <LabelDefsProvider> 89 - <ModerationOptsProvider> 90 - <LoggedOutViewProvider> 91 - <SelectedFeedProvider> 92 - <UnreadNotifsProvider> 93 - <SafeAreaProvider> 94 - <Shell /> 95 - </SafeAreaProvider> 96 - </UnreadNotifsProvider> 97 - </SelectedFeedProvider> 98 - </LoggedOutViewProvider> 99 - </ModerationOptsProvider> 100 - </LabelDefsProvider> 88 + <MessagesProvider> 89 + {/* LabelDefsProvider MUST come before ModerationOptsProvider */} 90 + <LabelDefsProvider> 91 + <ModerationOptsProvider> 92 + <LoggedOutViewProvider> 93 + <SelectedFeedProvider> 94 + <UnreadNotifsProvider> 95 + <SafeAreaProvider> 96 + <Shell /> 97 + </SafeAreaProvider> 98 + </UnreadNotifsProvider> 99 + </SelectedFeedProvider> 100 + </LoggedOutViewProvider> 101 + </ModerationOptsProvider> 102 + </LabelDefsProvider> 103 + </MessagesProvider> 101 104 </StatsigProvider> 102 105 </QueryProvider> 103 106 </React.Fragment>
+12 -1
src/screens/Messages/Conversation/index.tsx
··· 5 5 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' 6 6 import {msg} from '@lingui/macro' 7 7 import {useLingui} from '@lingui/react' 8 - import {useNavigation} from '@react-navigation/native' 8 + import {useFocusEffect, useNavigation} from '@react-navigation/native' 9 9 import {NativeStackScreenProps} from '@react-navigation/native-stack' 10 10 11 11 import {CommonNavigatorParams, NavigationProp} from '#/lib/routes/types' 12 12 import {useGate} from '#/lib/statsig/statsig' 13 + import {useCurrentConvoId} from '#/state/messages/current-convo-id' 13 14 import {BACK_HITSLOP} from 'lib/constants' 14 15 import {isWeb} from 'platform/detection' 15 16 import {ChatProvider, useChat} from 'state/messages' ··· 31 32 export function MessagesConversationScreen({route}: Props) { 32 33 const gate = useGate() 33 34 const convoId = route.params.conversation 35 + const {setCurrentConvoId} = useCurrentConvoId() 36 + 37 + useFocusEffect( 38 + useCallback(() => { 39 + setCurrentConvoId(convoId) 40 + return () => { 41 + setCurrentConvoId(undefined) 42 + } 43 + }, [convoId, setCurrentConvoId]), 44 + ) 34 45 35 46 if (!gate('dms')) return <ClipClopGate /> 36 47
+38
src/state/messages/current-convo-id.tsx
··· 1 + import React from 'react' 2 + 3 + const CurrentConvoIdContext = React.createContext<{ 4 + currentConvoId: string | undefined 5 + setCurrentConvoId: (convoId: string | undefined) => void 6 + }>({ 7 + currentConvoId: undefined, 8 + setCurrentConvoId: () => {}, 9 + }) 10 + 11 + export function useCurrentConvoId() { 12 + const ctx = React.useContext(CurrentConvoIdContext) 13 + if (!ctx) { 14 + throw new Error( 15 + 'useCurrentConvoId must be used within a CurrentConvoIdProvider', 16 + ) 17 + } 18 + return ctx 19 + } 20 + 21 + export function CurrentConvoIdProvider({ 22 + children, 23 + }: { 24 + children: React.ReactNode 25 + }) { 26 + const [currentConvoId, setCurrentConvoId] = React.useState< 27 + string | undefined 28 + >() 29 + const ctx = React.useMemo( 30 + () => ({currentConvoId, setCurrentConvoId}), 31 + [currentConvoId], 32 + ) 33 + return ( 34 + <CurrentConvoIdContext.Provider value={ctx}> 35 + {children} 36 + </CurrentConvoIdContext.Provider> 37 + ) 38 + }
+17 -1
src/state/messages/events/index.tsx
··· 2 2 import {AppState} from 'react-native' 3 3 import {BskyAgent} from '@atproto-labs/api' 4 4 5 + import {useGate} from '#/lib/statsig/statsig' 5 6 import {isWeb} from '#/platform/detection' 6 7 import {MessagesEventBus} from '#/state/messages/events/agent' 7 8 import {MessagesEventBusState} from '#/state/messages/events/types' ··· 20 21 return ctx 21 22 } 22 23 23 - export function MessagesEventBusProvider({ 24 + export function Temp_MessagesEventBusProvider({ 24 25 children, 25 26 }: { 26 27 children: React.ReactNode ··· 65 66 </MessagesEventBusContext.Provider> 66 67 ) 67 68 } 69 + 70 + export function MessagesEventBusProvider({ 71 + children, 72 + }: { 73 + children: React.ReactNode 74 + }) { 75 + const gate = useGate() 76 + const {serviceUrl} = useDmServiceUrlStorage() 77 + if (gate('dms') && serviceUrl) { 78 + return ( 79 + <Temp_MessagesEventBusProvider>{children}</Temp_MessagesEventBusProvider> 80 + ) 81 + } 82 + return children 83 + }
+10
src/state/messages/index.tsx
··· 4 4 import {useFocusEffect, useIsFocused} from '@react-navigation/native' 5 5 6 6 import {Convo, ConvoParams, ConvoState} from '#/state/messages/convo' 7 + import {CurrentConvoIdProvider} from '#/state/messages/current-convo-id' 8 + import {MessagesEventBusProvider} from '#/state/messages/events' 7 9 import {useAgent} from '#/state/session' 8 10 import {useDmServiceUrlStorage} from '#/screens/Messages/Temp/useDmServiceUrlStorage' 9 11 ··· 66 68 67 69 return <ChatContext.Provider value={service}>{children}</ChatContext.Provider> 68 70 } 71 + 72 + export function MessagesProvider({children}: {children: React.ReactNode}) { 73 + return ( 74 + <CurrentConvoIdProvider> 75 + <MessagesEventBusProvider>{children}</MessagesEventBusProvider> 76 + </CurrentConvoIdProvider> 77 + ) 78 + }