mirror of
https://github.com/cinnyapp/cinny.git
synced 2025-11-05 23:10:28 +03:00
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:
parent
5e527e434a
commit
edace32213
33 changed files with 1781 additions and 203 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue