Skip to content

Commit ea8ad75

Browse files
authored
fix: component context issues (#3549)
## 🎯 Goal A follow-up to [this PR](#3542), containing fixes to some introduced issues. Additionally, it does some final touches to our API before the major release on Thursday. ## 🛠 Implementation details <!-- Provide a description of the implementation --> ## 🎨 UI Changes <!-- Add relevant screenshots --> <details> <summary>iOS</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> <details> <summary>Android</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> ## 🧪 Testing <!-- Explain how this change can be tested (or why it can't be tested) --> ## ☑️ Checklist - [ ] I have signed the [Stream CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) (required) - [ ] PR targets the `develop` branch - [ ] Documentation is updated - [ ] New code is tested in main example apps, including all possible scenarios - [ ] SampleApp iOS and Android - [ ] Expo iOS and Android
1 parent 15dd5e1 commit ea8ad75

File tree

29 files changed

+391
-498
lines changed

29 files changed

+391
-498
lines changed

examples/ExpoMessaging/app/channel/[cid]/index.tsx

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,11 @@ import {
66
useChatContext,
77
ThreadContextValue,
88
MessageList,
9-
WithComponents,
109
} from 'stream-chat-expo';
1110
import { Stack, useLocalSearchParams, useRouter } from 'expo-router';
1211
import { AuthProgressLoader } from '../../../components/AuthProgressLoader';
1312
import { AppContext } from '../../../context/AppContext';
1413
import { useHeaderHeight } from '@react-navigation/elements';
15-
import InputButtons from '../../../components/InputButtons';
16-
import { MessageLocation } from '../../../components/LocationSharing/MessageLocation';
1714
import { StyleSheet, View } from 'react-native';
1815

1916
export default function ChannelScreen() {
@@ -71,23 +68,21 @@ export default function ChannelScreen() {
7168
<Stack.Screen
7269
options={{ title: 'Channel Screen', contentStyle: { backgroundColor: 'white' } }}
7370
/>
74-
<WithComponents overrides={{ MessageLocation, InputButtons }}>
75-
<Channel
76-
audioRecordingEnabled={true}
77-
channel={channel}
78-
onPressMessage={onPressMessage}
79-
keyboardVerticalOffset={headerHeight}
80-
thread={thread}
81-
>
82-
<MessageList
83-
onThreadSelect={(thread: ThreadContextValue['thread']) => {
84-
setThread(thread);
85-
router.push(`/channel/${channel.cid}/thread/${thread?.cid ?? ''}`);
86-
}}
87-
/>
88-
<MessageComposer />
89-
</Channel>
90-
</WithComponents>
71+
<Channel
72+
audioRecordingEnabled={true}
73+
channel={channel}
74+
onPressMessage={onPressMessage}
75+
keyboardVerticalOffset={headerHeight}
76+
thread={thread}
77+
>
78+
<MessageList
79+
onThreadSelect={(thread: ThreadContextValue['thread']) => {
80+
setThread(thread);
81+
router.push(`/channel/${channel.cid}/thread/${thread?.cid ?? ''}`);
82+
}}
83+
/>
84+
<MessageComposer />
85+
</Channel>
9186
</View>
9287
);
9388
}

examples/ExpoMessaging/components/ChatWrapper.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ import {
66
SqliteClient,
77
Streami18n,
88
useCreateChatClient,
9+
WithComponents,
910
} from 'stream-chat-expo';
1011
import { UserResponse } from 'stream-chat';
1112
import { AuthProgressLoader } from './AuthProgressLoader';
1213
import { useStreamChatTheme } from '../hooks/useStreamChatTheme';
1314
import { useUserContext } from '@/context/UserContext';
1415
import { STREAM_API_KEY, USER_TOKENS } from '@/constants/ChatUsers';
1516
import { usePushNotifications } from '@/hooks/usePushNotifications';
17+
import { useExpoMessagingComponentOverrides } from './ExpoMessagingComponentOverrides';
1618
import '../utils/backgroundMessageHandler';
1719

1820
const streami18n = new Streami18n({
@@ -39,16 +41,19 @@ export const ChatWrapper = ({ children }: PropsWithChildren<{}>) => {
3941
});
4042

4143
const theme = useStreamChatTheme();
44+
const componentOverrides = useExpoMessagingComponentOverrides();
4245

4346
if (!chatClient) {
4447
return <AuthProgressLoader />;
4548
}
4649

4750
return (
48-
<OverlayProvider i18nInstance={streami18n} value={{ style: theme }}>
49-
<Chat client={chatClient} i18nInstance={streami18n} enableOfflineSupport>
50-
{children}
51-
</Chat>
52-
</OverlayProvider>
51+
<WithComponents overrides={componentOverrides}>
52+
<OverlayProvider i18nInstance={streami18n} value={{ style: theme }}>
53+
<Chat client={chatClient} i18nInstance={streami18n} enableOfflineSupport>
54+
{children}
55+
</Chat>
56+
</OverlayProvider>
57+
</WithComponents>
5358
);
5459
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { useMemo } from 'react';
2+
import type { ComponentOverrides } from 'stream-chat-expo';
3+
4+
import InputButtons from './InputButtons';
5+
import { MessageLocation } from './LocationSharing/MessageLocation';
6+
7+
export const useExpoMessagingComponentOverrides = () => {
8+
return useMemo<ComponentOverrides>(
9+
() => ({ InputButtons, MessageLocation }),
10+
[],
11+
);
12+
};

examples/SampleApp/App.tsx

Lines changed: 41 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,12 @@ import {
44
I18nManager,
55
LogBox,
66
Platform,
7-
StyleSheet,
87
useColorScheme,
9-
View,
108
} from 'react-native';
119
import { createDrawerNavigator } from '@react-navigation/drawer';
1210
import { DarkTheme, DefaultTheme, NavigationContainer } from '@react-navigation/native';
1311
import { createNativeStackNavigator } from '@react-navigation/native-stack';
1412
import { SafeAreaProvider } from 'react-native-safe-area-context';
15-
import { BlurView } from '@react-native-community/blur';
1613
import {
1714
Chat,
1815
createTextComposerEmojiMiddleware,
@@ -23,7 +20,7 @@ import {
2320
Streami18n,
2421
ThemeProvider,
2522
useOverlayContext,
26-
useTheme,
23+
WithComponents,
2724
} from 'stream-chat-react-native';
2825

2926
import { getMessaging } from '@react-native-firebase/messaging';
@@ -55,10 +52,10 @@ import Geolocation from '@react-native-community/geolocation';
5552
import type { StackNavigatorParamList, UserSelectorParamList } from './src/types';
5653
import { GestureHandlerRootView } from 'react-native-gesture-handler';
5754
import { navigateToChannel, RootNavigationRef } from './src/utils/RootNavigation';
58-
import FastImage from 'react-native-fast-image';
5955
import { StreamChatProvider } from './src/context/StreamChatContext';
6056
import { MapScreen } from './src/screens/MapScreen';
6157
import { watchLocation } from './src/utils/watchLocation';
58+
import { useSampleAppComponentOverrides } from './src/components/SampleAppComponentOverrides';
6259

6360
Geolocation.setRNConfiguration({
6461
skipPermissionRequests: false,
@@ -107,30 +104,6 @@ const Stack = createNativeStackNavigator<StackNavigatorParamList>();
107104
const UserSelectorStack = createNativeStackNavigator<UserSelectorParamList>();
108105
const RTL_STORAGE_KEY = '@stream-rn-sampleapp-rtl-enabled';
109106

110-
const MessageOverlayBlurBackground = () => {
111-
const {
112-
theme: { semantics },
113-
} = useTheme();
114-
const scheme = useColorScheme();
115-
const isDark = scheme === 'dark';
116-
const isIOS = Platform.OS === 'ios';
117-
118-
return (
119-
<>
120-
<BlurView
121-
blurAmount={isIOS ? 10 : 6}
122-
blurType={isDark ? 'dark' : 'light'}
123-
blurRadius={isIOS ? undefined : 6}
124-
downsampleFactor={isIOS ? undefined : 12}
125-
pointerEvents='none'
126-
reducedTransparencyFallbackColor='rgba(0, 0, 0, 0.8)'
127-
style={StyleSheet.absoluteFill}
128-
/>
129-
<View style={[StyleSheet.absoluteFill, { backgroundColor: semantics.backgroundCoreScrim }]} />
130-
</>
131-
);
132-
};
133-
134107
const App = () => {
135108
const { chatClient, isConnecting, loginUser, logout, switchUser } = useChatClient();
136109
const [rtlEnabled, setRtlEnabled] = useState<boolean | undefined>(undefined);
@@ -152,6 +125,7 @@ const App = () => {
152125
const colorScheme = useColorScheme();
153126
const streamChatTheme = useStreamChatTheme();
154127
const streami18n = new Streami18n();
128+
const componentOverrides = useSampleAppComponentOverrides(messageOverlayBackdrop);
155129

156130
const setRTLEnabled = React.useCallback(async (enabled: boolean) => {
157131
await AsyncStore.setItem(RTL_STORAGE_KEY, enabled);
@@ -295,50 +269,46 @@ const App = () => {
295269
}}
296270
>
297271
<GestureHandlerRootView style={{ flex: 1 }}>
298-
<OverlayProvider
299-
MessageOverlayBackground={
300-
messageOverlayBackdrop === 'blurview' ? MessageOverlayBlurBackground : undefined
301-
}
302-
value={{ style: streamChatTheme }}
303-
i18nInstance={streami18n}
304-
>
305-
<ThemeProvider style={streamChatTheme}>
306-
<NavigationContainer
307-
ref={RootNavigationRef}
308-
theme={{
309-
colors: {
310-
...(colorScheme === 'dark' ? DarkTheme : DefaultTheme).colors,
311-
background: streamChatTheme.colors?.white_snow || '#FCFCFC',
312-
},
313-
fonts: (colorScheme === 'dark' ? DarkTheme : DefaultTheme).fonts,
314-
dark: colorScheme === 'dark',
315-
}}
316-
>
317-
<AppContext.Provider
318-
value={{
319-
chatClient,
320-
loginUser,
321-
logout,
322-
switchUser,
323-
rtlEnabled,
324-
setRTLEnabled,
325-
messageListImplementation,
326-
messageInputFloating: messageInputFloating ?? false,
327-
messageListMode,
328-
messageListPruning,
272+
<WithComponents overrides={componentOverrides}>
273+
<OverlayProvider value={{ style: streamChatTheme }} i18nInstance={streami18n}>
274+
<ThemeProvider style={streamChatTheme}>
275+
<NavigationContainer
276+
ref={RootNavigationRef}
277+
theme={{
278+
colors: {
279+
...(colorScheme === 'dark' ? DarkTheme : DefaultTheme).colors,
280+
background: streamChatTheme.colors?.white_snow || '#FCFCFC',
281+
},
282+
fonts: (colorScheme === 'dark' ? DarkTheme : DefaultTheme).fonts,
283+
dark: colorScheme === 'dark',
329284
}}
330285
>
331-
{isConnecting && !chatClient ? (
332-
<LoadingScreen />
333-
) : chatClient ? (
334-
<DrawerNavigatorWrapper chatClient={chatClient} i18nInstance={streami18n} />
335-
) : (
336-
<UserSelector />
337-
)}
338-
</AppContext.Provider>
339-
</NavigationContainer>
340-
</ThemeProvider>
341-
</OverlayProvider>
286+
<AppContext.Provider
287+
value={{
288+
chatClient,
289+
loginUser,
290+
logout,
291+
switchUser,
292+
rtlEnabled,
293+
setRTLEnabled,
294+
messageListImplementation,
295+
messageInputFloating: messageInputFloating ?? false,
296+
messageListMode,
297+
messageListPruning,
298+
}}
299+
>
300+
{isConnecting && !chatClient ? (
301+
<LoadingScreen />
302+
) : chatClient ? (
303+
<DrawerNavigatorWrapper chatClient={chatClient} i18nInstance={streami18n} />
304+
) : (
305+
<UserSelector />
306+
)}
307+
</AppContext.Provider>
308+
</NavigationContainer>
309+
</ThemeProvider>
310+
</OverlayProvider>
311+
</WithComponents>
342312
</GestureHandlerRootView>
343313
</SafeAreaProvider>
344314
);
@@ -369,8 +339,6 @@ const DrawerNavigatorWrapper: React.FC<{
369339
<Chat
370340
client={chatClient}
371341
enableOfflineSupport
372-
// @ts-expect-error - the `ImageComponent` prop is generic, meaning we can expect an error
373-
ImageComponent={FastImage}
374342
isMessageAIGenerated={isMessageAIGenerated}
375343
i18nInstance={i18nInstance}
376344
>

examples/SampleApp/src/components/ChannelPreview.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import React from 'react';
22
import { StyleSheet, View } from 'react-native';
33
import {
4-
ChannelPreviewView,
5-
ChannelPreviewViewProps,
64
ChannelPreviewStatus,
75
ChannelPreviewStatusProps,
86
Pin,
@@ -34,7 +32,7 @@ const styles = StyleSheet.create({
3432
},
3533
});
3634

37-
const CustomChannelPreviewStatus = (props: ChannelPreviewStatusProps) => {
35+
export const CustomChannelPreviewStatus = (props: ChannelPreviewStatusProps) => {
3836
const { channel } = props;
3937

4038
const membership = useChannelMembershipState(channel);
@@ -53,7 +51,3 @@ const CustomChannelPreviewStatus = (props: ChannelPreviewStatusProps) => {
5351
</View>
5452
);
5553
};
56-
57-
export const ChannelPreview: React.FC<ChannelPreviewViewProps> = (props) => {
58-
return <ChannelPreviewView {...props} PreviewStatus={CustomChannelPreviewStatus} />;
59-
};
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import React, { useMemo } from 'react';
2+
import { Platform, StyleSheet, useColorScheme, View } from 'react-native';
3+
import type { ComponentOverrides } from 'stream-chat-react-native';
4+
import { BlurView } from '@react-native-community/blur';
5+
import FastImage from 'react-native-fast-image';
6+
import {
7+
useTheme,
8+
} from 'stream-chat-react-native';
9+
10+
import { CustomAttachmentPickerContent } from './AttachmentPickerContent';
11+
import { CustomChannelPreviewStatus } from './ChannelPreview';
12+
import { MessageLocation } from './LocationSharing/MessageLocation';
13+
import type { MessageOverlayBackdropConfigItem } from './SecretMenu';
14+
15+
const MessageOverlayBlurBackground: NonNullable<ComponentOverrides['MessageOverlayBackground']> =
16+
() => {
17+
const {
18+
theme: { semantics },
19+
} = useTheme();
20+
const scheme = useColorScheme();
21+
const isDark = scheme === 'dark';
22+
const isIOS = Platform.OS === 'ios';
23+
24+
return (
25+
<>
26+
<BlurView
27+
blurAmount={isIOS ? 10 : 6}
28+
blurRadius={isIOS ? undefined : 6}
29+
blurType={isDark ? 'dark' : 'light'}
30+
downsampleFactor={isIOS ? undefined : 12}
31+
pointerEvents='none'
32+
reducedTransparencyFallbackColor='rgba(0, 0, 0, 0.8)'
33+
style={StyleSheet.absoluteFill}
34+
/>
35+
<View
36+
style={[StyleSheet.absoluteFill, { backgroundColor: semantics.backgroundCoreScrim }]}
37+
/>
38+
</>
39+
);
40+
};
41+
42+
const RenderNull = () => null;
43+
44+
export const useSampleAppComponentOverrides = (
45+
messageOverlayBackdrop?: MessageOverlayBackdropConfigItem['value'],
46+
) =>
47+
useMemo<ComponentOverrides>(
48+
() => ({
49+
AttachmentPickerContent: CustomAttachmentPickerContent,
50+
ChannelListHeaderNetworkDownIndicator: RenderNull,
51+
ImageComponent: FastImage,
52+
MessageLocation,
53+
NetworkDownIndicator: RenderNull,
54+
ChannelPreviewStatus: CustomChannelPreviewStatus,
55+
...(messageOverlayBackdrop === 'blurview'
56+
? { MessageOverlayBackground: MessageOverlayBlurBackground }
57+
: {}),
58+
}),
59+
[messageOverlayBackdrop],
60+
);

0 commit comments

Comments
 (0)