Skip to content

Commit ad8f3fa

Browse files
authored
Merge pull request #689 from GetStream/date-separator-items
date-separator-items
2 parents 585ad5f + 95e3095 commit ad8f3fa

File tree

3 files changed

+93
-56
lines changed

3 files changed

+93
-56
lines changed

src/components/MessageList/MessageList.js

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -230,20 +230,22 @@ class MessageList extends PureComponent {
230230
ref={this.messageList}
231231
>
232232
<MessageListInner
233+
bottomRef={this.bottomRef}
234+
channel={this.props.channel}
235+
client={this.props.client}
236+
DateSeparator={this.props.DateSeparator || this.props.dateSeparator}
237+
disableDateSeparator={this.props.disableDateSeparator}
233238
EmptyStateIndicator={this.props.EmptyStateIndicator}
234-
TypingIndicator={this.props.TypingIndicator}
235-
MessageSystem={this.props.MessageSystem}
236239
HeaderComponent={this.props.HeaderComponent}
237240
headerPosition={this.props.headerPosition}
238-
DateSeparator={this.props.DateSeparator || this.props.dateSeparator}
241+
hideDeletedMessages={this.props.hideDeletedMessages}
239242
messages={this.props.messages}
243+
MessageSystem={this.props.MessageSystem}
240244
noGroupByUser={this.props.noGroupByUser}
241-
threadList={this.props.threadList}
242-
client={this.props.client}
243-
channel={this.props.channel}
244-
read={this.props.read}
245-
bottomRef={this.bottomRef}
246245
onMessageLoadCaptured={this.onMessageLoadCaptured}
246+
read={this.props.read}
247+
threadList={this.props.threadList}
248+
TypingIndicator={this.props.TypingIndicator}
247249
internalInfiniteScrollProps={{
248250
hasMore: this.props.hasMore,
249251
isLoading: this.props.loadingMore,
@@ -256,25 +258,12 @@ class MessageList extends PureComponent {
256258
),
257259
}}
258260
internalMessageProps={{
259-
messageListRect: this.state.messageListRect,
260-
openThread: this.props.openThread,
261-
members: this.props.members,
262-
watchers: this.props.watchers,
263-
channel: this.props.channel,
264-
retrySendMessage: this.props.retrySendMessage,
261+
additionalMessageInputProps: this.props
262+
.additionalMessageInputProps,
265263
addNotification: this.addNotification,
266-
updateMessage: this.props.updateMessage,
267-
removeMessage: this.props.removeMessage,
268-
Message: this.props.Message,
269-
mutes: this.props.mutes,
270-
unsafeHTML: this.props.unsafeHTML,
271264
Attachment: this.props.Attachment,
272265
Avatar: this.props.Avatar,
273-
onMentionsClick: this.props.onMentionsClick,
274-
onMentionsHover: this.props.onMentionsHover,
275-
messageActions: this.props.messageActions,
276-
additionalMessageInputProps: this.props
277-
.additionalMessageInputProps,
266+
channel: this.props.channel,
278267
getFlagMessageSuccessNotification: this.props
279268
.getFlagMessageSuccessNotification,
280269
getFlagMessageErrorNotification: this.props
@@ -285,11 +274,23 @@ class MessageList extends PureComponent {
285274
.getMuteUserErrorNotification,
286275
getPinMessageErrorNotification: this.props
287276
.getPinMessageErrorNotification,
277+
members: this.props.members,
278+
Message: this.props.Message,
279+
messageActions: this.props.messageActions,
280+
messageListRect: this.state.messageListRect,
281+
mutes: this.props.mutes,
282+
onMentionsClick: this.props.onMentionsClick,
283+
onMentionsHover: this.props.onMentionsHover,
284+
openThread: this.props.openThread,
285+
removeMessage: this.props.removeMessage,
286+
retrySendMessage: this.props.retrySendMessage,
287+
unsafeHTML: this.props.unsafeHTML,
288+
updateMessage: this.props.updateMessage,
289+
watchers: this.props.watchers,
288290
pinPermissions: this.props.pinPermissions,
289291
}}
290292
/>
291293
</div>
292-
293294
<div className="str-chat__list-notifications">
294295
{this.state.notifications.map((notification) => (
295296
<CustomNotification
@@ -300,12 +301,10 @@ class MessageList extends PureComponent {
300301
{notification.text}
301302
</CustomNotification>
302303
))}
303-
304304
<ConnectionStatus />
305-
306305
<MessageNotification
307-
showNotification={this.state.newMessagesNotification}
308306
onClick={this.goToNewMessages}
307+
showNotification={this.state.newMessagesNotification}
309308
>
310309
{t('New Messages!')}
311310
</MessageNotification>
@@ -322,6 +321,10 @@ MessageList.propTypes = {
322321
* Defaults to and accepts same props as: [DateSeparator](https://github.com/GetStream/stream-chat-react/blob/master/src/components/DateSeparator.js)
323322
* */
324323
dateSeparator: PropTypes.elementType,
324+
/** Disables the injection of date separator components, defaults to false */
325+
disableDateSeparator: PropTypes.bool,
326+
/** Hides the MessageDeleted components from the list, defaults to false */
327+
hideDeletedMessages: PropTypes.bool,
325328
/** Turn off grouping of messages by user */
326329
noGroupByUser: PropTypes.bool,
327330
/** render HTML instead of markdown. Posting HTML is only allowed server-side */
@@ -407,7 +410,7 @@ MessageList.propTypes = {
407410
* */
408411
TypingIndicator: PropTypes.elementType,
409412
/**
410-
* The UI Indicator to use when MessagerList or ChannelList is empty
413+
* The UI Indicator to use when MessageList or ChannelList is empty
411414
* */
412415
EmptyStateIndicator: PropTypes.elementType,
413416
/**

src/components/MessageList/MessageListInner.js

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
/* eslint-disable sonarjs/cognitive-complexity */
21
/* eslint-disable no-continue */
32
/* eslint-disable sonarjs/no-duplicate-string */
43
import React, { useMemo } from 'react';
@@ -18,6 +17,7 @@ const getLastReceived = (messages) => {
1817
const getReadStates = (messages, read) => {
1918
// create object with empty array for each message id
2019
const readData = {};
20+
2121
Object.values(read).forEach((readState) => {
2222
if (!readState.last_read) return;
2323

@@ -35,36 +35,53 @@ const getReadStates = (messages, read) => {
3535
return readData;
3636
};
3737

38-
const insertDates = (messages, lastRead, userID) => {
38+
const insertDates = (messages, lastRead, userID, hideDeletedMessages) => {
3939
let unread = false;
40+
let lastDateSeparator;
4041
const newMessages = [];
42+
4143
for (let i = 0, l = messages.length; i < l; i += 1) {
4244
const message = messages[i];
45+
46+
if (hideDeletedMessages && message.type === 'deleted') {
47+
continue;
48+
}
49+
4350
if (message.type === 'message.read') {
4451
newMessages.push(message);
4552
continue;
4653
}
54+
4755
const messageDate = message.created_at.toDateString();
4856
let prevMessageDate = messageDate;
57+
4958
if (i > 0) {
5059
prevMessageDate = messages[i - 1].created_at.toDateString();
5160
}
5261

5362
if (!unread) {
5463
unread = lastRead && new Date(lastRead) < message.created_at;
55-
// userId check makes sure New is not shown for current user messages
56-
if (unread && message.user.id !== userID)
64+
65+
// do not show date separator for current user's messages
66+
if (unread && message.user.id !== userID) {
5767
newMessages.push({
5868
type: 'message.date',
5969
date: message.created_at,
6070
unread,
6171
});
72+
}
6273
}
6374

6475
if (
65-
(i === 0 || messageDate !== prevMessageDate) &&
66-
newMessages?.[newMessages.length - 1]?.type !== 'message.date' // prevent two subsequent DateSeparator
76+
(i === 0 ||
77+
messageDate !== prevMessageDate ||
78+
(hideDeletedMessages &&
79+
messages[i - 1]?.type === 'deleted' &&
80+
lastDateSeparator !== messageDate)) &&
81+
newMessages?.[newMessages.length - 1]?.type !== 'message.date' // do not show two date separators in a row
6782
) {
83+
lastDateSeparator = messageDate;
84+
6885
newMessages.push(
6986
{ type: 'message.date', date: message.created_at },
7087
message,
@@ -85,7 +102,7 @@ const insertIntro = (messages, headerPosition) => {
85102
return newMessages;
86103
}
87104

88-
// if no messages, intro get's inserted
105+
// if no messages, intro gets inserted
89106
if (!newMessages.length) {
90107
newMessages.unshift({ type: 'channel.intro' });
91108
return newMessages;
@@ -103,7 +120,7 @@ const insertIntro = (messages, headerPosition) => {
103120
? messages[i + 1].created_at.getTime()
104121
: null;
105122

106-
// headerposition is smaller than message time so comes after;
123+
// header position is smaller than message time so comes after;
107124
if (messageTime < headerPosition) {
108125
// if header position is also smaller than message time continue;
109126
if (nextMessageTime < headerPosition) {
@@ -176,30 +193,47 @@ const getGroupStyles = (
176193

177194
const MessageListInner = (props) => {
178195
const {
179-
EmptyStateIndicator,
180-
MessageSystem,
196+
bottomRef,
197+
client,
198+
channel,
181199
DateSeparator,
200+
disableDateSeparator = false,
201+
EmptyStateIndicator,
182202
HeaderComponent,
183-
TypingIndicator,
184203
headerPosition,
185-
bottomRef,
186-
onMessageLoadCaptured,
204+
hideDeletedMessages = false,
205+
internalInfiniteScrollProps,
206+
internalMessageProps,
187207
messages,
208+
MessageSystem,
188209
noGroupByUser,
189-
client,
190-
threadList,
191-
channel,
210+
onMessageLoadCaptured,
192211
read,
193-
internalMessageProps,
194-
internalInfiniteScrollProps,
212+
threadList,
213+
TypingIndicator,
195214
} = props;
215+
196216
const lastRead = useMemo(() => channel.lastRead(), [channel]);
197217

198218
const enrichedMessages = useMemo(() => {
199-
const messageWithDates = insertDates(messages, lastRead, client.userID);
219+
const messageWithDates =
220+
disableDateSeparator || threadList
221+
? messages
222+
: insertDates(messages, lastRead, client.userID, hideDeletedMessages);
223+
200224
if (HeaderComponent) return insertIntro(messageWithDates, headerPosition);
225+
201226
return messageWithDates;
202-
}, [messages, lastRead, client.userID, HeaderComponent, headerPosition]);
227+
}, [
228+
client.userID,
229+
disableDateSeparator,
230+
HeaderComponent,
231+
headerPosition,
232+
hideDeletedMessages,
233+
lastRead,
234+
messages,
235+
threadList,
236+
]);
203237

204238
const messageGroupStyles = useMemo(
205239
() =>
@@ -233,8 +267,6 @@ const MessageListInner = (props) => {
233267
const elements = useMemo(() => {
234268
return enrichedMessages.map((message) => {
235269
if (message.type === 'message.date') {
236-
if (threadList) return null;
237-
238270
return (
239271
<li key={`${message.date.toISOString()}-i`}>
240272
<DateSeparator date={message.date} unread={message.unread} />
@@ -270,10 +302,10 @@ const MessageListInner = (props) => {
270302
>
271303
<Message
272304
client={client}
273-
message={message}
274305
groupStyles={[groupStyles]} /* TODO: convert to simple string */
275-
readBy={readData[message.id] || []}
276306
lastReceivedId={lastReceivedId}
307+
message={message}
308+
readBy={readData[message.id] || []}
277309
threadList={threadList}
278310
{...internalMessageProps}
279311
/>
@@ -284,12 +316,12 @@ const MessageListInner = (props) => {
284316
return null;
285317
});
286318
}, [
287-
MessageSystem,
288319
client,
289320
enrichedMessages,
290321
internalMessageProps,
291322
lastReceivedId,
292323
messageGroupStyles,
324+
MessageSystem,
293325
onMessageLoadCaptured,
294326
readData,
295327
threadList,
@@ -299,10 +331,10 @@ const MessageListInner = (props) => {
299331

300332
return (
301333
<InfiniteScroll
302-
isReverse
303-
useWindow={false}
304334
className="str-chat__reverse-infinite-scroll"
305335
data-testid="reverse-infinite-scroll"
336+
isReverse
337+
useWindow={false}
306338
{...internalInfiniteScrollProps}
307339
>
308340
<ul className="str-chat__ul">{elements}</ul>

types/index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,8 @@ export interface MessageListProps {
591591
/** Date separator component to render */
592592
dateSeparator?: React.ElementType<DateSeparatorProps>;
593593
DateSeparator?: React.ElementType<DateSeparatorProps>;
594+
disableDateSeparator?: boolean;
595+
hideDeletedMessages?: boolean;
594596
/** Turn off grouping of messages by user */
595597
noGroupByUser?: boolean;
596598
/** Weather its a thread of no. Default - false */

0 commit comments

Comments
 (0)