Add support for custom emoji in reactions

Signed-off-by: Ajay Bura <ajbura@gmail.com>
This commit is contained in:
Ajay Bura 2022-01-26 12:06:18 +05:30
parent e4f7c6add9
commit 20b99dce48
2 changed files with 33 additions and 5 deletions

View file

@ -3,6 +3,7 @@ import React, { useState, useEffect, useCallback, useRef } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import './Message.scss'; import './Message.scss';
import { getShortcodeToCustomEmoji } from '../../organisms/emoji-board/custom-emoji';
import { twemojify } from '../../../util/twemojify'; import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix'; import initMatrix from '../../../client/initMatrix';
@ -301,12 +302,12 @@ function genReactionMsg(userIds, reaction) {
return ( return (
<> <>
{userIds.map((userId, index) => ( {userIds.map((userId, index) => (
<> <React.Fragment key={userId}>
{twemojify(getUsername(userId))} {twemojify(getUsername(userId))}
<span style={{ opacity: '.6' }}> <span style={{ opacity: '.6' }}>
{index === userIds.length - 1 ? ' and ' : ', '} {index === userIds.length - 1 ? ' and ' : ', '}
</span> </span>
</> </React.Fragment>
))} ))}
<span style={{ opacity: '.6' }}>{' reacted with '}</span> <span style={{ opacity: '.6' }}>{' reacted with '}</span>
{twemojify(reaction, { className: 'react-emoji' })} {twemojify(reaction, { className: 'react-emoji' })}
@ -315,8 +316,14 @@ function genReactionMsg(userIds, reaction) {
} }
function MessageReaction({ function MessageReaction({
reaction, count, users, isActive, onClick, shortcodeToEmoji, reaction, count, users, isActive, onClick,
}) { }) {
const customEmojiMatch = reaction.match(/^:(\S+):$/);
let customEmojiUrl = null;
if (customEmojiMatch) {
const customEmoji = shortcodeToEmoji.get(customEmojiMatch[1]);
customEmojiUrl = initMatrix.matrixClient.mxcUrlToHttp(customEmoji?.mxc);
}
return ( return (
<Tooltip <Tooltip
className="msg__reaction-tooltip" className="msg__reaction-tooltip"
@ -327,13 +334,18 @@ function MessageReaction({
type="button" type="button"
className={`msg__reaction${isActive ? ' msg__reaction--active' : ''}`} className={`msg__reaction${isActive ? ' msg__reaction--active' : ''}`}
> >
{ twemojify(reaction, { className: 'react-emoji' }) } {
customEmojiUrl
? <img className="react-emoji" draggable="false" alt={reaction} src={customEmojiUrl} />
: twemojify(reaction, { className: 'react-emoji' })
}
<Text variant="b3" className="msg__reaction-count">{count}</Text> <Text variant="b3" className="msg__reaction-count">{count}</Text>
</button> </button>
</Tooltip> </Tooltip>
); );
} }
MessageReaction.propTypes = { MessageReaction.propTypes = {
shortcodeToEmoji: PropTypes.shape({}).isRequired,
reaction: PropTypes.node.isRequired, reaction: PropTypes.node.isRequired,
count: PropTypes.number.isRequired, count: PropTypes.number.isRequired,
users: PropTypes.arrayOf(PropTypes.string).isRequired, users: PropTypes.arrayOf(PropTypes.string).isRequired,
@ -346,6 +358,7 @@ function MessageReactionGroup({ roomTimeline, mEvent }) {
const eventId = mEvent.getId(); const eventId = mEvent.getId();
const mx = initMatrix.matrixClient; const mx = initMatrix.matrixClient;
const reactions = {}; const reactions = {};
const shortcodeToEmoji = getShortcodeToCustomEmoji(roomTimeline.room);
const eventReactions = reactionTimeline.get(eventId); const eventReactions = reactionTimeline.get(eventId);
const addReaction = (key, count, senderId, isActive) => { const addReaction = (key, count, senderId, isActive) => {
@ -392,6 +405,7 @@ function MessageReactionGroup({ roomTimeline, mEvent }) {
Object.keys(reactions).map((key) => ( Object.keys(reactions).map((key) => (
<MessageReaction <MessageReaction
key={key} key={key}
shortcodeToEmoji={shortcodeToEmoji}
reaction={key} reaction={key}
count={reactions[key].count} count={reactions[key].count}
users={reactions[key].users} users={reactions[key].users}

View file

@ -147,6 +147,18 @@ function getShortcodeToEmoji(room) {
return allEmoji; return allEmoji;
} }
function getShortcodeToCustomEmoji(room) {
const allEmoji = new Map();
getRelevantPacks(room).reverse()
.flatMap((pack) => pack.getEmojis())
.forEach((emoji) => {
allEmoji.set(emoji.shortcode, emoji);
});
return allEmoji;
}
// Produces a special list of emoji specifically for auto-completion // Produces a special list of emoji specifically for auto-completion
// //
// This list contains each emoji once, with all emoji being deduplicated by shortcode. // This list contains each emoji once, with all emoji being deduplicated by shortcode.
@ -167,5 +179,7 @@ function getEmojiForCompletion(room) {
} }
export { export {
getUserImagePack, getShortcodeToEmoji, getRelevantPacks, getEmojiForCompletion, getUserImagePack,
getShortcodeToEmoji, getShortcodeToCustomEmoji,
getRelevantPacks, getEmojiForCompletion,
}; };