Add support for sending user emoji using autocomplete (#205)

* Add support for sending user emoji using autocomplete

What's included:
- An implementation for detecting user emojis
- Addition of user emojis to the emoji autocomplete in the command bar
- Translation of shortcodes into image tags on message sending

What's not included:
- Loading emojis from the active room, loading the user's global emoji packs, loading emoji from spaces
- Selecting custom emoji using the emoji picker

This is a predominantly proof-of-concept change, and everything here may be subject to
architectural review and reworking.

* Amending PR:  Allow sending multiple of the same emoji

* Amending PR:  Add support for emojis in edited messages

* Amend PR:  Apply requested revisions

This commit consists of several small changes, including:
- Fix crash when the user doesn't have the im.ponies.user_emotes account data entry
- Add mx-data-emoticon attribute to command bar emoji
- Rewrite alt text in the command bar interface
- Remove "vertical-align" attribute from sent emoji

* Amending PR:  Fix bugs (listed below)

- Fix bug where sending emoji w/ markdown off resulted in a crash
- Fix bug where alt text in the command bar was wrong

* Amending PR:  Add support for replacement of twemoji shortcodes

* Amending PR: Fix & refactor getAllEmoji -> getShortcodeToEmoji

* Amending PR: Fix bug: Sending two of the same emoji corrupts message

* Amending PR:  Stylistic fixes
This commit is contained in:
Emi 2021-12-27 22:29:39 -05:00 committed by GitHub
parent 6ff339b552
commit 90621bb1e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 182 additions and 26 deletions

View file

@ -13,7 +13,7 @@ import {
openPublicRooms,
openInviteUser,
} from '../../../client/action/navigation';
import { emojis } from '../emoji-board/emoji';
import { getEmojiForCompletion } from '../emoji-board/custom-emoji';
import AsyncSearch from '../../../util/AsyncSearch';
import Text from '../../atoms/text/Text';
@ -81,24 +81,51 @@ function renderSuggestions({ prefix, option, suggestions }, fireCmd) {
}
function renderEmojiSuggestion(emPrefix, emos) {
const mx = initMatrix.matrixClient;
// Renders a small Twemoji
function renderTwemoji(emoji) {
return parse(twemoji.parse(
emoji.unicode,
{
attributes: () => ({
unicode: emoji.unicode,
shortcodes: emoji.shortcodes?.toString(),
}),
},
));
}
// Render a custom emoji
function renderCustomEmoji(emoji) {
return (
<img
className="emoji"
src={mx.mxcUrlToHttp(emoji.mxc)}
data-mx-emoticon=""
alt={`:${emoji.shortcode}:`}
/>
);
}
// Dynamically render either a custom emoji or twemoji based on what the input is
function renderEmoji(emoji) {
if (emoji.mxc) {
return renderCustomEmoji(emoji);
}
return renderTwemoji(emoji);
}
return emos.map((emoji) => (
<CmdItem
key={emoji.hexcode}
key={emoji.shortcode}
onClick={() => fireCmd({
prefix: emPrefix,
result: emoji,
})}
>
{
parse(twemoji.parse(
emoji.unicode,
{
attributes: () => ({
unicode: emoji.unicode,
shortcodes: emoji.shortcodes?.toString(),
}),
},
))
renderEmoji(emoji)
}
<Text variant="b2">{`:${emoji.shortcode}:`}</Text>
</CmdItem>
@ -183,6 +210,7 @@ function RoomViewCmdBar({ roomId, roomTimeline, viewEvent }) {
setCmd({ prefix, suggestions: commands });
},
':': () => {
const emojis = getEmojiForCompletion(mx);
asyncSearch.setup(emojis, { keys: ['shortcode'], isContain: true, limit: 20 });
setCmd({ prefix, suggestions: emojis.slice(26, 46) });
},
@ -210,7 +238,7 @@ function RoomViewCmdBar({ roomId, roomTimeline, viewEvent }) {
}
if (myCmd.prefix === ':') {
viewEvent.emit('cmd_fired', {
replace: myCmd.result.unicode,
replace: myCmd.result.mxc ? `:${myCmd.result.shortcode}: ` : myCmd.result.unicode,
});
}
if (myCmd.prefix === '@') {