[NEW] Reaction view (#18272)

Co-authored-by: Tasso Evangelista <tasso.evangelista@rocket.chat>
Co-authored-by: Guilherme Gazzo <guilhermegazzo@gmail.com>
Co-authored-by: Guilherme Gazzo <guilherme@gazzo.xyz>
Co-authored-by: Gabriel Henriques <gabriel.henriques@rocket.chat>
pull/19661/head
Martin Schoeler 5 years ago committed by GitHub
parent 0b488a37d2
commit 90246a4576
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 24
      app/ui-utils/client/lib/MessageAction.js
  2. 68
      app/ui-utils/client/lib/ReactionListContent.js
  3. 2
      app/ui/client/views/app/room.js
  4. 10
      client/components/basic/Emoji.js
  5. 1
      packages/rocketchat-i18n/i18n/en.i18n.json

@ -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',
});
});

@ -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 <Scrollable>
<Box>
{Object.entries(reactions).map(([reaction, { names = [], usernames }]) => <Box key={reaction}>
<Box display='flex' flexWrap='wrap' overflowX='hidden' mb='x8'>
<Emoji emojiHandle={reaction} />
<Box paddingBlock='x4' mis='x4'>
{usernames.map((username, i) => <Username
key={username}
displayName={useRealName ? names[i] || username : username}
username={username}
roomInstance={roomInstance}
onClose={onClose}
/>)}
</Box>
</Box>
</Box>)}
</Box>
</Scrollable>;
}
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 <Tag onClick={handleUserCard} marginInlineEnd='x4' key={displayName}>{displayName}</Tag>;
}
export default function ReactionListContent({ reactions, roomInstance, onClose }) {
const t = useTranslation();
return <>
<Modal.Header>
<Modal.Title>{t('Users_reacted')}</Modal.Title>
<Modal.Close onClick={onClose}/>
</Modal.Header>
<Modal.Content fontScale='p1'>
<Reactions reactions={reactions} roomInstance={roomInstance} onClose={onClose}/>
</Modal.Content>
<Modal.Footer>
<ButtonGroup align='end'>
<Button primary onClick={onClose}>{t('Ok')}</Button>
</ButtonGroup>
</Modal.Footer>
</>;
}

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

@ -0,0 +1,10 @@
import React from 'react';
import { renderEmoji } from '../../../app/emoji/client/index';
function Emoji({ emojiHandle }) {
const markup = { __html: `${ renderEmoji(emojiHandle) }` };
return <div dangerouslySetInnerHTML={ markup }></div>;
}
export default Emoji;

@ -3780,6 +3780,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 <em>__user_removed__</em> removed by <em>__user_by__</em>.",
"User_sent_a_message_on_channel": "<strong>__username__</strong> sent a message on <strong>__channel__</strong>",

Loading…
Cancel
Save