Skip to content

Commit 2419e82

Browse files
committed
fix: refactor icons in the SDK
2 parents 1b9c965 + b1e4423 commit 2419e82

37 files changed

+1183
-693
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import React, { useMemo } from 'react';
2+
import { View, Text, StyleSheet } from 'react-native';
3+
4+
import { DraftMessage, LocalMessage, MessageResponse } from 'stream-chat';
5+
6+
import { useTheme } from '../../contexts/themeContext/ThemeContext';
7+
import { useMessagePreviewIcon, useMessagePreviewText } from '../../hooks';
8+
import { primitives } from '../../theme';
9+
10+
export type ChannelMessagePreviewProps = {
11+
message: LocalMessage | MessageResponse | DraftMessage;
12+
};
13+
14+
export const ChannelMessagePreview = ({ message }: ChannelMessagePreviewProps) => {
15+
const isMessageDeleted = message?.type === 'deleted';
16+
const {
17+
theme: { semantics },
18+
} = useTheme();
19+
const styles = useStyles({ isMessageDeleted });
20+
const MessagePreviewIcon = useMessagePreviewIcon({ message });
21+
const messagePreviewTitle = useMessagePreviewText({ message });
22+
23+
return (
24+
<View style={[styles.container]}>
25+
{MessagePreviewIcon ? (
26+
<MessagePreviewIcon
27+
height={16}
28+
stroke={isMessageDeleted ? semantics.textTertiary : semantics.textSecondary}
29+
width={16}
30+
/>
31+
) : null}
32+
<Text numberOfLines={1} style={[styles.subtitle]}>
33+
{messagePreviewTitle}
34+
</Text>
35+
</View>
36+
);
37+
};
38+
39+
const useStyles = ({ isMessageDeleted = false }: { isMessageDeleted?: boolean }) => {
40+
const {
41+
theme: {
42+
channelPreview: { messagePreview },
43+
semantics,
44+
},
45+
} = useTheme();
46+
return useMemo(() => {
47+
return StyleSheet.create({
48+
container: {
49+
flexDirection: 'row',
50+
alignItems: 'center',
51+
gap: primitives.spacingXxs,
52+
flexShrink: 1,
53+
...messagePreview.container,
54+
},
55+
subtitle: {
56+
color: isMessageDeleted ? semantics.textTertiary : semantics.textSecondary,
57+
fontSize: primitives.typographyFontSizeSm,
58+
fontWeight: primitives.typographyFontWeightRegular,
59+
includeFontPadding: false,
60+
lineHeight: primitives.typographyLineHeightNormal,
61+
flexShrink: 1,
62+
...messagePreview.subtitle,
63+
},
64+
});
65+
}, [
66+
isMessageDeleted,
67+
semantics.textTertiary,
68+
semantics.textSecondary,
69+
messagePreview.container,
70+
messagePreview.subtitle,
71+
]);
72+
};

package/src/components/ChannelPreview/ChannelListMessageDeliveryStatus.tsx renamed to package/src/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.tsx

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
11
import React, { useMemo } from 'react';
22
import { StyleSheet, Text, View } from 'react-native';
33

4-
import { LocalMessage } from 'stream-chat';
4+
import { LocalMessage, MessageResponse } from 'stream-chat';
55

66
import { ChannelPreviewProps } from './ChannelPreview';
7-
import { LastMessageType } from './hooks/useChannelPreviewData';
8-
9-
import { MessageDeliveryStatus, useMessageDeliveryStatus } from './hooks/useMessageDeliveryStatus';
107

118
import { useChatContext } from '../../contexts/chatContext/ChatContext';
129
import { useTheme } from '../../contexts/themeContext/ThemeContext';
1310
import { useTranslationContext } from '../../contexts/translationContext/TranslationContext';
11+
import { MessageDeliveryStatus, useMessageDeliveryStatus } from '../../hooks';
1412
import { Check, CheckAll, Time } from '../../icons';
1513
import { primitives } from '../../theme';
1614
import { MessageStatusTypes } from '../../utils/utils';
1715

18-
export type ChannelListMessageDeliveryStatusProps = Pick<ChannelPreviewProps, 'channel'> & {
19-
lastMessage: LastMessageType;
16+
export type ChannelMessagePreviewDeliveryStatusProps = Pick<ChannelPreviewProps, 'channel'> & {
17+
message: MessageResponse | LocalMessage;
2018
};
2119

22-
export const ChannelListMessageDeliveryStatus = ({
20+
export const ChannelMessagePreviewDeliveryStatus = ({
2321
channel,
24-
lastMessage,
25-
}: ChannelListMessageDeliveryStatusProps) => {
22+
message,
23+
}: ChannelMessagePreviewDeliveryStatusProps) => {
2624
const { client } = useChatContext();
2725
const { t } = useTranslationContext();
2826
const channelConfigExists = typeof channel?.getConfig === 'function';
@@ -36,9 +34,15 @@ export const ChannelListMessageDeliveryStatus = ({
3634
},
3735
} = useTheme();
3836

37+
const membersWithoutSelf = useMemo(() => {
38+
return Object.values(channel.state?.members || {}).filter(
39+
(member) => member.user?.id !== client.user?.id,
40+
);
41+
}, [channel.state?.members, client.user?.id]);
42+
3943
const isLastMessageByCurrentUser = useMemo(() => {
40-
return lastMessage?.user?.id === client.user?.id;
41-
}, [lastMessage, client.user?.id]);
44+
return message?.user?.id === client.user?.id;
45+
}, [message, client.user?.id]);
4246

4347
const readEvents = useMemo(() => {
4448
if (!channelConfigExists) {
@@ -53,19 +57,23 @@ export const ChannelListMessageDeliveryStatus = ({
5357

5458
const { status } = useMessageDeliveryStatus({
5559
channel,
56-
lastMessage: lastMessage as LocalMessage,
60+
lastMessage: message as LocalMessage,
5761
isReadEventsEnabled: readEvents,
5862
});
5963

60-
if (!isLastMessageByCurrentUser) {
64+
if (!channel.data?.name && membersWithoutSelf.length === 1 && !isLastMessageByCurrentUser) {
6165
return null;
6266
}
6367

68+
if (!isLastMessageByCurrentUser) {
69+
return <Text style={styles.username}>{message?.user?.name || message?.user?.id}:</Text>;
70+
}
71+
6472
return (
6573
<View style={styles.container}>
66-
{lastMessage.status === MessageStatusTypes.SENDING ? (
74+
{message.status === MessageStatusTypes.SENDING ? (
6775
<Time stroke={semantics.chatTextTimestamp} height={16} width={16} {...timeIcon} />
68-
) : lastMessage.status === MessageStatusTypes.RECEIVED &&
76+
) : message.status === MessageStatusTypes.RECEIVED &&
6977
status === MessageDeliveryStatus.READ ? (
7078
<CheckAll stroke={semantics.accentPrimary} height={16} width={16} {...checkAllIcon} />
7179
) : status === MessageDeliveryStatus.DELIVERED ? (
@@ -103,6 +111,12 @@ const useStyles = () => {
103111
lineHeight: primitives.typographyLineHeightNormal,
104112
...text,
105113
},
114+
username: {
115+
color: semantics.textTertiary,
116+
fontSize: primitives.typographyFontSizeSm,
117+
fontWeight: primitives.typographyFontWeightSemiBold,
118+
lineHeight: primitives.typographyLineHeightNormal,
119+
},
106120
});
107121
}, [semantics, text, container]);
108122
};

package/src/components/ChannelPreview/ChannelPreviewMessage.tsx

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import React, { useCallback, useMemo } from 'react';
1+
import React, { useMemo } from 'react';
22
import { StyleSheet, Text, View } from 'react-native';
33

4-
import { DraftMessage, LocalMessage, MessageResponse } from 'stream-chat';
5-
4+
import { ChannelMessagePreview } from './ChannelMessagePreview';
5+
import { ChannelMessagePreviewDeliveryStatus } from './ChannelMessagePreviewDeliveryStatus';
66
import { ChannelPreviewProps } from './ChannelPreview';
77

88
import { ChannelTypingIndicatorPreview } from './ChannelTypingIndicatorPreview';
@@ -20,8 +20,6 @@ import { useTranslationContext } from '../../contexts/translationContext/Transla
2020
import { PollIcon } from '../../icons/PollIcon';
2121
import { primitives } from '../../theme';
2222
import { MessageStatusTypes } from '../../utils/utils';
23-
import { MessagePreview } from '../MessagePreview/MessagePreview';
24-
import { MessagePreviewUserDetails } from '../MessagePreview/MessagePreviewUserDetails';
2523
import { ErrorBadge } from '../ui';
2624

2725
export type ChannelPreviewMessageProps = Pick<ChannelPreviewProps, 'channel'> & {
@@ -53,25 +51,6 @@ export const ChannelPreviewMessage = (props: ChannelPreviewMessageProps) => {
5351
const isFailedMessage =
5452
lastMessage?.status === MessageStatusTypes.FAILED || lastMessage?.type === 'error';
5553

56-
const textStyle = useMemo(() => {
57-
return [styles.subtitle];
58-
}, [styles.subtitle]);
59-
60-
const iconProps = useMemo(() => {
61-
return {
62-
width: 16,
63-
height: 16,
64-
stroke: isMessageDeleted ? semantics.textTertiary : semantics.textSecondary,
65-
};
66-
}, [isMessageDeleted, semantics.textTertiary, semantics.textSecondary]);
67-
68-
const renderMessagePreview = useCallback(
69-
(message: LocalMessage | MessageResponse | DraftMessage) => {
70-
return <MessagePreview message={message} textStyle={textStyle} iconProps={iconProps} />;
71-
},
72-
[textStyle, iconProps],
73-
);
74-
7554
if (usersTyping.length > 0) {
7655
return <ChannelTypingIndicatorPreview channel={channel} usersTyping={usersTyping} />;
7756
}
@@ -80,7 +59,7 @@ export const ChannelPreviewMessage = (props: ChannelPreviewMessageProps) => {
8059
return (
8160
<View style={styles.container}>
8261
<Text style={styles.draftText}>{t('Draft')}:</Text>
83-
{renderMessagePreview(draftMessage)}
62+
<ChannelMessagePreview message={draftMessage} />
8463
</View>
8564
);
8665
}
@@ -115,15 +94,15 @@ export const ChannelPreviewMessage = (props: ChannelPreviewMessageProps) => {
11594
if (channel.data?.name || membersWithoutSelf.length > 1) {
11695
return (
11796
<View style={styles.container}>
118-
<MessagePreviewUserDetails channel={channel} message={lastMessage} />
119-
{renderMessagePreview(lastMessage)}
97+
<ChannelMessagePreviewDeliveryStatus channel={channel} message={lastMessage} />
98+
<ChannelMessagePreview message={lastMessage} />
12099
</View>
121100
);
122101
} else {
123102
return (
124103
<View style={styles.container}>
125-
<MessagePreviewUserDetails channel={channel} message={lastMessage} />
126-
{renderMessagePreview(lastMessage)}
104+
<ChannelMessagePreviewDeliveryStatus channel={channel} message={lastMessage} />
105+
<ChannelMessagePreview message={lastMessage} />
127106
</View>
128107
);
129108
}
Lines changed: 57 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import React from 'react';
1+
import React, { useMemo } from 'react';
22
import { StyleSheet, Text, View } from 'react-native';
33

44
import { useTheme } from '../../contexts/themeContext/ThemeContext';
55
import { useTranslationContext } from '../../contexts/translationContext/TranslationContext';
6-
import { useViewport } from '../../hooks/useViewport';
7-
import { ChatIcon, MessageBubbleEmpty, MessageIcon } from '../../icons';
6+
import { MessageBubbleEmpty } from '../../icons';
7+
import { primitives } from '../../theme';
88

99
export type EmptyStateProps = {
1010
listType?: 'channel' | 'message' | 'threads' | 'default';
@@ -13,78 +13,81 @@ export type EmptyStateProps = {
1313
export const EmptyStateIndicator = ({ listType }: EmptyStateProps) => {
1414
const {
1515
theme: {
16-
colors: { black, grey, grey_gainsboro },
17-
emptyStateIndicator: {
18-
channelContainer,
19-
channelDetails,
20-
channelTitle,
21-
messageContainer,
22-
messageTitle,
23-
},
16+
emptyStateIndicator: { channelContainer, channelTitle, messageContainer, messageTitle },
17+
semantics,
2418
},
2519
} = useTheme();
26-
const { vw } = useViewport();
27-
const width = vw(33);
2820
const { t } = useTranslationContext();
21+
const styles = useStyles();
2922

3023
switch (listType) {
3124
case 'channel':
3225
return (
3326
<View style={[styles.container, channelContainer]}>
34-
<MessageIcon height={width} pathFill={grey_gainsboro} width={width} />
35-
<Text
36-
style={[styles.channelTitle, { color: black }, channelTitle]}
37-
testID='empty-channel-state-title'
38-
>
39-
{t("Let's start chatting!")}
40-
</Text>
41-
<Text
42-
style={[styles.channelDetails, { color: grey, width: vw(66) }, channelDetails]}
43-
testID='empty-channel-state-details'
44-
>
45-
{t('How about sending your first message to a friend?')}
27+
<MessageBubbleEmpty height={27} stroke={semantics.textTertiary} width={25} />
28+
<Text style={[styles.channelTitle, channelTitle]} testID='empty-channel-state-title'>
29+
{t('No conversations yet')}
4630
</Text>
4731
</View>
4832
);
4933
case 'message':
5034
return (
5135
<View style={[styles.container, messageContainer]}>
52-
<ChatIcon height={width} pathFill={grey_gainsboro} width={width} />
53-
<Text style={[styles.messageTitle, { color: grey_gainsboro }, messageTitle]}>
54-
{t('No chats here yet…')}
55-
</Text>
36+
<MessageBubbleEmpty height={27} stroke={semantics.textTertiary} width={25} />
37+
<Text style={[styles.messageTitle, messageTitle]}>{t('No chats here yet…')}</Text>
5638
</View>
5739
);
5840
case 'threads':
5941
return (
60-
<View style={[styles.container]}>
61-
<MessageBubbleEmpty height={width} pathFill={'#B4BBBA'} width={width} />
62-
<Text style={{ color: '#7E828B' }}>{t('No threads here yet')}...</Text>
42+
<View style={styles.container}>
43+
<MessageBubbleEmpty height={27} stroke={semantics.textTertiary} width={25} />
44+
<Text style={styles.threadText}>{t('Reply to a message to start a thread')}</Text>
6345
</View>
6446
);
6547
default:
66-
return <Text style={[{ color: black }, messageContainer]}>No items exist</Text>;
48+
return (
49+
<Text style={[{ color: semantics.textSecondary }, messageContainer]}>No items exist</Text>
50+
);
6751
}
6852
};
6953

70-
const styles = StyleSheet.create({
71-
channelDetails: {
72-
fontSize: 14,
73-
textAlign: 'center',
74-
},
75-
channelTitle: {
76-
fontSize: 16,
77-
paddingBottom: 8,
78-
paddingTop: 16,
79-
},
80-
container: {
81-
alignItems: 'center',
82-
flex: 1,
83-
justifyContent: 'center',
84-
},
85-
messageTitle: {
86-
fontSize: 20,
87-
fontWeight: 'bold',
88-
paddingBottom: 8,
89-
},
90-
});
54+
const useStyles = () => {
55+
const {
56+
theme: { semantics },
57+
} = useTheme();
58+
59+
return useMemo(() => {
60+
return StyleSheet.create({
61+
channelDetails: {
62+
fontSize: 14,
63+
textAlign: 'center',
64+
},
65+
channelTitle: {
66+
color: semantics.textSecondary,
67+
fontSize: primitives.typographyFontSizeMd,
68+
fontWeight: primitives.typographyFontWeightRegular,
69+
lineHeight: primitives.typographyLineHeightNormal,
70+
textAlign: 'center',
71+
paddingVertical: primitives.spacingSm,
72+
},
73+
container: {
74+
alignItems: 'center',
75+
flex: 1,
76+
justifyContent: 'center',
77+
},
78+
messageTitle: {
79+
fontSize: 20,
80+
fontWeight: 'bold',
81+
paddingBottom: 8,
82+
},
83+
threadText: {
84+
color: semantics.textSecondary,
85+
fontSize: primitives.typographyFontSizeMd,
86+
fontWeight: primitives.typographyFontWeightRegular,
87+
lineHeight: primitives.typographyLineHeightNormal,
88+
textAlign: 'center',
89+
paddingVertical: primitives.spacingSm,
90+
},
91+
});
92+
}, [semantics]);
93+
};

0 commit comments

Comments
 (0)