aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/messages/ChannelPreview.tsx136
-rw-r--r--src/components/messages/MessagesHeader.tsx6
-rw-r--r--src/components/messages/index.ts1
-rw-r--r--src/screens/chat/ChatListScreen.tsx30
-rw-r--r--src/types/types.ts1
5 files changed, 164 insertions, 10 deletions
diff --git a/src/components/messages/ChannelPreview.tsx b/src/components/messages/ChannelPreview.tsx
new file mode 100644
index 00000000..11408dc1
--- /dev/null
+++ b/src/components/messages/ChannelPreview.tsx
@@ -0,0 +1,136 @@
+import {useNavigation} from '@react-navigation/core';
+import React, {useContext} from 'react';
+import {Image, StyleSheet, Text, View} from 'react-native';
+import {TouchableOpacity} from 'react-native-gesture-handler';
+import {useSelector} from 'react-redux';
+import {ChannelPreviewMessengerProps} from 'stream-chat-react-native';
+import {ChatContext} from '../../App';
+import {RootState} from '../../store/rootReducer';
+import {
+ LocalAttachmentType,
+ LocalChannelType,
+ LocalCommandType,
+ LocalEventType,
+ LocalMessageType,
+ LocalReactionType,
+ LocalUserType,
+} from '../../types';
+import {normalize, SCREEN_HEIGHT} from '../../utils';
+
+const ChannelPreview: React.FC<
+ ChannelPreviewMessengerProps<
+ LocalAttachmentType,
+ LocalChannelType,
+ LocalCommandType,
+ LocalEventType,
+ LocalMessageType,
+ LocalReactionType,
+ LocalUserType
+ >
+> = (props) => {
+ const navigation = useNavigation();
+ const {setChannel} = useContext(ChatContext);
+ const {channel} = props;
+ const {userId: loggedInUserId} = useSelector(
+ (state: RootState) => state.user.user,
+ );
+ const otherMembers = channel
+ ? Object.values(channel.state.members).filter(
+ (member) => member.user?.id !== loggedInUserId,
+ )
+ : [];
+ const member = otherMembers.length === 1 ? otherMembers[0] : undefined;
+ const online = member?.user?.online;
+ const unread = channel.state.unreadCount > 0;
+
+ return (
+ <TouchableOpacity
+ style={styles.container}
+ onPress={() => {
+ setChannel(channel);
+ navigation.navigate('Chat');
+ }}>
+ <View>
+ <Image
+ style={styles.avatar}
+ source={
+ otherMembers.length === 1
+ ? {uri: member?.user?.thumbnail_url}
+ : require('../../assets/images/avatar-placeholder.png')
+ }
+ />
+ {online && <View style={styles.online} />}
+ </View>
+ <View style={styles.content}>
+ <Text
+ style={[styles.name, unread ? styles.unread : {}]}
+ numberOfLines={1}>
+ {member?.user?.first_name} {member?.user?.last_name}
+ </Text>
+ <Text
+ style={[styles.lastMessage, unread ? styles.unread : {}]}
+ numberOfLines={1}>
+ {channel.state.messages[channel.state.messages.length - 1].text}
+ </Text>
+ </View>
+ {unread && <View style={styles.purpleDot} />}
+ </TouchableOpacity>
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ flexDirection: 'row',
+ height: Math.round(SCREEN_HEIGHT / 10),
+ alignItems: 'center',
+ paddingHorizontal: '8%',
+ paddingVertical: '5%',
+ },
+ avatar: {
+ width: normalize(62),
+ height: normalize(62),
+ borderRadius: normalize(62) / 2,
+ },
+ online: {
+ position: 'absolute',
+ backgroundColor: '#6EE7E7',
+ width: normalize(18),
+ height: normalize(18),
+ borderRadius: normalize(18) / 2,
+ borderColor: 'white',
+ borderWidth: 2,
+ bottom: 0,
+ right: 0,
+ },
+ content: {
+ flex: 1,
+ height: '100%',
+ justifyContent: 'space-between',
+ flexDirection: 'column',
+ marginLeft: '5%',
+ },
+ name: {
+ fontWeight: '500',
+ fontSize: normalize(14),
+ lineHeight: normalize(17),
+ },
+ lastMessage: {
+ color: '#828282',
+ fontWeight: '500',
+ fontSize: normalize(12),
+ lineHeight: normalize(14),
+ },
+ unread: {
+ fontWeight: '700',
+ color: 'black',
+ },
+ purpleDot: {
+ backgroundColor: '#8F01FF',
+ width: normalize(10),
+ height: normalize(10),
+ borderRadius: normalize(10) / 2,
+ },
+});
+
+export default ChannelPreview;
diff --git a/src/components/messages/MessagesHeader.tsx b/src/components/messages/MessagesHeader.tsx
index 18c89de3..660da97d 100644
--- a/src/components/messages/MessagesHeader.tsx
+++ b/src/components/messages/MessagesHeader.tsx
@@ -1,4 +1,4 @@
-import React, {useContext} from 'react';
+import React, {Fragment, useContext} from 'react';
import {StyleSheet, View} from 'react-native';
import {Text} from 'react-native-animatable';
import {TouchableOpacity} from 'react-native-gesture-handler';
@@ -16,10 +16,12 @@ const MessagesHeader: React.FC<MessagesHeaderProps> = ({createChannel}) => {
return (
<View style={styles.header}>
<Text style={styles.headerText}>Messages</Text>
- {unread && unread !== 0 && (
+ {unread && unread !== 0 ? (
<Text style={styles.unreadText}>
{unread > 99 ? '99+' : unread} unread
</Text>
+ ) : (
+ <Fragment />
)}
<View style={styles.flex} />
<TouchableOpacity style={styles.compose} onPress={createChannel}>
diff --git a/src/components/messages/index.ts b/src/components/messages/index.ts
index 2d6bb581..e194093c 100644
--- a/src/components/messages/index.ts
+++ b/src/components/messages/index.ts
@@ -1 +1,2 @@
export {default as MessagesHeader} from './MessagesHeader';
+export {default as ChannelPreview} from './ChannelPreview';
diff --git a/src/screens/chat/ChatListScreen.tsx b/src/screens/chat/ChatListScreen.tsx
index 98a7f097..637c6231 100644
--- a/src/screens/chat/ChatListScreen.tsx
+++ b/src/screens/chat/ChatListScreen.tsx
@@ -5,9 +5,18 @@ import {SafeAreaView, StatusBar, StyleSheet, View} from 'react-native';
import {useStore} from 'react-redux';
import {ChannelList, Chat} from 'stream-chat-react-native';
import {ChatContext} from '../../App';
-import {MessagesHeader} from '../../components/messages';
+import {ChannelPreview, MessagesHeader} from '../../components/messages';
import {MainStackParams} from '../../routes';
import {RootState} from '../../store/rootReducer';
+import {
+ LocalAttachmentType,
+ LocalChannelType,
+ LocalCommandType,
+ LocalEventType,
+ LocalMessageType,
+ LocalReactionType,
+ LocalUserType,
+} from '../../types';
type ChatListScreenNavigationProp = StackNavigationProp<
MainStackParams,
@@ -19,8 +28,8 @@ interface ChatListScreenProps {
/*
* Screen that displays all of the user's active conversations.
*/
-const ChatListScreen: React.FC<ChatListScreenProps> = ({navigation}) => {
- const {chatClient, setChannel} = useContext(ChatContext);
+const ChatListScreen: React.FC<ChatListScreenProps> = () => {
+ const {chatClient} = useContext(ChatContext);
const [clientReady, setClientReady] = useState(false);
const state: RootState = useStore().getState();
const loggedInUserId = state.user.user.userId;
@@ -68,12 +77,16 @@ const ChatListScreen: React.FC<ChatListScreenProps> = ({navigation}) => {
{clientReady && (
<Chat client={chatClient}>
<View style={styles.chatContainer}>
- <ChannelList
+ <ChannelList<
+ LocalAttachmentType,
+ LocalChannelType,
+ LocalCommandType,
+ LocalEventType,
+ LocalMessageType,
+ LocalReactionType,
+ LocalUserType
+ >
filters={memoizedFilters}
- onSelect={(channel) => {
- setChannel(channel);
- navigation.navigate('Chat');
- }}
options={{
presence: true,
state: true,
@@ -81,6 +94,7 @@ const ChatListScreen: React.FC<ChatListScreenProps> = ({navigation}) => {
}}
sort={{last_message_at: -1}}
maxUnreadCount={99}
+ Preview={ChannelPreview}
/>
</View>
</Chat>
diff --git a/src/types/types.ts b/src/types/types.ts
index 1a352808..582eefac 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -298,6 +298,7 @@ export type LocalCommandType = string;
export type LocalEventType = Record<string, unknown>;
export type LocalMessageType = Record<string, unknown>;
export type LocalResponseType = Record<string, unknown>;
+export type LocalReactionType = Record<string, unknown>;
export type LocalUserType = Record<string, unknown>;
export type ChatContextType = {