import React, { useContext, useEffect, useState } from 'react'; import { Platform, StyleSheet, TouchableOpacity, View } from 'react-native'; import { RouteProp, useFocusEffect, useNavigation } from '@react-navigation/native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { Channel, ChannelAvatar, MessageInput, MessageList, ThreadContextValue, useAttachmentPickerContext, useChannelPreviewDisplayName, useChatContext, useTheme, useTypingString, } from 'stream-chat-react-native'; import { ScreenHeader } from '../components/ScreenHeader'; import { AppContext } from '../context/AppContext'; import { useChannelMembersStatus } from '../hooks/useChannelMembersStatus'; import type { StackNavigationProp } from '@react-navigation/stack'; import type { Channel as StreamChatChannel } from 'stream-chat'; import type { LocalAttachmentType, LocalChannelType, LocalCommandType, LocalEventType, LocalMessageType, LocalReactionType, LocalUserType, StackNavigatorParamList, } from '../types'; import { NetworkDownIndicator } from '../components/NetworkDownIndicator'; const styles = StyleSheet.create({ flex: { flex: 1 }, }); export type ChannelScreenNavigationProp = StackNavigationProp< StackNavigatorParamList, 'ChannelScreen' >; export type ChannelScreenRouteProp = RouteProp; export type ChannelScreenProps = { navigation: ChannelScreenNavigationProp; route: ChannelScreenRouteProp; }; export type ChannelHeaderProps = { channel: StreamChatChannel< LocalAttachmentType, LocalChannelType, LocalCommandType, LocalEventType, LocalMessageType, LocalReactionType, LocalUserType >; }; const ChannelHeader: React.FC = ({ channel }) => { const { closePicker } = useAttachmentPickerContext(); const membersStatus = useChannelMembersStatus(channel); const displayName = useChannelPreviewDisplayName(channel, 30); const { isOnline } = useChatContext(); const { chatClient } = useContext(AppContext); const navigation = useNavigation(); const typing = useTypingString(); if (!channel || !chatClient) return null; const isOneOnOneConversation = channel && Object.values(channel.state.members).length === 2 && channel.id?.indexOf('!members-') === 0; return ( ( { closePicker(); if (isOneOnOneConversation) { navigation.navigate('OneOnOneChannelDetailScreen', { channel, }); } else { navigation.navigate('GroupChannelDetailsScreen', { channel, }); } }} > )} showUnreadCountBadge Subtitle={isOnline ? undefined : NetworkDownIndicator} subtitleText={typing ? typing : membersStatus} titleText={displayName} /> ); }; // Either provide channel or channelId. export const ChannelScreen: React.FC = ({ route: { params: { channel: channelFromProp, channelId, messageId }, }, }) => { const { chatClient } = useContext(AppContext); const navigation = useNavigation(); const { bottom } = useSafeAreaInsets(); const { theme: { colors: { white }, }, } = useTheme(); const [channel, setChannel] = useState< | StreamChatChannel< LocalAttachmentType, LocalChannelType, LocalCommandType, LocalEventType, LocalMessageType, LocalReactionType, LocalUserType > | undefined >(channelFromProp); const [selectedThread, setSelectedThread] = useState< ThreadContextValue< LocalAttachmentType, LocalChannelType, LocalCommandType, LocalEventType, LocalMessageType, LocalReactionType, LocalUserType >['thread'] >(); useEffect(() => { const initChannel = async () => { if (!chatClient || !channelId) return; const newChannel = chatClient?.channel('messaging', channelId); if (!newChannel?.initialized) { await newChannel?.watch(); } setChannel(newChannel); }; initChannel(); }, [channelId]); useFocusEffect(() => { setSelectedThread(undefined); }); if (!channel || !chatClient) return null; return ( null} thread={selectedThread} > onThreadSelect={(thread) => { setSelectedThread(thread); navigation.navigate('ThreadScreen', { channel, thread, }); }} /> ); };