import React, { useContext, useEffect, useMemo, useState } from 'react'; import { LogBox, Platform, SafeAreaView, View, useColorScheme, StatusBar } from 'react-native'; import { DarkTheme, DefaultTheme, NavigationContainer, RouteProp } from '@react-navigation/native'; import { createStackNavigator, StackNavigationProp, useHeaderHeight, } from '@react-navigation/stack'; import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context'; import { ChannelSort, Channel as ChannelType, StreamChat } from 'stream-chat'; import { Channel, ChannelList, Chat, MessageInput, MessageList, OverlayProvider, Streami18n, Thread, ThreadContextValue, useAttachmentPickerContext, useOverlayContext, } from 'stream-chat-react-native'; import { useStreamChatTheme } from './useStreamChatTheme'; LogBox.ignoreAllLogs(true); type LocalAttachmentType = Record; type LocalChannelType = Record; type LocalCommandType = string; type LocalEventType = Record; type LocalMessageType = Record; type LocalResponseType = Record; type LocalUserType = Record; const chatClient = StreamChat.getInstance< LocalAttachmentType, LocalChannelType, LocalCommandType, LocalEventType, LocalMessageType, LocalResponseType, LocalUserType >('q95x9hkbyd6p'); const userToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicm9uIn0.eRVjxLvd4aqCEHY_JRa97g6k7WpHEhxL7Z4K4yTot1c'; const user = { id: 'ron', }; const filters = { example: 'example-apps', members: { $in: ['ron'] }, type: 'messaging', }; const sort: ChannelSort = { last_message_at: -1 }; const options = { presence: true, state: true, watch: true, }; /** * Start playing with streami18n instance here: * Please refer to description of this PR for details: https://github.com/GetStream/stream-chat-react-native/pull/150 */ const streami18n = new Streami18n({ language: 'en', }); type ChannelListScreenProps = { navigation: StackNavigationProp; }; const ChannelListScreen: React.FC = ({ navigation }) => { const { setChannel } = useContext(AppContext); const memoizedFilters = useMemo(() => filters, []); return ( filters={memoizedFilters} onSelect={(channel) => { setChannel(channel); navigation.navigate('Channel'); }} options={options} sort={sort} /> ); }; type ChannelScreenProps = { navigation: StackNavigationProp; }; const ChannelScreen: React.FC = ({ navigation }) => { const { channel, setThread, thread } = useContext(AppContext); const headerHeight = useHeaderHeight(); const { setTopInset } = useAttachmentPickerContext(); const { overlay } = useOverlayContext(); useEffect(() => { navigation.setOptions({ gestureEnabled: Platform.OS === 'ios' && overlay === 'none', }); }, [overlay]); useEffect(() => { setTopInset(headerHeight); }, [headerHeight]); return ( onThreadSelect={(thread) => { setThread(thread); if (channel?.id) { navigation.navigate('Thread'); } }} /> ); }; type ThreadScreenProps = { navigation: StackNavigationProp; route: RouteProp; }; const ThreadScreen: React.FC = ({ navigation }) => { const { channel, setThread, thread } = useContext(AppContext); const headerHeight = useHeaderHeight(); const { overlay } = useOverlayContext(); useEffect(() => { navigation.setOptions({ gestureEnabled: Platform.OS === 'ios' && overlay === 'none', }); }, [overlay]); return ( onThreadDismount={() => setThread(null)} /> ); }; type ChannelRoute = { Channel: undefined }; type ChannelListRoute = { ChannelList: undefined }; type ThreadRoute = { Thread: undefined }; type NavigationParamsList = ChannelRoute & ChannelListRoute & ThreadRoute; const Stack = createStackNavigator(); type AppContextType = { channel: | ChannelType< LocalAttachmentType, LocalChannelType, LocalCommandType, LocalEventType, LocalMessageType, LocalResponseType, LocalUserType > | undefined; setChannel: React.Dispatch< React.SetStateAction< | ChannelType< LocalAttachmentType, LocalChannelType, LocalCommandType, LocalEventType, LocalMessageType, LocalResponseType, LocalUserType > | undefined > >; setThread: React.Dispatch< React.SetStateAction< | ThreadContextValue< LocalAttachmentType, LocalChannelType, LocalCommandType, LocalEventType, LocalMessageType, LocalResponseType, LocalUserType >['thread'] | undefined > >; thread: | ThreadContextValue< LocalAttachmentType, LocalChannelType, LocalCommandType, LocalEventType, LocalMessageType, LocalResponseType, LocalUserType >['thread'] | undefined; }; const AppContext = React.createContext({} as AppContextType); const App = () => { const colorScheme = useColorScheme(); const { bottom } = useSafeAreaInsets(); const theme = useStreamChatTheme(); const [channel, setChannel] = useState< ChannelType< LocalAttachmentType, LocalChannelType, LocalCommandType, LocalEventType, LocalMessageType, LocalResponseType, LocalUserType > >(); const [clientReady, setClientReady] = useState(false); const [thread, setThread] = useState< ThreadContextValue< LocalAttachmentType, LocalChannelType, LocalCommandType, LocalEventType, LocalMessageType, LocalResponseType, LocalUserType >['thread'] >(); useEffect(() => { const setupClient = async () => { await chatClient.connectUser(user, userToken); return setClientReady(true); }; setupClient(); }, []); return ( bottomInset={bottom} i18nInstance={streami18n} value={{ style: theme }} > {clientReady && ( ({ headerBackTitle: 'Back', headerRight: () => <>, headerTitle: channel?.data?.name, })} /> ({ headerLeft: () => <> })} /> )} ); }; export default () => { const theme = useStreamChatTheme(); return ( ); };