diff --git a/app/ui-utils/client/lib/MessageAction.js b/app/ui-utils/client/lib/MessageAction.js index 141cfe3557422..5b22ccc55e61a 100644 --- a/app/ui-utils/client/lib/MessageAction.js +++ b/app/ui-utils/client/lib/MessageAction.js @@ -8,7 +8,9 @@ import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; import { ReactiveVar } from 'meteor/reactive-var'; import { Tracker } from 'meteor/tracker'; import { Session } from 'meteor/session'; +import { HTML } from 'meteor/htmljs'; +import { createTemplateForComponent } from '../../../../client/reactAdapters'; import { messageArgs } from './messageArgs'; import { roomTypes, canDeleteMessage } from '../../../utils/client'; import { Messages, Rooms, Subscriptions } from '../../../models/client'; @@ -355,4 +357,26 @@ Meteor.startup(async function() { order: 17, group: 'menu', }); + + MessageAction.addButton({ + id: 'reaction-list', + icon: 'emoji', + label: 'Reactions', + context: ['message', 'message-mobile', 'threads'], + action(_, roomInstance) { + const { msg: { reactions } } = messageArgs(this); + + modal.open({ + template: createTemplateForComponent('reactionList', () => import('./ReactionListContent'), { + renderContainerView: () => HTML.DIV({ style: 'margin: -16px; height: 100%; display: flex; flex-direction: column; overflow: hidden;' }), // eslint-disable-line new-cap + }), + data: { reactions, roomInstance, onClose: () => modal.close() }, + }); + }, + condition({ msg: { reactions } }) { + return !!reactions; + }, + order: 18, + group: 'menu', + }); }); diff --git a/app/ui-utils/client/lib/ReactionListContent.js b/app/ui-utils/client/lib/ReactionListContent.js new file mode 100644 index 0000000000000..bede9d5f12a2d --- /dev/null +++ b/app/ui-utils/client/lib/ReactionListContent.js @@ -0,0 +1,68 @@ +import React from 'react'; +import { Box, Tag, Modal, ButtonGroup, Button, Scrollable } from '@rocket.chat/fuselage'; +import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; + +import { useTranslation } from '../../../../client/contexts/TranslationContext'; +import { useSetting } from '../../../../client/contexts/SettingsContext'; +import { useSession } from '../../../../client/contexts/SessionContext'; +import Emoji from '../../../../client/components/basic/Emoji'; +import { openUserCard } from '../../../ui/client/lib/UserCard'; +import { openProfileTabOrOpenDM } from '../../../ui/client/views/app/room'; + +export function Reactions({ reactions, roomInstance, onClose }) { + const useRealName = useSetting('UI_Use_Real_Name'); + + return + + {Object.entries(reactions).map(([reaction, { names = [], usernames }]) => + + + + {usernames.map((username, i) => )} + + + )} + + ; +} + +export function Username({ username, displayName, roomInstance, onClose }) { + const openedRoom = useSession('openedRoom'); + const handleUserCard = useMutableCallback((e) => openUserCard({ + username, + rid: openedRoom, + target: e.currentTarget, + open: (e) => { + e.preventDefault(); + onClose(); + openProfileTabOrOpenDM(e, roomInstance, username); + }, + })); + + return {displayName}; +} + +export default function ReactionListContent({ reactions, roomInstance, onClose }) { + const t = useTranslation(); + + return <> + + {t('Users_reacted')} + + + + + + + + + + + ; +} diff --git a/app/ui/client/views/app/room.js b/app/ui/client/views/app/room.js index 82bbefa449548..97398d18f5787 100644 --- a/app/ui/client/views/app/room.js +++ b/app/ui/client/views/app/room.js @@ -72,7 +72,7 @@ const openProfileTab = (e, instance, username) => { instance.tabBar.open('members-list'); }; -const openProfileTabOrOpenDM = (e, instance, username) => { +export const openProfileTabOrOpenDM = (e, instance, username) => { // if (settings.get('UI_Click_Direct_Message')) { // Meteor.call('createDirectMessage', username, (error, result) => { // if (error) { diff --git a/client/components/basic/Emoji.js b/client/components/basic/Emoji.js new file mode 100644 index 0000000000000..6926a24ba2c66 --- /dev/null +++ b/client/components/basic/Emoji.js @@ -0,0 +1,10 @@ +import React from 'react'; + +import { renderEmoji } from '../../../app/emoji/client/index'; + +function Emoji({ emojiHandle }) { + const markup = { __html: `${ renderEmoji(emojiHandle) }` }; + return
; +} + +export default Emoji; diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 8202e879828c9..7ad3733481128 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -3775,6 +3775,7 @@ "User_not_found_or_incorrect_password": "User not found or incorrect password", "User_or_channel_name": "User or channel name", "User_Presence": "User Presence", + "Users_reacted": "Users that Reacted", "User_removed": "User removed", "User_removed_by": "User __user_removed__ removed by __user_by__.", "User_sent_a_message_on_channel": "__username__ sent a message on __channel__",