Skip to content

Commit

Permalink
Send custom emoji reaction as mxc
Browse files Browse the repository at this point in the history
  • Loading branch information
ajbura committed Aug 4, 2022
1 parent b0741fa commit 519f620
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 31 deletions.
41 changes: 21 additions & 20 deletions src/app/molecules/message/Message.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import React, {
import PropTypes from 'prop-types';
import './Message.scss';

import { getShortcodeToCustomEmoji } from '../../organisms/emoji-board/custom-emoji';
import { twemojify } from '../../../util/twemojify';

import initMatrix from '../../../client/initMatrix';
Expand Down Expand Up @@ -322,25 +321,25 @@ function getMyEmojiEvent(emojiKey, eventId, roomTimeline) {
return rEvent;
}

function toggleEmoji(roomId, eventId, emojiKey, roomTimeline) {
function toggleEmoji(roomId, eventId, emojiKey, shortcode, roomTimeline) {
const myAlreadyReactEvent = getMyEmojiEvent(emojiKey, eventId, roomTimeline);
if (myAlreadyReactEvent) {
const rId = myAlreadyReactEvent.getId();
if (rId.startsWith('~')) return;
redactEvent(roomId, rId);
return;
}
sendReaction(roomId, eventId, emojiKey);
sendReaction(roomId, eventId, emojiKey, shortcode);
}

function pickEmoji(e, roomId, eventId, roomTimeline) {
openEmojiBoard(getEventCords(e), (emoji) => {
toggleEmoji(roomId, eventId, emoji.unicode, roomTimeline);
toggleEmoji(roomId, eventId, emoji.mxc ?? emoji.unicode, emoji.shortcodes[0], roomTimeline);
e.target.click();
});
}

function genReactionMsg(userIds, reaction) {
function genReactionMsg(userIds, reaction, shortcode) {
return (
<>
{userIds.map((userId, index) => (
Expand All @@ -354,24 +353,22 @@ function genReactionMsg(userIds, reaction) {
</React.Fragment>
))}
<span style={{ opacity: '.6' }}>{' reacted with '}</span>
{twemojify(reaction, { className: 'react-emoji' })}
{twemojify(shortcode ? `:${shortcode}:` : reaction, { className: 'react-emoji' })}
</>
);
}

function MessageReaction({
shortcodeToEmoji, reaction, count, users, isActive, onClick,
reaction, shortcode, 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);
if (reaction.match(/^mxc:\/\/\S+$/)) {
customEmojiUrl = initMatrix.matrixClient.mxcUrlToHttp(reaction);
}
return (
<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
onClick={onClick}
Expand All @@ -380,17 +377,20 @@ function MessageReaction({
>
{
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' })
}
<Text variant="b3" className="msg__reaction-count">{count}</Text>
</button>
</Tooltip>
);
}
MessageReaction.defaultProps = {
shortcode: undefined,
};
MessageReaction.propTypes = {
shortcodeToEmoji: PropTypes.shape({}).isRequired,
reaction: PropTypes.node.isRequired,
shortcode: PropTypes.string,
count: PropTypes.number.isRequired,
users: PropTypes.arrayOf(PropTypes.string).isRequired,
isActive: PropTypes.bool.isRequired,
Expand All @@ -401,17 +401,17 @@ function MessageReactionGroup({ roomTimeline, mEvent }) {
const { roomId, room, reactionTimeline } = roomTimeline;
const mx = initMatrix.matrixClient;
const reactions = {};
const shortcodeToEmoji = getShortcodeToCustomEmoji(room);
const canSendReaction = room.currentState.maySendEvent('m.reaction', mx.getUserId());

const eventReactions = reactionTimeline.get(mEvent.getId());
const addReaction = (key, count, senderId, isActive) => {
const addReaction = (key, shortcode, count, senderId, isActive) => {
let reaction = reactions[key];
if (reaction === undefined) {
reaction = {
count: 0,
users: [],
isActive: false,
shortcode,
};
}
if (count) {
Expand All @@ -429,17 +429,18 @@ function MessageReactionGroup({ roomTimeline, mEvent }) {
if (rEvent.getRelation() === null) return;
const reaction = rEvent.getRelation();
const senderId = rEvent.getSender();
const { shortcode } = rEvent.getContent();
const isActive = senderId === mx.getUserId();

addReaction(reaction.key, undefined, senderId, isActive);
addReaction(reaction.key, shortcode, undefined, senderId, isActive);
});
} else {
// Use aggregated reactions
const aggregatedReaction = mEvent.getServerAggregatedRelation('m.annotation')?.chunk;
if (!aggregatedReaction) return null;
aggregatedReaction.forEach((reaction) => {
if (reaction.type !== 'm.reaction') return;
addReaction(reaction.key, reaction.count, undefined, false);
addReaction(reaction.key, undefined, reaction.count, undefined, false);
});
}

Expand All @@ -449,13 +450,13 @@ function MessageReactionGroup({ roomTimeline, mEvent }) {
Object.keys(reactions).map((key) => (
<MessageReaction
key={key}
shortcodeToEmoji={shortcodeToEmoji}
reaction={key}
shortcode={reactions[key].shortcode}
count={reactions[key].count}
users={reactions[key].users}
isActive={reactions[key].isActive}
onClick={() => {
toggleEmoji(roomId, mEvent.getId(), key, roomTimeline);
toggleEmoji(roomId, mEvent.getId(), key, reactions[key].shortcode, roomTimeline);
}}
/>
))
Expand Down
7 changes: 5 additions & 2 deletions src/app/organisms/emoji-board/EmojiBoard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const EmojiGroup = React.memo(({ name, groupEmojis }) => {
unicode={`:${emoji.shortcode}:`}
shortcodes={emoji.shortcode}
src={initMatrix.matrixClient.mxcUrlToHttp(emoji.mxc)}
data-mx-emoticon
data-mx-emoticon={emoji.mxc}
/>
)
}
Expand Down Expand Up @@ -141,10 +141,13 @@ function EmojiBoard({ onSelect, searchRef }) {
function getEmojiDataFromTarget(target) {
const unicode = target.getAttribute('unicode');
const hexcode = target.getAttribute('hexcode');
const mxc = target.getAttribute('data-mx-emoticon');
let shortcodes = target.getAttribute('shortcodes');
if (typeof shortcodes === 'undefined') shortcodes = undefined;
else shortcodes = shortcodes.split(',');
return { unicode, hexcode, shortcodes };
return {
unicode, hexcode, shortcodes, mxc,
};
}

function selectEmoji(e) {
Expand Down
19 changes: 10 additions & 9 deletions src/client/action/roomTimeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 content = {
'm.relates_to': {
event_id: toEventId,
key: reaction,
rel_type: 'm.annotation',
},
};
if (typeof shortcode === 'string') content.shortcode = shortcode;
try {
await mx.sendEvent(roomId, 'm.reaction', {
'm.relates_to': {
event_id: toEventId,
key: reaction,
rel_type: 'm.annotation',
},
});
await mx.sendEvent(roomId, 'm.reaction', content);
} catch (e) {
throw new Error(e);
}
Expand Down

0 comments on commit 519f620

Please sign in to comment.