From 8bfa65987d4044f1c135036af8fea267c89f89d9 Mon Sep 17 00:00:00 2001 From: Patrick He <77468352+he-patrick@users.noreply.github.com> Date: Tue, 6 Aug 2024 09:30:37 -0400 Subject: [PATCH] feat(chat) use the original message ID for processing This is a prerequisite for operations that rely on previous messages, such as reactions. --- modules/API/API.js | 6 +- react/features/breakout-rooms/middleware.ts | 4 +- .../components/AbstractMessageContainer.ts | 4 +- .../chat/components/native/ChatMessage.tsx | 4 +- .../chat/components/web/ChatMessage.tsx | 2 +- .../chat/components/web/ChatMessageGroup.tsx | 2 +- react/features/chat/functions.ts | 2 +- react/features/chat/middleware.ts | 78 +++++++++++-------- react/features/chat/reducer.ts | 6 +- react/features/chat/types.ts | 2 +- 10 files changed, 59 insertions(+), 51 deletions(-) diff --git a/modules/API/API.js b/modules/API/API.js index 47d10e5e4f..d4887e3d7a 100644 --- a/modules/API/API.js +++ b/modules/API/API.js @@ -1338,14 +1338,14 @@ class API { * @returns {void} */ notifyReceivedChatMessage( - { body, id, nick, privateMessage, ts } = {}) { - if (APP.conference.isLocalId(id)) { + { body, from, nick, privateMessage, ts } = {}) { + if (APP.conference.isLocalId(from)) { return; } this._sendEvent({ name: 'incoming-message', - from: id, + from, message: body, nick, privateMessage, diff --git a/react/features/breakout-rooms/middleware.ts b/react/features/breakout-rooms/middleware.ts index 8645c6741c..2e27666a82 100644 --- a/react/features/breakout-rooms/middleware.ts +++ b/react/features/breakout-rooms/middleware.ts @@ -83,12 +83,12 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => { const { messages } = getState()['features/chat']; messages?.forEach(m => { - if (m.messageType === MESSAGE_TYPE_REMOTE && !getParticipantById(getState(), m.id)) { + if (m.messageType === MESSAGE_TYPE_REMOTE && !getParticipantById(getState(), m.participantId)) { const rooms: IRooms = action.rooms; for (const room of Object.values(rooms)) { const participants = room.participants || {}; - const matchedJid = Object.keys(participants).find(jid => jid.endsWith(m.id)); + const matchedJid = Object.keys(participants).find(jid => jid.endsWith(m.participantId)); if (matchedJid) { m.displayName = participants[matchedJid].displayName; diff --git a/react/features/chat/components/AbstractMessageContainer.ts b/react/features/chat/components/AbstractMessageContainer.ts index d5a40b3f5b..19cf8bf60b 100644 --- a/react/features/chat/components/AbstractMessageContainer.ts +++ b/react/features/chat/components/AbstractMessageContainer.ts @@ -36,13 +36,13 @@ export default class AbstractMessageContainer

extends Compo for (let i = 0; i < messagesCount; i++) { const message = this.props.messages[i]; - if (message.id === currentGroupParticipantId) { + if (message.participantId === currentGroupParticipantId) { currentGrouping.push(message); } else { currentGrouping.length && groups.push(currentGrouping); currentGrouping = [ message ]; - currentGroupParticipantId = message.id; + currentGroupParticipantId = message.participantId; } } diff --git a/react/features/chat/components/native/ChatMessage.tsx b/react/features/chat/components/native/ChatMessage.tsx index 952b2944f0..eedad83c92 100644 --- a/react/features/chat/components/native/ChatMessage.tsx +++ b/react/features/chat/components/native/ChatMessage.tsx @@ -113,7 +113,7 @@ class ChatMessage extends Component { { this.props.showAvatar && } @@ -175,7 +175,7 @@ class ChatMessage extends Component { diff --git a/react/features/chat/components/web/ChatMessage.tsx b/react/features/chat/components/web/ChatMessage.tsx index 926902e423..5a36b8e26b 100644 --- a/react/features/chat/components/web/ChatMessage.tsx +++ b/react/features/chat/components/web/ChatMessage.tsx @@ -197,7 +197,7 @@ const ChatMessage = ({ className = { classes.replyButtonContainer }> + participantID = { message.participantId } /> )} diff --git a/react/features/chat/components/web/ChatMessageGroup.tsx b/react/features/chat/components/web/ChatMessageGroup.tsx index b156712e11..8d86bc5fd5 100644 --- a/react/features/chat/components/web/ChatMessageGroup.tsx +++ b/react/features/chat/components/web/ChatMessageGroup.tsx @@ -66,7 +66,7 @@ const ChatMessageGroup = ({ className = '', messages }: IProps) => {

{messages.map((message, i) => ( diff --git a/react/features/chat/functions.ts b/react/features/chat/functions.ts index a4f045cd43..e580a18dd2 100644 --- a/react/features/chat/functions.ts +++ b/react/features/chat/functions.ts @@ -172,7 +172,7 @@ export function getMessageText(message: IMessage) { */ export function getCanReplyToMessage(state: IReduxState, message: IMessage) { const { knocking } = state['features/lobby']; - const participant = getParticipantById(state, message.id); + const participant = getParticipantById(state, message.participantId); return Boolean(participant) && (message.privateMessage || (message.lobbyChat && !knocking)) diff --git a/react/features/chat/middleware.ts b/react/features/chat/middleware.ts index 5490a8fcc7..0c50614dcc 100644 --- a/react/features/chat/middleware.ts +++ b/react/features/chat/middleware.ts @@ -125,7 +125,7 @@ MiddlewareRegistry.register(store => next => action => { store.dispatch(pushReactions(data.reactions)); _handleReceivedMessage(store, { - id: participant.getId(), + participantId: participant.getId(), message: getReactionMessageFromBuffer(data.reactions), privateMessage: false, lobbyChat: false, @@ -137,12 +137,12 @@ MiddlewareRegistry.register(store => next => action => { } case NON_PARTICIPANT_MESSAGE_RECEIVED: { - const { id, json: data } = action; + const { participantId, json: data } = action; if (data?.type === MESSAGE_TYPE_SYSTEM && data.message) { _handleReceivedMessage(store, { displayName: data.displayName ?? i18next.t('chat.systemDisplayName'), - id, + participantId, lobbyChat: false, message: data.message, privateMessage: true, @@ -213,7 +213,7 @@ MiddlewareRegistry.register(store => next => action => { case ADD_REACTION_MESSAGE: { if (localParticipant?.id) { _handleReceivedMessage(store, { - id: localParticipant.id, + participantId: localParticipant.id, message: action.message, privateMessage: false, timestamp: Date.now(), @@ -274,25 +274,30 @@ function _addChatMsgListener(conference: IJitsiConference, store: IStore) { conference.on( JitsiConferenceEvents.MESSAGE_RECEIVED, - // eslint-disable-next-line max-params - (id: string, message: string, timestamp: number, displayName: string, isGuest?: boolean) => { + /* eslint-disable max-params */ + (participantId: string, message: string, timestamp: number, + displayName: string, isGuest: boolean, messageId: string) => { + /* eslint-enable max-params */ _onConferenceMessageReceived(store, { - id: id || displayName, // in case of messages coming from visitors we can have unknown id + // in case of messages coming from visitors we can have unknown id + participantId: participantId || displayName, message, timestamp, displayName, isGuest, + messageId, privateMessage: false }); } ); conference.on( JitsiConferenceEvents.PRIVATE_MESSAGE_RECEIVED, - (id: string, message: string, timestamp: number) => { + (participantId: string, message: string, timestamp: number, messageId: string) => { _onConferenceMessageReceived(store, { - id, + participantId, message, timestamp, + messageId, privateMessage: true }); } @@ -311,25 +316,29 @@ function _addChatMsgListener(conference: IJitsiConference, store: IStore) { * @param {Object} message - The message object. * @returns {void} */ -function _onConferenceMessageReceived(store: IStore, { displayName, id, isGuest, message, timestamp, privateMessage }: { - displayName?: string; id: string; isGuest?: boolean; - message: string; privateMessage: boolean; timestamp: number; }) { +function _onConferenceMessageReceived(store: IStore, + { displayName, isGuest, message, messageId, participantId, privateMessage, timestamp }: { + displayName?: string; isGuest?: boolean; message: string; messageId?: string; + participantId: string; privateMessage: boolean; timestamp: number; } +) { + const isGif = isGifMessage(message); if (isGif) { - _handleGifMessageReceived(store, id, message); + _handleGifMessageReceived(store, participantId, message); if (getGifDisplayMode(store.getState()) === 'tile') { return; } } _handleReceivedMessage(store, { displayName, - id, isGuest, + participantId, message, privateMessage, lobbyChat: false, - timestamp + timestamp, + messageId }, true, isGif); } @@ -337,14 +346,14 @@ function _onConferenceMessageReceived(store: IStore, { displayName, id, isGuest, * Handles a received gif message. * * @param {Object} store - Redux store. - * @param {string} id - Id of the participant that sent the message. + * @param {string} participantId - Id of the participant that sent the message. * @param {string} message - The message sent. * @returns {void} */ -function _handleGifMessageReceived(store: IStore, id: string, message: string) { +function _handleGifMessageReceived(store: IStore, participantId: string, message: string) { const url = message.substring(GIF_PREFIX.length, message.length - 1); - store.dispatch(addGif(id, url)); + store.dispatch(addGif(participantId, url)); } /** @@ -374,7 +383,7 @@ function _handleChatError({ dispatch }: IStore, error: Error) { export function handleLobbyMessageReceived(message: string, participantId: string) { return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => { _handleReceivedMessage({ dispatch, - getState }, { id: participantId, + getState }, { participantId, message, privateMessage: false, lobbyChat: true, @@ -387,18 +396,18 @@ export function handleLobbyMessageReceived(message: string, participantId: strin * Function to get lobby chat user display name. * * @param {Store} state - The Redux store. - * @param {string} id - The knocking participant id. + * @param {string} participantId - The knocking participant id. * @returns {string} */ -function getLobbyChatDisplayName(state: IReduxState, id: string) { +function getLobbyChatDisplayName(state: IReduxState, participantId: string) { const { knockingParticipants } = state['features/lobby']; const { lobbyMessageRecipient } = state['features/chat']; - if (id === lobbyMessageRecipient?.id) { + if (participantId === lobbyMessageRecipient?.id) { return lobbyMessageRecipient.name; } - const knockingParticipant = knockingParticipants.find(p => p.id === id); + const knockingParticipant = knockingParticipants.find(p => p.id === participantId); if (knockingParticipant) { return knockingParticipant.name; @@ -417,9 +426,9 @@ function getLobbyChatDisplayName(state: IReduxState, id: string) { * @returns {void} */ function _handleReceivedMessage({ dispatch, getState }: IStore, - { displayName, id, isGuest, message, privateMessage, timestamp, lobbyChat }: { - displayName?: string; id: string; isGuest?: boolean; lobbyChat: boolean; - message: string; privateMessage: boolean; timestamp: number; }, + { displayName, isGuest, lobbyChat, message, messageId, participantId, privateMessage, timestamp }: { + displayName?: string; isGuest?: boolean; lobbyChat: boolean; message: string; + messageId?: string; participantId: string; privateMessage: boolean; timestamp: number; }, shouldPlaySound = true, isReaction = false ) { @@ -434,12 +443,12 @@ function _handleReceivedMessage({ dispatch, getState }: IStore, // Provide a default for the case when a message is being // backfilled for a participant that has left the conference. - const participant = getParticipantById(state, id) || { local: undefined }; + const participant = getParticipantById(state, participantId) || { local: undefined }; const localParticipant = getLocalParticipant(getState); let displayNameToShow = lobbyChat - ? getLobbyChatDisplayName(state, id) - : displayName || getParticipantDisplayName(state, id); + ? getLobbyChatDisplayName(state, participantId) + : displayName || getParticipantDisplayName(state, participantId); const hasRead = participant.local || isChatOpen; const timestampToDate = timestamp ? new Date(timestamp) : new Date(); const millisecondsTimestamp = timestampToDate.getTime(); @@ -455,13 +464,14 @@ function _handleReceivedMessage({ dispatch, getState }: IStore, dispatch(addMessage({ displayName: displayNameToShow, hasRead, - id, + participantId, messageType: participant.local ? MESSAGE_TYPE_LOCAL : MESSAGE_TYPE_REMOTE, message, privateMessage, lobbyChat, recipient: getParticipantDisplayName(state, localParticipant?.id ?? ''), timestamp: millisecondsTimestamp, + messageId, isReaction })); @@ -477,7 +487,7 @@ function _handleReceivedMessage({ dispatch, getState }: IStore, APP.API.notifyReceivedChatMessage({ body: message, - id, + from: participantId, nick: displayNameToShow, privateMessage, ts: timestamp @@ -512,7 +522,7 @@ function _persistSentPrivateMessage({ dispatch, getState }: IStore, recipientID: dispatch(addMessage({ displayName, hasRead: true, - id: localParticipant.id, + participantId: localParticipant.id, messageType: MESSAGE_TYPE_LOCAL, message, privateMessage: !isLobbyPrivateMessage, @@ -562,7 +572,7 @@ function _shouldSendPrivateMessageTo(state: IReduxState, action: AnyAction) { if (lastMessage.privateMessage) { // We show the notice if the last received message was private. - return lastMessage.id; + return lastMessage.participantId; } // But messages may come rapidly, we want to protect our users from mis-sending a message @@ -577,7 +587,7 @@ function _shouldSendPrivateMessageTo(state: IReduxState, action: AnyAction) { ? recentPrivateMessages[0] : recentPrivateMessages[recentPrivateMessages.length - 1]; if (recentPrivateMessage) { - return recentPrivateMessage.id; + return recentPrivateMessage.participantId; } return undefined; diff --git a/react/features/chat/reducer.ts b/react/features/chat/reducer.ts index d5c63332d8..e050f23396 100644 --- a/react/features/chat/reducer.ts +++ b/react/features/chat/reducer.ts @@ -1,5 +1,3 @@ -import { v4 as uuidv4 } from 'uuid'; - import { ILocalParticipant, IParticipant } from '../base/participants/types'; import ReducerRegistry from '../base/redux/ReducerRegistry'; @@ -48,9 +46,9 @@ ReducerRegistry.register('features/chat', (state = DEFAULT_STATE, ac const newMessage: IMessage = { displayName: action.displayName, error: action.error, - id: action.id, + participantId: action.participantId, isReaction: action.isReaction, - messageId: uuidv4(), + messageId: action.messageId, messageType: action.messageType, message: action.message, privateMessage: action.privateMessage, diff --git a/react/features/chat/types.ts b/react/features/chat/types.ts index a58b289ab3..a50fb312a7 100644 --- a/react/features/chat/types.ts +++ b/react/features/chat/types.ts @@ -5,12 +5,12 @@ import { IStore } from '../app/types'; export interface IMessage { displayName: string; error?: Object; - id: string; isReaction: boolean; lobbyChat: boolean; message: string; messageId: string; messageType: string; + participantId: string; privateMessage: boolean; recipient: string; timestamp: number;