From 3e69be4ab8135df508c6cb5a177ebe4bccfe25a7 Mon Sep 17 00:00:00 2001 From: awlui Date: Wed, 1 May 2024 11:49:45 -0700 Subject: [PATCH 1/2] [APP-7066] - consider local send status messages as current users' --- src/index.ts | 2 + .../MessageList/getMessagePartsInfo.ts | 5 +- .../components/MessageList/index.tsx | 1 + src/ui/MessageContent/index.tsx | 6 +-- src/utils/messages.ts | 51 ++++++++++++++----- 5 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/index.ts b/src/index.ts index 14dd7e661..40d3210b8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,3 +23,5 @@ export { default as useSendbirdStateContext } from './hooks/useSendbirdStateCont // Public enum included in AppProps export { TypingIndicatorType } from './types'; + +export { getIsByMe } from "./utils/messages"; diff --git a/src/modules/GroupChannel/components/MessageList/getMessagePartsInfo.ts b/src/modules/GroupChannel/components/MessageList/getMessagePartsInfo.ts index 45676f3ab..ff224f1b9 100644 --- a/src/modules/GroupChannel/components/MessageList/getMessagePartsInfo.ts +++ b/src/modules/GroupChannel/components/MessageList/getMessagePartsInfo.ts @@ -30,11 +30,12 @@ export const getMessagePartsInfo = ({ currentMessage = null, currentChannel = null, replyType = '', -}: GetMessagePartsInfoProps): OutPuts => { + currentUserId = undefined +}: GetMessagePartsInfoProps & { currentUserId?: string }): OutPuts => { const previousMessage = allMessages[currentIndex - 1]; const nextMessage = allMessages[currentIndex + 1]; const [chainTop, chainBottom] = isMessageGroupingEnabled - ? compareMessagesForGrouping(previousMessage, currentMessage, nextMessage, currentChannel, (replyType as ReplyType)) + ? compareMessagesForGrouping(previousMessage, currentMessage, nextMessage, currentChannel, (replyType as ReplyType), currentUserId) : [false, false]; const previousMessageCreatedAt = previousMessage?.createdAt; const currentCreatedAt = currentMessage.createdAt; diff --git a/src/modules/GroupChannel/components/MessageList/index.tsx b/src/modules/GroupChannel/components/MessageList/index.tsx index 3929d215b..d32263ff7 100644 --- a/src/modules/GroupChannel/components/MessageList/index.tsx +++ b/src/modules/GroupChannel/components/MessageList/index.tsx @@ -266,6 +266,7 @@ export const MessageList = ({ currentIndex: idx, currentMessage: message as CoreMessageType, currentChannel, + currentUserId: store.config.userId }); const isOutgoingMessage = isSendableMessage(message) && message.sender.userId === store.config.userId; return ( diff --git a/src/ui/MessageContent/index.tsx b/src/ui/MessageContent/index.tsx index 15c9d979d..f3bd22092 100644 --- a/src/ui/MessageContent/index.tsx +++ b/src/ui/MessageContent/index.tsx @@ -46,6 +46,7 @@ import MessageFeedbackModal from '../MessageFeedbackModal'; import { SbFeedbackStatus } from './types'; import MessageFeedbackFailedModal from '../MessageFeedbackFailedModal'; import { MobileBottomSheetProps } from '../MobileMenu/types'; +import { getIsByMe } from '../../utils/messages'; export interface MessageContentProps { className?: string | Array; @@ -162,9 +163,8 @@ export default function MessageContent(props: MessageContentProps): ReactElement const { stringSet } = useContext(LocalizationContext); - const isByMe = (userId === (message as SendableMessageType)?.sender?.userId) - || ((message as SendableMessageType)?.sendingStatus === 'pending') - || ((message as SendableMessageType)?.sendingStatus === 'failed'); + + const isByMe = getIsByMe(userId, message); const isByMeClassName = isByMe ? 'outgoing' : 'incoming'; const chainTopClassName = chainTop ? 'chain-top' : ''; const isReactionEnabledInChannel = isReactionEnabled && !channel?.isEphemeral; diff --git a/src/utils/messages.ts b/src/utils/messages.ts index 36b108d0e..abce18eca 100644 --- a/src/utils/messages.ts +++ b/src/utils/messages.ts @@ -4,7 +4,7 @@ import format from 'date-fns/format'; import { ReplyType } from '../types'; import type { CoreMessageType } from '.'; -import { isReadMessage } from '.'; +import { isReadMessage, isSendableMessage } from '.'; /** * exported, should be backward compatible @@ -16,6 +16,7 @@ export const compareMessagesForGrouping = ( nextMessage: CoreMessageType, currentChannel?: GroupChannel, replyType?: ReplyType, + currentUserId?: string, ) => { if (!currentChannel || (currentChannel as GroupChannel).channelType !== 'group') { return [ @@ -30,18 +31,43 @@ export const compareMessagesForGrouping = ( const sendingStatus = (currMessage as UserMessage)?.sendingStatus || ''; const isAcceptable = sendingStatus !== 'failed'; return [ - isSameGroup(prevMessage, currMessage, currentChannel) && isAcceptable, - isSameGroup(currMessage, nextMessage, currentChannel) && isAcceptable, + isSameGroup(prevMessage, currMessage, currentUserId) && isAcceptable, + isSameGroup(currMessage, nextMessage, currentUserId) && isAcceptable, ]; }; export const getMessageCreatedAt = (message: BaseMessage) => format(message.createdAt, 'p'); +// Group current user's messages together. The current user's messages +// may not have their userId on it, and if not, we assume that messages w/ a +// local send status is the current user's as well. +// Given the above is true, group by timestamp +export const areBothFromMyUserAndInSameGroup = ( + message: CoreMessageType, + comparingMessage: CoreMessageType, + currentUserId?: string +) => { + if (!currentUserId || !message.createdAt || !comparingMessage.createdAt) return false; + + const isFirstMessageByMe = getIsByMe(currentUserId, message); + const isSecondMessageByMe = getIsByMe(currentUserId, comparingMessage); + + if (isFirstMessageByMe && isSecondMessageByMe) { + return getMessageCreatedAt(message) === getMessageCreatedAt(comparingMessage); + } + + return false; +} + export const isSameGroup = ( message: CoreMessageType, comparingMessage: CoreMessageType, - currentChannel?: GroupChannel, + currentUserId?: string ) => { + if (areBothFromMyUserAndInSameGroup(message, comparingMessage, currentUserId)) { + return true; + } + if ( !( message @@ -61,16 +87,6 @@ export const isSameGroup = ( return false; } - // group pending messages with any message type other than failed - // Given the above is true, group by timestamp and sender id - if ([message.sendingStatus, comparingMessage.sendingStatus].includes(SendingStatus.PENDING) && - ![message.sendingStatus, comparingMessage.sendingStatus].includes(SendingStatus.FAILED)) { - return ( - message?.sender?.userId === comparingMessage?.sender?.userId - && getMessageCreatedAt(message) === getMessageCreatedAt(comparingMessage) - ); - } - return ( message?.sendingStatus === comparingMessage?.sendingStatus && message?.sender?.userId === comparingMessage?.sender?.userId @@ -78,6 +94,13 @@ export const isSameGroup = ( ); }; +export const getIsByMe = (userId: string, message: BaseMessage) => { + if (!isSendableMessage(message) || !userId) return false; + const messageIsLocalType = [SendingStatus.FAILED, SendingStatus.PENDING].includes(message.sendingStatus); + + return userId === message.sender.userId || messageIsLocalType; +} + export default { compareMessagesForGrouping, getMessageCreatedAt, From c83470d8a7b8a17a95bed27be74867527c6a59c3 Mon Sep 17 00:00:00 2001 From: awlui Date: Wed, 1 May 2024 13:10:07 -0700 Subject: [PATCH 2/2] pr fb --- .../GroupChannel/components/MessageList/getMessagePartsInfo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/GroupChannel/components/MessageList/getMessagePartsInfo.ts b/src/modules/GroupChannel/components/MessageList/getMessagePartsInfo.ts index ff224f1b9..5658f34bf 100644 --- a/src/modules/GroupChannel/components/MessageList/getMessagePartsInfo.ts +++ b/src/modules/GroupChannel/components/MessageList/getMessagePartsInfo.ts @@ -30,7 +30,7 @@ export const getMessagePartsInfo = ({ currentMessage = null, currentChannel = null, replyType = '', - currentUserId = undefined + currentUserId }: GetMessagePartsInfoProps & { currentUserId?: string }): OutPuts => { const previousMessage = allMessages[currentIndex - 1]; const nextMessage = allMessages[currentIndex + 1];