Custom emoji & Sticker support (#686)

* Remove comments

* Show custom emoji first in suggestions

* Show global image packs in emoji picker

* Display emoji and sticker in room settings

* Fix some pack not visible in emojiboard

* WIP

* Add/delete/rename images to exisitng packs

* Change pack avatar, name & attribution

* Add checkbox to make pack global

* Bug fix

* Create or delete pack

* Add personal emoji in settings

* Show global pack selector in settings

* Show space emoji in emojiboard

* Send custom emoji reaction as mxc

* Render stickers as stickers

* Fix sticker jump bug

* Fix reaction width

* Fix stretched custom emoji

* Fix sending space emoji in message

* Remove unnessesary comments

* Send user pills

* Fix pill generating regex

* Add support for sending stickers
This commit is contained in:
Ajay Bura 2022-08-06 09:04:23 +05:30 committed by GitHub
parent 5e527e434a
commit edace32213
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 1781 additions and 203 deletions

View file

@ -5,21 +5,10 @@ import encrypt from 'browser-encrypt-attachment';
import { math } from 'micromark-extension-math';
import { getShortcodeToEmoji } from '../../app/organisms/emoji-board/custom-emoji';
import { mathExtensionHtml, spoilerExtension, spoilerExtensionHtml } from '../../util/markdown';
import { getImageDimension } from '../../util/common';
import cons from './cons';
import settings from './settings';
function getImageDimension(file) {
return new Promise((resolve) => {
const img = new Image();
img.onload = async () => {
resolve({
w: img.width,
h: img.height,
});
};
img.src = URL.createObjectURL(file);
});
}
function loadVideo(videoFile) {
return new Promise((resolve, reject) => {
const video = document.createElement('video');
@ -120,14 +109,13 @@ function bindReplyToContent(roomId, reply, content) {
return newContent;
}
// Apply formatting to a plain text message
//
// This includes inserting any custom emoji that might be relevant, and (only if the
// user has enabled it in their settings) formatting the message using markdown.
function formatAndEmojifyText(room, text) {
const allEmoji = getShortcodeToEmoji(room);
function formatAndEmojifyText(mx, roomList, roomId, text) {
const room = mx.getRoom(roomId);
const { userIdsToDisplayNames } = room.currentState;
const parentIds = roomList.getAllParentSpaces(roomId);
const parentRooms = [...parentIds].map((id) => mx.getRoom(id));
const allEmoji = getShortcodeToEmoji(mx, [room, ...parentRooms]);
// Start by applying markdown formatting (if relevant)
let formattedText;
if (settings.isMarkdown) {
formattedText = getFormattedBody(text);
@ -135,17 +123,25 @@ function formatAndEmojifyText(room, text) {
formattedText = text;
}
// Check to see if there are any :shortcode-style-tags: in the message
Array.from(formattedText.matchAll(/\B:([\w-]+):\B/g))
// Then filter to only the ones corresponding to a valid emoji
.filter((match) => allEmoji.has(match[1]))
// Reversing the array ensures that indices are preserved as we start replacing
const MXID_REGEX = /\B@\S+:\S+\.\S+[^.,:;?!\s]/g;
Array.from(formattedText.matchAll(MXID_REGEX))
.filter((mxidMatch) => userIdsToDisplayNames[mxidMatch[0]])
.reverse()
// Replace each :shortcode: with an <img/> tag
.forEach((mxidMatch) => {
const tag = `<a href="https://matrix.to/#/${mxidMatch[0]}">${userIdsToDisplayNames[mxidMatch[0]]}</a>`;
formattedText = formattedText.substr(0, mxidMatch.index)
+ tag
+ formattedText.substr(mxidMatch.index + mxidMatch[0].length);
});
const SHORTCODE_REGEX = /\B:([\w-]+):\B/g;
Array.from(formattedText.matchAll(SHORTCODE_REGEX))
.filter((shortcodeMatch) => allEmoji.has(shortcodeMatch[1]))
.reverse() /* Reversing the array ensures that indices are preserved as we start replacing */
.forEach((shortcodeMatch) => {
const emoji = allEmoji.get(shortcodeMatch[1]);
// Render the tag that will replace the shortcode
let tag;
if (emoji.mxc) {
tag = `<img data-mx-emoticon="" src="${
@ -159,7 +155,6 @@ function formatAndEmojifyText(room, text) {
tag = emoji.unicode;
}
// Splice the tag into the text
formattedText = formattedText.substr(0, shortcodeMatch.index)
+ tag
+ formattedText.substr(shortcodeMatch.index + shortcodeMatch[0].length);
@ -169,10 +164,11 @@ function formatAndEmojifyText(room, text) {
}
class RoomsInput extends EventEmitter {
constructor(mx) {
constructor(mx, roomList) {
super();
this.matrixClient = mx;
this.roomList = roomList;
this.roomIdToInput = new Map();
}
@ -273,7 +269,9 @@ class RoomsInput extends EventEmitter {
// Apply formatting if relevant
const formattedBody = formatAndEmojifyText(
this.matrixClient.getRoom(roomId),
this.matrixClient,
this.roomList,
roomId,
input.message,
);
if (formattedBody !== input.message) {
@ -412,7 +410,9 @@ class RoomsInput extends EventEmitter {
// Apply formatting if relevant
const formattedBody = formatAndEmojifyText(
this.matrixClient.getRoom(roomId),
this.matrixClient,
this.roomList,
roomId,
editedBody,
);
if (formattedBody !== editedBody) {