Send custom emoji reaction as mxc

This commit is contained in:
Ajay Bura 2022-08-04 17:14:08 +05:30
parent b0741faa4d
commit 519f620cb7
3 changed files with 36 additions and 31 deletions

View file

@ -5,7 +5,6 @@ import 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';
@ -322,7 +321,7 @@ function getMyEmojiEvent(emojiKey, eventId, roomTimeline) {
return rEvent; return rEvent;
} }
function toggleEmoji(roomId, eventId, emojiKey, roomTimeline) { function toggleEmoji(roomId, eventId, emojiKey, shortcode, roomTimeline) {
const myAlreadyReactEvent = getMyEmojiEvent(emojiKey, eventId, roomTimeline); const myAlreadyReactEvent = getMyEmojiEvent(emojiKey, eventId, roomTimeline);
if (myAlreadyReactEvent) { if (myAlreadyReactEvent) {
const rId = myAlreadyReactEvent.getId(); const rId = myAlreadyReactEvent.getId();
@ -330,17 +329,17 @@ function toggleEmoji(roomId, eventId, emojiKey, roomTimeline) {
redactEvent(roomId, rId); redactEvent(roomId, rId);
return; return;
} }
sendReaction(roomId, eventId, emojiKey); sendReaction(roomId, eventId, emojiKey, shortcode);
} }
function pickEmoji(e, roomId, eventId, roomTimeline) { function pickEmoji(e, roomId, eventId, roomTimeline) {
openEmojiBoard(getEventCords(e), (emoji) => { openEmojiBoard(getEventCords(e), (emoji) => {
toggleEmoji(roomId, eventId, emoji.unicode, roomTimeline); toggleEmoji(roomId, eventId, emoji.mxc ?? emoji.unicode, emoji.shortcodes[0], roomTimeline);
e.target.click(); e.target.click();
}); });
} }
function genReactionMsg(userIds, reaction) { function genReactionMsg(userIds, reaction, shortcode) {
return ( return (
<> <>
{userIds.map((userId, index) => ( {userIds.map((userId, index) => (
@ -354,24 +353,22 @@ function genReactionMsg(userIds, reaction) {
</React.Fragment> </React.Fragment>
))} ))}
<span style={{ opacity: '.6' }}>{' reacted with '}</span> <span style={{ opacity: '.6' }}>{' reacted with '}</span>
{twemojify(reaction, { className: 'react-emoji' })} {twemojify(shortcode ? `:${shortcode}:` : reaction, { className: 'react-emoji' })}
</> </>
); );
} }
function MessageReaction({ function MessageReaction({
shortcodeToEmoji, reaction, count, users, isActive, onClick, reaction, shortcode, count, users, isActive, onClick,
}) { }) {
const customEmojiMatch = reaction.match(/^:(\S+):$/);
let customEmojiUrl = null; let customEmojiUrl = null;
if (customEmojiMatch) { if (reaction.match(/^mxc:\/\/\S+$/)) {
const customEmoji = shortcodeToEmoji.get(customEmojiMatch[1]); customEmojiUrl = initMatrix.matrixClient.mxcUrlToHttp(reaction);
customEmojiUrl = initMatrix.matrixClient.mxcUrlToHttp(customEmoji?.mxc);
} }
return ( return (
<Tooltip <Tooltip
className="msg__reaction-tooltip" className="msg__reaction-tooltip"
content={<Text variant="b2">{users.length > 0 ? genReactionMsg(users, reaction) : 'Unable to load who has reacted'}</Text>} content={<Text variant="b2">{users.length > 0 ? genReactionMsg(users, reaction, shortcode) : 'Unable to load who has reacted'}</Text>}
> >
<button <button
onClick={onClick} onClick={onClick}
@ -380,7 +377,7 @@ function MessageReaction({
> >
{ {
customEmojiUrl customEmojiUrl
? <img className="react-emoji" draggable="false" alt={reaction} src={customEmojiUrl} /> ? <img className="react-emoji" draggable="false" alt={shortcode ?? reaction} src={customEmojiUrl} />
: twemojify(reaction, { className: 'react-emoji' }) : twemojify(reaction, { className: 'react-emoji' })
} }
<Text variant="b3" className="msg__reaction-count">{count}</Text> <Text variant="b3" className="msg__reaction-count">{count}</Text>
@ -388,9 +385,12 @@ function MessageReaction({
</Tooltip> </Tooltip>
); );
} }
MessageReaction.defaultProps = {
shortcode: undefined,
};
MessageReaction.propTypes = { MessageReaction.propTypes = {
shortcodeToEmoji: PropTypes.shape({}).isRequired,
reaction: PropTypes.node.isRequired, reaction: PropTypes.node.isRequired,
shortcode: PropTypes.string,
count: PropTypes.number.isRequired, count: PropTypes.number.isRequired,
users: PropTypes.arrayOf(PropTypes.string).isRequired, users: PropTypes.arrayOf(PropTypes.string).isRequired,
isActive: PropTypes.bool.isRequired, isActive: PropTypes.bool.isRequired,
@ -401,17 +401,17 @@ function MessageReactionGroup({ roomTimeline, mEvent }) {
const { roomId, room, reactionTimeline } = roomTimeline; const { roomId, room, reactionTimeline } = roomTimeline;
const mx = initMatrix.matrixClient; const mx = initMatrix.matrixClient;
const reactions = {}; const reactions = {};
const shortcodeToEmoji = getShortcodeToCustomEmoji(room);
const canSendReaction = room.currentState.maySendEvent('m.reaction', mx.getUserId()); const canSendReaction = room.currentState.maySendEvent('m.reaction', mx.getUserId());
const eventReactions = reactionTimeline.get(mEvent.getId()); const eventReactions = reactionTimeline.get(mEvent.getId());
const addReaction = (key, count, senderId, isActive) => { const addReaction = (key, shortcode, count, senderId, isActive) => {
let reaction = reactions[key]; let reaction = reactions[key];
if (reaction === undefined) { if (reaction === undefined) {
reaction = { reaction = {
count: 0, count: 0,
users: [], users: [],
isActive: false, isActive: false,
shortcode,
}; };
} }
if (count) { if (count) {
@ -429,9 +429,10 @@ function MessageReactionGroup({ roomTimeline, mEvent }) {
if (rEvent.getRelation() === null) return; if (rEvent.getRelation() === null) return;
const reaction = rEvent.getRelation(); const reaction = rEvent.getRelation();
const senderId = rEvent.getSender(); const senderId = rEvent.getSender();
const { shortcode } = rEvent.getContent();
const isActive = senderId === mx.getUserId(); const isActive = senderId === mx.getUserId();
addReaction(reaction.key, undefined, senderId, isActive); addReaction(reaction.key, shortcode, undefined, senderId, isActive);
}); });
} else { } else {
// Use aggregated reactions // Use aggregated reactions
@ -439,7 +440,7 @@ function MessageReactionGroup({ roomTimeline, mEvent }) {
if (!aggregatedReaction) return null; if (!aggregatedReaction) return null;
aggregatedReaction.forEach((reaction) => { aggregatedReaction.forEach((reaction) => {
if (reaction.type !== 'm.reaction') return; if (reaction.type !== 'm.reaction') return;
addReaction(reaction.key, reaction.count, undefined, false); addReaction(reaction.key, undefined, reaction.count, undefined, false);
}); });
} }
@ -449,13 +450,13 @@ 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}
shortcode={reactions[key].shortcode}
count={reactions[key].count} count={reactions[key].count}
users={reactions[key].users} users={reactions[key].users}
isActive={reactions[key].isActive} isActive={reactions[key].isActive}
onClick={() => { onClick={() => {
toggleEmoji(roomId, mEvent.getId(), key, roomTimeline); toggleEmoji(roomId, mEvent.getId(), key, reactions[key].shortcode, roomTimeline);
}} }}
/> />
)) ))

View file

@ -70,7 +70,7 @@ const EmojiGroup = React.memo(({ name, groupEmojis }) => {
unicode={`:${emoji.shortcode}:`} unicode={`:${emoji.shortcode}:`}
shortcodes={emoji.shortcode} shortcodes={emoji.shortcode}
src={initMatrix.matrixClient.mxcUrlToHttp(emoji.mxc)} src={initMatrix.matrixClient.mxcUrlToHttp(emoji.mxc)}
data-mx-emoticon data-mx-emoticon={emoji.mxc}
/> />
) )
} }
@ -141,10 +141,13 @@ function EmojiBoard({ onSelect, searchRef }) {
function getEmojiDataFromTarget(target) { function getEmojiDataFromTarget(target) {
const unicode = target.getAttribute('unicode'); const unicode = target.getAttribute('unicode');
const hexcode = target.getAttribute('hexcode'); const hexcode = target.getAttribute('hexcode');
const mxc = target.getAttribute('data-mx-emoticon');
let shortcodes = target.getAttribute('shortcodes'); let shortcodes = target.getAttribute('shortcodes');
if (typeof shortcodes === 'undefined') shortcodes = undefined; if (typeof shortcodes === 'undefined') shortcodes = undefined;
else shortcodes = shortcodes.split(','); else shortcodes = shortcodes.split(',');
return { unicode, hexcode, shortcodes }; return {
unicode, hexcode, shortcodes, mxc,
};
} }
function selectEmoji(e) { function selectEmoji(e) {

View file

@ -11,17 +11,18 @@ async function redactEvent(roomId, eventId, reason) {
} }
} }
async function sendReaction(roomId, toEventId, reaction) { async function sendReaction(roomId, toEventId, reaction, shortcode) {
const mx = initMatrix.matrixClient; const mx = initMatrix.matrixClient;
const content = {
'm.relates_to': {
event_id: toEventId,
key: reaction,
rel_type: 'm.annotation',
},
};
if (typeof shortcode === 'string') content.shortcode = shortcode;
try { try {
await mx.sendEvent(roomId, 'm.reaction', { await mx.sendEvent(roomId, 'm.reaction', content);
'm.relates_to': {
event_id: toEventId,
key: reaction,
rel_type: 'm.annotation',
},
});
} catch (e) { } catch (e) {
throw new Error(e); throw new Error(e);
} }