feat(chat) use the original message ID for processing

This is a prerequisite for operations that rely on previous messages, such as reactions.
pull/14980/head jitsi-meet_9661
Patrick He 10 months ago committed by GitHub
parent b1c0cc5322
commit 8bfa65987d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      modules/API/API.js
  2. 4
      react/features/breakout-rooms/middleware.ts
  3. 4
      react/features/chat/components/AbstractMessageContainer.ts
  4. 4
      react/features/chat/components/native/ChatMessage.tsx
  5. 2
      react/features/chat/components/web/ChatMessage.tsx
  6. 2
      react/features/chat/components/web/ChatMessageGroup.tsx
  7. 2
      react/features/chat/functions.ts
  8. 78
      react/features/chat/middleware.ts
  9. 6
      react/features/chat/reducer.ts
  10. 2
      react/features/chat/types.ts

@ -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,

@ -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;

@ -36,13 +36,13 @@ export default class AbstractMessageContainer<P extends IProps, S> 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;
}
}

@ -113,7 +113,7 @@ class ChatMessage extends Component<IChatMessageProps> {
<View style = { styles.avatarWrapper }>
{ this.props.showAvatar && <Avatar
displayName = { message.displayName }
participantId = { message.id }
participantId = { message.participantId }
size = { styles.avatarWrapper.width } />
}
</View>
@ -175,7 +175,7 @@ class ChatMessage extends Component<IChatMessageProps> {
<View style = { styles.replyContainer as ViewStyle }>
<PrivateMessageButton
isLobbyMessage = { lobbyChat }
participantID = { message.id }
participantID = { message.participantId }
reply = { true }
showLabel = { false }
toggledStyles = { styles.replyStyles } />

@ -197,7 +197,7 @@ const ChatMessage = ({
className = { classes.replyButtonContainer }>
<PrivateMessageButton
isLobbyMessage = { message.lobbyChat }
participantID = { message.id } />
participantID = { message.participantId } />
</div>
)}
</div>

@ -66,7 +66,7 @@ const ChatMessageGroup = ({ className = '', messages }: IProps) => {
<div className = { clsx(classes.groupContainer, className) }>
<Avatar
className = { clsx(classes.avatar, 'avatar') }
participantId = { messages[0].id }
participantId = { messages[0].participantId }
size = { 32 } />
<div className = { `${classes.messageGroup} chat-message-group ${className}` }>
{messages.map((message, i) => (

@ -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))

@ -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;

@ -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<IChatState>('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,

@ -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;

Loading…
Cancel
Save