Skip to content

Commit 34d8fde

Browse files
committed
feat: inline unread separator and notification redesign
1 parent 2028cb5 commit 34d8fde

File tree

19 files changed

+91
-30
lines changed

19 files changed

+91
-30
lines changed

package/src/components/Message/MessageSimple/MessageWrapper.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ export const MessageWrapper = React.memo((props: MessageWrapperProps) => {
136136
)}
137137
{showUnreadUnderlay && (
138138
<View style={styles.unreadUnderlayContainer}>
139-
<InlineUnreadIndicator />
139+
<InlineUnreadIndicator unreadCount={unread_messages} />
140140
</View>
141141
)}
142142
</View>

package/src/components/MessageList/InlineUnreadIndicator.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,20 @@ import { useTheme } from '../../contexts/themeContext/ThemeContext';
55
import { useTranslationContext } from '../../contexts/translationContext/TranslationContext';
66
import { primitives } from '../../theme';
77

8-
export const InlineUnreadIndicator = () => {
8+
export type InlineUnreadIndicatorProps = {
9+
unreadCount?: number;
10+
};
11+
12+
export const InlineUnreadIndicator = (props: InlineUnreadIndicatorProps) => {
13+
const { unreadCount } = props;
914
const styles = useStyles();
1015
const { t } = useTranslationContext();
1116

1217
return (
1318
<View accessibilityLabel='Inline unread indicator' style={styles.container}>
14-
<Text style={styles.text}>{t('Unread Messages')}</Text>
19+
<Text style={styles.text}>
20+
{unreadCount ? t('{{count}} new messages', { count: unreadCount }) : t('Unread Messages')}
21+
</Text>
1522
</View>
1623
);
1724
};

package/src/components/MessageList/MessageFlashList.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import { mergeThemes, useTheme } from '../../contexts/themeContext/ThemeContext'
5353
import { ThreadContextValue, useThreadContext } from '../../contexts/threadContext/ThreadContext';
5454

5555
import { useStableCallback, useStateStore } from '../../hooks';
56+
import { ChannelUnreadStateStoreType } from '../../state-store/channel-unread-state';
5657
import { MessageInputHeightState } from '../../state-store/message-input-height-store';
5758
import { primitives } from '../../theme';
5859
import { MessageWrapper } from '../Message/MessageSimple/MessageWrapper';
@@ -104,6 +105,10 @@ const messageInputHeightStoreSelector = (state: MessageInputHeightState) => ({
104105
height: state.height,
105106
});
106107

108+
const channelUnreadStateStoreSelector = (state: ChannelUnreadStateStoreType) => ({
109+
unread_messages: state.channelUnreadState?.unread_messages,
110+
});
111+
107112
type MessageFlashListPropsWithContext = Pick<
108113
AttachmentPickerContextValue,
109114
'closePicker' | 'attachmentPickerStore'
@@ -317,6 +322,11 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
317322
messageInputHeightStoreSelector,
318323
);
319324

325+
const { unread_messages } = useStateStore(
326+
channelUnreadStateStore.state,
327+
channelUnreadStateStoreSelector,
328+
);
329+
320330
const [hasMoved, setHasMoved] = useState(false);
321331
const [scrollToBottomButtonVisible, setScrollToBottomButtonVisible] = useState(false);
322332
const [isUnreadNotificationOpen, setIsUnreadNotificationOpen] = useState<boolean>(false);
@@ -1094,13 +1104,16 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
10941104
<ScrollToBottomButton
10951105
onPress={goToNewMessages}
10961106
showNotification={scrollToBottomButtonVisible}
1097-
unreadCount={threadList ? 0 : channel?.countUnread()}
1107+
unreadCount={threadList ? 0 : unread_messages}
10981108
/>
10991109
</Animated.View>
11001110
<NetworkDownIndicator />
11011111
{isUnreadNotificationOpen && !threadList ? (
11021112
<View style={styles.unreadMessagesNotificationContainer}>
1103-
<UnreadMessagesNotification onCloseHandler={onUnreadNotificationClose} />
1113+
<UnreadMessagesNotification
1114+
onCloseHandler={onUnreadNotificationClose}
1115+
unreadCount={unread_messages}
1116+
/>
11041117
</View>
11051118
) : null}
11061119
</View>

package/src/components/MessageList/MessageList.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ import { ThreadContextValue, useThreadContext } from '../../contexts/threadConte
6666
import { useStableCallback } from '../../hooks';
6767
import { useStateStore } from '../../hooks/useStateStore';
6868
import { bumpOverlayLayoutRevision } from '../../state-store';
69+
import { ChannelUnreadStateStoreType } from '../../state-store/channel-unread-state';
6970
import { MessageInputHeightState } from '../../state-store/message-input-height-store';
7071
import { primitives } from '../../theme';
7172
import { MessageWrapper } from '../Message/MessageSimple/MessageWrapper';
@@ -304,6 +305,10 @@ const messageInputHeightStoreSelector = (state: MessageInputHeightState) => ({
304305
height: state.height,
305306
});
306307

308+
const channelUnreadStateStoreSelector = (state: ChannelUnreadStateStoreType) => ({
309+
unread_messages: state.channelUnreadState?.unread_messages,
310+
});
311+
307312
/**
308313
* The message list component renders a list of messages. It consumes the following contexts:
309314
*
@@ -375,6 +380,10 @@ const MessageListWithContext = (props: MessageListPropsWithContext) => {
375380
messageInputHeightStore.store,
376381
messageInputHeightStoreSelector,
377382
);
383+
const { unread_messages } = useStateStore(
384+
channelUnreadStateStore.state,
385+
channelUnreadStateStoreSelector,
386+
);
378387

379388
const myMessageThemeString = useMemo(() => JSON.stringify(myMessageTheme), [myMessageTheme]);
380389

@@ -1319,15 +1328,18 @@ const MessageListWithContext = (props: MessageListPropsWithContext) => {
13191328
<ScrollToBottomButton
13201329
onPress={goToNewMessages}
13211330
showNotification={scrollToBottomButtonVisible}
1322-
unreadCount={threadList ? 0 : channel?.countUnread()}
1331+
unreadCount={threadList ? 0 : unread_messages}
13231332
/>
13241333
</Animated.View>
13251334
) : null}
13261335

13271336
<NetworkDownIndicator />
13281337
{isUnreadNotificationOpen && !threadList ? (
13291338
<View style={styles.unreadMessagesNotificationContainer}>
1330-
<UnreadMessagesNotification onCloseHandler={onUnreadNotificationClose} />
1339+
<UnreadMessagesNotification
1340+
onCloseHandler={onUnreadNotificationClose}
1341+
unreadCount={unread_messages}
1342+
/>
13311343
</View>
13321344
) : null}
13331345
</View>

package/src/components/MessageList/UnreadMessagesNotification.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@ export type UnreadMessagesNotificationProps = {
1818
* Callback to handle the press event
1919
*/
2020
onPressHandler?: () => Promise<void>;
21+
/**
22+
* Unread count
23+
*/
24+
unreadCount?: number;
2125
};
2226

2327
export const UnreadMessagesNotification = (props: UnreadMessagesNotificationProps) => {
24-
const { onCloseHandler, onPressHandler } = props;
28+
const { onCloseHandler, onPressHandler, unreadCount } = props;
2529
const { t } = useTranslationContext();
2630
const {
2731
channelUnreadStateStore,
@@ -60,7 +64,7 @@ export const UnreadMessagesNotification = (props: UnreadMessagesNotificationProp
6064
variant='secondary'
6165
type='ghost'
6266
LeadingIcon={ArrowUp}
63-
label={t('Unread Messages')}
67+
label={unreadCount ? t('{{count}} unread', { count: unreadCount }) : t('Unread Messages')}
6468
onPress={handleOnPress}
6569
size='md'
6670
/>

package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,12 +1035,9 @@ exports[`Thread should match thread snapshot 1`] = `
10351035
>
10361036
<View
10371037
style={
1038-
[
1039-
{
1040-
"paddingVertical": 8,
1041-
},
1042-
{},
1043-
]
1038+
{
1039+
"paddingVertical": 8,
1040+
}
10441041
}
10451042
>
10461043
<View
@@ -1834,7 +1831,7 @@ exports[`Thread should match thread snapshot 1`] = `
18341831
"left": 0,
18351832
"position": "absolute",
18361833
"right": 0,
1837-
"top": 8,
1834+
"top": 16,
18381835
}
18391836
}
18401837
/>

package/src/contexts/messagesContext/MessagesContext.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ import type {
1212
MessageResponse,
1313
} from 'stream-chat';
1414

15-
import type { PollContentProps, StreamingMessageViewProps } from '../../components';
15+
import type {
16+
InlineUnreadIndicatorProps,
17+
PollContentProps,
18+
StreamingMessageViewProps,
19+
} from '../../components';
1620
import type { AttachmentProps } from '../../components/Attachment/Attachment';
1721
import type { AudioAttachmentProps } from '../../components/Attachment/Audio';
1822
import type { FileAttachmentProps } from '../../components/Attachment/FileAttachment';
@@ -181,7 +185,7 @@ export type MessagesContextValue = Pick<MessageContextValue, 'isMessageAIGenerat
181185
* UI component for InlineUnreadIndicator
182186
* Defaults to: [InlineUnreadIndicator](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/MessageList/InlineUnreadIndicator.tsx)
183187
**/
184-
InlineUnreadIndicator: React.ComponentType;
188+
InlineUnreadIndicator: React.ComponentType<InlineUnreadIndicatorProps>;
185189

186190
Message: React.ComponentType<MessageProps>;
187191
/**

package/src/i18n/en.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,5 +200,7 @@
200200
"Unmute Group": "Unmute Group",
201201
"{{memberCount}} members, {{onlineCount}} online_one": "{{memberCount}} member, {{onlineCount}} online",
202202
"{{memberCount}} members, {{onlineCount}} online_other": "{{memberCount}} members, {{onlineCount}} online",
203-
"{{memberCount}} members, {{onlineCount}} online_many": "{{memberCount}} members, {{onlineCount}} online"
203+
"{{memberCount}} members, {{onlineCount}} online_many": "{{memberCount}} members, {{onlineCount}} online",
204+
"{{count}} unread": "{{count}} unread",
205+
"{{count}} new messages": "{{count}} new messages"
204206
}

package/src/i18n/es.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,5 +200,7 @@
200200
"Unmute Group": "Activar sonido del grupo",
201201
"{{memberCount}} members, {{onlineCount}} online_one": "{{memberCount}} miembro, {{onlineCount}} en línea",
202202
"{{memberCount}} members, {{onlineCount}} online_other": "{{memberCount}} miembros, {{onlineCount}} en línea",
203-
"{{memberCount}} members, {{onlineCount}} online_many": "{{memberCount}} miembros, {{onlineCount}} en línea"
203+
"{{memberCount}} members, {{onlineCount}} online_many": "{{memberCount}} miembros, {{onlineCount}} en línea",
204+
"{{count}} unread": "{{count}} no leídos",
205+
"{{count}} new messages": "{{count}} nuevos mensajes"
204206
}

package/src/i18n/fr.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,5 +200,7 @@
200200
"Unmute Group": "Rétablir le son du groupe",
201201
"{{memberCount}} members, {{onlineCount}} online_one": "{{memberCount}} membre, {{onlineCount}} en ligne",
202202
"{{memberCount}} members, {{onlineCount}} online_other": "{{memberCount}} membres, {{onlineCount}} en ligne",
203-
"{{memberCount}} members, {{onlineCount}} online_many": "{{memberCount}} membres, {{onlineCount}} en ligne"
203+
"{{memberCount}} members, {{onlineCount}} online_many": "{{memberCount}} membres, {{onlineCount}} en ligne",
204+
"{{count}} unread": "{{count}} non lus",
205+
"{{count}} new messages": "{{count}} nouveaux messages"
204206
}

0 commit comments

Comments
 (0)