aboutsummaryrefslogtreecommitdiff
path: root/src/components/messages
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/messages')
-rw-r--r--src/components/messages/ChannelPreview.tsx131
-rw-r--r--src/components/messages/ChatHeader.tsx84
-rw-r--r--src/components/messages/MessagesHeader.tsx20
-rw-r--r--src/components/messages/index.ts1
4 files changed, 230 insertions, 6 deletions
diff --git a/src/components/messages/ChannelPreview.tsx b/src/components/messages/ChannelPreview.tsx
new file mode 100644
index 00000000..312f879a
--- /dev/null
+++ b/src/components/messages/ChannelPreview.tsx
@@ -0,0 +1,131 @@
+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 {useStore} from 'react-redux';
+import {usernameRegex} from 'src/constants';
+import {ChannelPreviewMessengerProps} from 'stream-chat-react-native';
+import {ChatContext} from '../../App';
+import {
+ LocalAttachmentType,
+ LocalChannelType,
+ LocalCommandType,
+ LocalEventType,
+ LocalMessageType,
+ LocalReactionType,
+ LocalUserType,
+} from '../../types';
+import {normalize, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
+import {getMember, isOnline} from '../../utils/messages';
+
+const ChannelPreview: React.FC<ChannelPreviewMessengerProps<
+ LocalAttachmentType,
+ LocalChannelType,
+ LocalCommandType,
+ LocalEventType,
+ LocalMessageType,
+ LocalReactionType,
+ LocalUserType
+>> = (props) => {
+ const {setChannel} = useContext(ChatContext);
+ const state = useStore().getState();
+ const navigation = useNavigation();
+ const {channel} = props;
+ const member = getMember(channel, state);
+ const online = isOnline(member?.user?.last_active);
+ const unread = channel.state.unreadCount > 0;
+
+ return (
+ <TouchableOpacity
+ style={styles.container}
+ onPress={() => {
+ setChannel(channel);
+ navigation.navigate('Chat');
+ }}>
+ <View>
+ <Image
+ style={styles.avatar}
+ source={
+ member
+ ? {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.length > 0
+ ? 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 / 9),
+ width: Math.round(SCREEN_WIDTH * 0.85),
+ alignSelf: 'center',
+ alignItems: 'center',
+ },
+ avatar: {
+ width: normalize(60),
+ height: normalize(60),
+ 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: '60%',
+ flexDirection: 'column',
+ marginLeft: '5%',
+ },
+ name: {
+ fontWeight: '500',
+ fontSize: normalize(14),
+ lineHeight: normalize(17),
+ },
+ lastMessage: {
+ color: '#828282',
+ fontWeight: '500',
+ fontSize: normalize(12),
+ lineHeight: normalize(14),
+ paddingTop: '5%',
+ },
+ unread: {
+ fontWeight: '700',
+ color: 'black',
+ },
+ purpleDot: {
+ backgroundColor: '#8F01FF',
+ width: normalize(10),
+ height: normalize(10),
+ borderRadius: normalize(10) / 2,
+ marginLeft: '5%',
+ },
+});
+
+export default ChannelPreview;
diff --git a/src/components/messages/ChatHeader.tsx b/src/components/messages/ChatHeader.tsx
new file mode 100644
index 00000000..2bc096ec
--- /dev/null
+++ b/src/components/messages/ChatHeader.tsx
@@ -0,0 +1,84 @@
+import React, {useContext} from 'react';
+import {Image, StyleSheet, View} from 'react-native';
+import {Text} from 'react-native-animatable';
+import {useStore} from 'react-redux';
+import {ChatContext} from '../../App';
+import {ChatHeaderHeight, normalize, StatusBarHeight} from '../../utils';
+import {formatLastSeenText, getMember, isOnline} from '../../utils/messages';
+
+type ChatHeaderProps = {};
+
+const ChatHeader: React.FC<ChatHeaderProps> = () => {
+ const {channel} = useContext(ChatContext);
+ const state = useStore().getState();
+ const member = getMember(channel, state);
+ const online = isOnline(member?.user?.last_active);
+ const lastSeen = formatLastSeenText(member?.user?.last_active);
+
+ return (
+ <View style={styles.container}>
+ <View>
+ <Image
+ style={styles.avatar}
+ source={
+ member
+ ? {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} numberOfLines={1}>
+ {member?.user?.first_name} {member?.user?.last_name}
+ </Text>
+ <Text style={styles.lastSeen}>{lastSeen}</Text>
+ </View>
+ </View>
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ height: ChatHeaderHeight - StatusBarHeight,
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingLeft: '15%',
+ },
+ avatar: {
+ width: normalize(40),
+ height: normalize(40),
+ borderRadius: normalize(40) / 2,
+ },
+ online: {
+ position: 'absolute',
+ backgroundColor: '#6EE7E7',
+ width: normalize(16),
+ height: normalize(16),
+ borderRadius: normalize(16) / 2,
+ borderColor: 'white',
+ borderWidth: 3,
+ top: 0,
+ right: 0,
+ },
+ content: {
+ flex: 1,
+ height: '80%',
+ justifyContent: 'space-between',
+ flexDirection: 'column',
+ marginLeft: '5%',
+ },
+ name: {
+ fontWeight: '700',
+ fontSize: normalize(15),
+ lineHeight: normalize(18),
+ },
+ lastSeen: {
+ color: '#828282',
+ fontWeight: '500',
+ fontSize: normalize(12),
+ lineHeight: normalize(14),
+ },
+});
+
+export default ChatHeader;
diff --git a/src/components/messages/MessagesHeader.tsx b/src/components/messages/MessagesHeader.tsx
index d8445580..660da97d 100644
--- a/src/components/messages/MessagesHeader.tsx
+++ b/src/components/messages/MessagesHeader.tsx
@@ -1,23 +1,31 @@
-import * as React 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';
import {normalize} from '../../utils';
+import ComposeIcon from '../../assets/icons/compose.svg';
+import {ChatContext} from '../../App';
type MessagesHeaderProps = {
createChannel: () => void;
};
const MessagesHeader: React.FC<MessagesHeaderProps> = ({createChannel}) => {
+ const {chatClient} = useContext(ChatContext);
+ const unread = chatClient.user?.total_unread_count as number;
return (
<View style={styles.header}>
<Text style={styles.headerText}>Messages</Text>
- <Text style={styles.unreadText}>2 unread</Text>
+ {unread && unread !== 0 ? (
+ <Text style={styles.unreadText}>
+ {unread > 99 ? '99+' : unread} unread
+ </Text>
+ ) : (
+ <Fragment />
+ )}
<View style={styles.flex} />
- <TouchableOpacity
- style={styles.compose}
- onPress={createChannel}>
- <Text>Compose</Text>
+ <TouchableOpacity style={styles.compose} onPress={createChannel}>
+ <ComposeIcon width={normalize(20)} height={normalize(20)} />
</TouchableOpacity>
</View>
);
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';