Send custom emoji reaction as mxc
This commit is contained in:
parent
b0741faa4d
commit
519f620cb7
3 changed files with 36 additions and 31 deletions
|
@ -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);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue