diff options
author | Ivan Chen <ivan@tagg.id> | 2021-04-07 18:22:26 -0400 |
---|---|---|
committer | Ivan Chen <ivan@tagg.id> | 2021-04-07 18:22:26 -0400 |
commit | e3483bcf735c2a65ab53d5ee10e43ca6c5e33864 (patch) | |
tree | decd5c4a2504de4883dcdd2de416a05540f69786 | |
parent | 6e456b97cbdc8c13b586a939ddcdfbf2587ed3cf (diff) |
added figma styling
-rw-r--r-- | src/components/messages/ChannelPreview.tsx | 136 | ||||
-rw-r--r-- | src/components/messages/MessagesHeader.tsx | 6 | ||||
-rw-r--r-- | src/components/messages/index.ts | 1 | ||||
-rw-r--r-- | src/screens/chat/ChatListScreen.tsx | 30 | ||||
-rw-r--r-- | src/types/types.ts | 1 |
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 = { |