diff --git a/JitsiConference.js b/JitsiConference.js index d4ada0be6a..db089b2f04 100644 --- a/JitsiConference.js +++ b/JitsiConference.js @@ -970,6 +970,18 @@ JitsiConference.prototype.sendTextMessage = function(message, elementName = 'bod } }; +/** + * Sends a reaction to the other participants in the conference + * @param reaction the reaction. + * @param messageId the ID of the message to attach the reaction to. + * @param receiverId the intended recipient, if the message is private. + */ +JitsiConference.prototype.sendReaction = function(reaction, messageId, receiverId) { + if (this.room) { + this.room.sendReaction(reaction, messageId, receiverId); + } +}; + /** * Send private text message to another participant of the conference * @param id the id of the participant to send a private message. diff --git a/JitsiConferenceEventManager.js b/JitsiConferenceEventManager.js index 5180316027..33dc341d68 100644 --- a/JitsiConferenceEventManager.js +++ b/JitsiConferenceEventManager.js @@ -376,6 +376,16 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() { participantId, txt, ts, nick, isGuest, messageId); }); + chatRoom.addListener( + XMPPEvents.REACTION_RECEIVED, + + (jid, reactionList, messageId) => { + + conference.eventEmitter.emit( + JitsiConferenceEvents.REACTION_RECEIVED, + jid, reactionList, messageId); + }); + chatRoom.addListener( XMPPEvents.PRIVATE_MESSAGE_RECEIVED, diff --git a/JitsiConferenceEvents.ts b/JitsiConferenceEvents.ts index be058aa42e..690ce64a00 100644 --- a/JitsiConferenceEvents.ts +++ b/JitsiConferenceEvents.ts @@ -284,6 +284,11 @@ export enum JitsiConferenceEvents { */ MESSAGE_RECEIVED = 'conference.messageReceived', + /** + * New reaction was received. + */ + REACTION_RECEIVED = 'conference.reactionReceived', + /** * Event fired when the conference metadata is updated. */ diff --git a/modules/xmpp/ChatRoom.js b/modules/xmpp/ChatRoom.js index 57bace4a09..0cdf7bfc39 100644 --- a/modules/xmpp/ChatRoom.js +++ b/modules/xmpp/ChatRoom.js @@ -962,6 +962,26 @@ export default class ChatRoom extends Listenable { this.eventEmitter.emit(XMPPEvents.SENDING_CHAT_MESSAGE, message); } + /** + * Sends a reaction message to the other participants in the conference. + * @param {string} reaction - The reaction being sent. + * @param {string} messageId - The id of the message being sent. + * @param {string} receiverId - The receiver of the message if it is private. + */ + sendReaction(reaction, messageId, receiverId) { + // Adds the 'to' attribute depending on if the message is private or not. + const msg = receiverId ? $msg({ to: `${this.roomjid}/${receiverId}`, + type: 'chat' }) : $msg({ to: this.roomjid, + type: 'groupchat' }); + + msg.c('reactions', { id: messageId, + xmlns: 'urn:xmpp:reactions:0' }) + .c('reaction', {}, reaction) + .up().c('store', { xmlns: 'urn:xmpp:hints' }); + + this.connection.send(msg); + } + /* eslint-disable max-params */ /** * Send private text message to another participant of the conference @@ -1144,6 +1164,24 @@ export default class ChatRoom extends Listenable { return true; } + const reactions = $(msg).find('>[xmlns="urn:xmpp:reactions:0"]>reaction'); + + if (reactions.length > 0) { + const messageId = $(msg).find('>[xmlns="urn:xmpp:reactions:0"]').attr('id'); + const reactionList = []; + + reactions.each((_, reactionElem) => { + const reaction = $(reactionElem).text(); + + reactionList.push(reaction); + }); + + this.eventEmitter.emit(XMPPEvents.REACTION_RECEIVED, from, reactionList, messageId); + + return true; + } + + const txt = $(msg).find('>body').text(); const subject = $(msg).find('>subject'); diff --git a/service/xmpp/XMPPEvents.ts b/service/xmpp/XMPPEvents.ts index c20702802c..1c61c54950 100644 --- a/service/xmpp/XMPPEvents.ts +++ b/service/xmpp/XMPPEvents.ts @@ -122,6 +122,10 @@ export enum XMPPEvents { // received. MESSAGE_RECEIVED = 'xmpp.message_received', + // Designates an event indicating that a reaction XMPP message in the MUC + // was received. + REACTION_RECEIVED = "xmpp.reaction_received", + // Designates an event indicating that an invite XMPP message in the MUC was // received. INVITE_MESSAGE_RECEIVED = 'xmpp.invite_message_received',