From 32109c72e84e4766e5d9bbd934193e97daa909eb Mon Sep 17 00:00:00 2001 From: Sravan S Date: Wed, 22 Feb 2023 22:12:52 +0900 Subject: [PATCH 1/2] fix: fix not showing newly recived messages We decided not to filter at event handler, instead we filter, clean at reducer --- .../Channel/context/ChannelProvider.tsx | 3 +- .../Channel/context/__test__/utils.spec.js | 57 +++++++++++++++++++ .../context/dux/__tests__/reducers.spec.js | 6 +- .../Channel/context/dux/data.mock.js | 8 +++ .../Channel/context/dux/reducers.js | 26 ++------- .../context/hooks/useHandleChannelEvents.ts | 5 +- src/smart-components/Channel/context/utils.js | 22 +++++++ 7 files changed, 98 insertions(+), 29 deletions(-) create mode 100644 src/smart-components/Channel/context/__test__/utils.spec.js diff --git a/src/smart-components/Channel/context/ChannelProvider.tsx b/src/smart-components/Channel/context/ChannelProvider.tsx index ad66a8625..3906af2c4 100644 --- a/src/smart-components/Channel/context/ChannelProvider.tsx +++ b/src/smart-components/Channel/context/ChannelProvider.tsx @@ -321,8 +321,7 @@ const ChannelProvider: React.FC = (props: ChannelContextPro currentGroupChannel, sdkInit, currentUserId: userId, - hasMoreNext, - disableMarkAsRead + disableMarkAsRead, }, { messagesDispatcher, diff --git a/src/smart-components/Channel/context/__test__/utils.spec.js b/src/smart-components/Channel/context/__test__/utils.spec.js new file mode 100644 index 000000000..6121242f7 --- /dev/null +++ b/src/smart-components/Channel/context/__test__/utils.spec.js @@ -0,0 +1,57 @@ +// test mergeAndSortMessages +// const mergedMessages = [...oldMessages, ...newMessages]; +// const getUniqueListByMessageId = (arr) => getUniqueListBy(arr, 'messageId'); +// const unique = getUniqueListByMessageId(mergedMessages); +// return unique; + +import { mergeAndSortMessages } from "../utils"; + +const oldMessages = [ + { + messageId: 390282401, + createdAt: 390282401, + }, + { + messageId: 390282407, + createdAt: 390282407, + }, +]; + +const messagesToAdd_1 = [ + { + messageId: 390282408, + createdAt: 390282408 + }, + { + messageId: 390282409, + createdAt: 390282409, + }, +]; + +const messagesToAdd_2 = [ + { + messageId: 390282404, + createdAt: 390282404, + }, + { + messageId: 390282405, + createdAt: 390282405, + }, +]; + +describe('mergeAndSortMessages', () => { + it('should append new list of messages to end of list', () => { + const newList = mergeAndSortMessages(oldMessages, messagesToAdd_1); + expect(newList).toEqual([...oldMessages, ...messagesToAdd_1]); + }); + + it('should sort messages by createdAt', () => { + const newList = mergeAndSortMessages(oldMessages, messagesToAdd_2); + expect(newList).toEqual([ + oldMessages[0], + messagesToAdd_2[0], + messagesToAdd_2[1], + oldMessages[1], + ]); + }); +}); diff --git a/src/smart-components/Channel/context/dux/__tests__/reducers.spec.js b/src/smart-components/Channel/context/dux/__tests__/reducers.spec.js index 183bf6c54..9890066cc 100644 --- a/src/smart-components/Channel/context/dux/__tests__/reducers.spec.js +++ b/src/smart-components/Channel/context/dux/__tests__/reducers.spec.js @@ -1,4 +1,8 @@ -import { mockMessage1, generateMockMessage, generateMockChannel } from '../data.mock'; +import { + mockMessage1, + generateMockMessage, + generateMockChannel, +} from '../data.mock'; import * as actionTypes from '../actionTypes'; import reducers from '../reducers'; import initialState from '../initialState'; diff --git a/src/smart-components/Channel/context/dux/data.mock.js b/src/smart-components/Channel/context/dux/data.mock.js index a69e98bff..e4f76d3db 100644 --- a/src/smart-components/Channel/context/dux/data.mock.js +++ b/src/smart-components/Channel/context/dux/data.mock.js @@ -175,6 +175,14 @@ export const mockMessage1 = { "errorCode": 0, threadInfo: null, }; +export const mockMessage2 = { + "messageId": 390292882, + "channelUrl": "sendbird_group_channel_13883929_3dc3bb3af92eded8ff8e5f71de775fe149a32dd6", + "data": "", + "customType": "", + "createdAt": 1582004961440, + "updatedAt": 0, +}; export const frozenChannel = { "url": "sendbird_group_channel_204619489_3df4fd3d2feeef8bb0775e57950784a92fa3184c", diff --git a/src/smart-components/Channel/context/dux/reducers.js b/src/smart-components/Channel/context/dux/reducers.js index b74e1a1e8..e7947e464 100644 --- a/src/smart-components/Channel/context/dux/reducers.js +++ b/src/smart-components/Channel/context/dux/reducers.js @@ -3,7 +3,7 @@ import format from 'date-fns/format'; import * as actionTypes from './actionTypes'; import compareIds from '../../../../utils/compareIds'; import { PREV_RESULT_SIZE, NEXT_RESULT_SIZE } from '../const'; -import { passUnsuccessfullMessages } from '../utils'; +import { passUnsuccessfullMessages, mergeAndSortMessages } from '../utils'; import { filterMessageListParams, getSendingMessageStatus } from '../../../../utils'; const { @@ -111,32 +111,14 @@ export default function reducer(state, action) { const hasMoreNext = messages && messages.length === NEXT_RESULT_SIZE + 1; const latestMessageTimeStamp = getLatestMessageTimeStamp(messages); - // Remove duplicated messages - const duplicatedMessageIds = []; - const updatedOldMessages = state.allMessages.map((msg) => { - const duplicatedMessage = messages.find(({ messageId }) => ( - compareIds(messageId, msg.messageId) - )); - if (!duplicatedMessage) { - return msg; - } - duplicatedMessageIds.push(duplicatedMessage.messageId); - return (duplicatedMessage.updatedAt > msg.updatedAt) ? duplicatedMessage : msg; - }); - const filteredNewMessages = (duplicatedMessageIds.length > 0) - ? messages.filter((msg) => ( - !duplicatedMessageIds.find((messageId) => compareIds(messageId, msg.messageId)) - )) - : messages; + // sort ~ + const sortedMessages = mergeAndSortMessages(state.allMessages, messages); return { ...state, hasMoreNext, latestMessageTimeStamp, - allMessages: [ - ...updatedOldMessages, - ...filteredNewMessages, - ], + allMessages: sortedMessages, }; } case actionTypes.FETCH_INITIAL_MESSAGES_FAILURE: diff --git a/src/smart-components/Channel/context/hooks/useHandleChannelEvents.ts b/src/smart-components/Channel/context/hooks/useHandleChannelEvents.ts index b571949e4..990b9cdc1 100644 --- a/src/smart-components/Channel/context/hooks/useHandleChannelEvents.ts +++ b/src/smart-components/Channel/context/hooks/useHandleChannelEvents.ts @@ -19,7 +19,6 @@ import * as messageActions from '../dux/actionTypes'; */ interface DynamicParams { sdkInit: boolean; - hasMoreNext: boolean; currentUserId: string; disableMarkAsRead: boolean; currentGroupChannel: GroupChannel; @@ -34,7 +33,6 @@ interface StaticParams { function useHandleChannelEvents({ sdkInit, - hasMoreNext, currentUserId, disableMarkAsRead, currentGroupChannel, @@ -51,8 +49,7 @@ function useHandleChannelEvents({ if (channelUrl && sdkInit) { const channelHandler: GroupChannelHandler = { onMessageReceived: (channel, message) => { - // Do not update when hasMoreNext - if (compareIds(channel?.url, channelUrl) && !hasMoreNext) { + if (compareIds(channel?.url, channelUrl)) { let scrollToEnd = false; try { const { current } = scrollRef; diff --git a/src/smart-components/Channel/context/utils.js b/src/smart-components/Channel/context/utils.js index d33667fad..f00fd6a69 100644 --- a/src/smart-components/Channel/context/utils.js +++ b/src/smart-components/Channel/context/utils.js @@ -4,6 +4,7 @@ import * as topics from '../../../lib/pubSub/topics'; import { getSendingMessageStatus, isReadMessage } from '../../../utils'; import { OutgoingMessageStates } from '../../../utils/exports/getOutgoingMessageState'; +import compareIds from '../../../utils/compareIds'; const UNDEFINED = 'undefined'; const { SUCCEEDED, FAILED, PENDING } = getSendingMessageStatus(); @@ -186,6 +187,27 @@ export const getNicknamesMapFromMembers = (members = []) => { return nicknamesMap; }; +const getUniqueListBy = (arr, key) => [...new Map(arr.map((item) => [item[key], item])).values()]; +const getUniqueListByMessageId = (arr) => getUniqueListBy(arr, 'messageId'); +const sortByCreatedAt = (messages) => messages.sort((a, b) => a.createdAt - b.createdAt); + +export const mergeAndSortMessages = (oldMessages, newMessages) => { + const lastOldMessage = oldMessages[oldMessages.length - 1]; + const firstNewMessage = newMessages[0]; + // If the last message of oldMessages is older than the first message of newMessages, + // then we can safely append newMessages to oldMessages. + if (lastOldMessage?.createdAt < firstNewMessage?.createdAt) { + return [...oldMessages, ...newMessages]; + } + + // todo: optimize this + // If the last message of oldMessages is newer than the first message of newMessages, + // then we need to merge the two arrays and sort them by createdAt. + const mergedMessages = [...oldMessages, ...newMessages]; + const unique = getUniqueListByMessageId(mergedMessages); + return sortByCreatedAt(unique); +}; + export const getMessageCreatedAt = (message) => format(message.createdAt, 'p'); export const isSameGroup = (message, comparingMessage, currentChannel) => { From 9017d3cca919f5ee7ef65fe50172c93ef758f678 Mon Sep 17 00:00:00 2001 From: Sravan S Date: Wed, 22 Feb 2023 22:17:38 +0900 Subject: [PATCH 2/2] fix: lint --- src/smart-components/Channel/context/utils.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/smart-components/Channel/context/utils.js b/src/smart-components/Channel/context/utils.js index f00fd6a69..47c17275c 100644 --- a/src/smart-components/Channel/context/utils.js +++ b/src/smart-components/Channel/context/utils.js @@ -4,7 +4,6 @@ import * as topics from '../../../lib/pubSub/topics'; import { getSendingMessageStatus, isReadMessage } from '../../../utils'; import { OutgoingMessageStates } from '../../../utils/exports/getOutgoingMessageState'; -import compareIds from '../../../utils/compareIds'; const UNDEFINED = 'undefined'; const { SUCCEEDED, FAILED, PENDING } = getSendingMessageStatus();