fix crashes and re-add twemoji
This commit is contained in:
parent
b86967fc3c
commit
745cd87b7f
9 changed files with 143 additions and 24 deletions
|
@ -45,7 +45,8 @@
|
|||
"react-dom": "17.0.2",
|
||||
"react-modal": "3.16.1",
|
||||
"sanitize-html": "2.8.0",
|
||||
"tippy.js": "6.3.7"
|
||||
"tippy.js": "6.3.7",
|
||||
"twemoji": "14.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.emoji {
|
||||
content-visibility: auto;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
|
|
@ -131,7 +131,7 @@ function SearchedEmoji() {
|
|||
|
||||
function EmojiBoard({ onSelect, searchRef }) {
|
||||
const scrollEmojisRef = useRef(null);
|
||||
const emojiInfo = useRef(null);
|
||||
const [emojiInfo, setEmojiInfo] = useState(null);
|
||||
|
||||
function isTargetNotEmoji(target) {
|
||||
return target.classList.contains('emoji') === false;
|
||||
|
@ -159,25 +159,15 @@ function EmojiBoard({ onSelect, searchRef }) {
|
|||
if (emoji.hexcode) addRecentEmoji(emoji.unicode);
|
||||
}
|
||||
|
||||
function setEmojiInfo(emoji) {
|
||||
const infoEmoji = emojiInfo.current.firstElementChild.firstElementChild;
|
||||
const infoShortcode = emojiInfo.current.lastElementChild;
|
||||
|
||||
infoEmoji.src = emoji.src;
|
||||
infoEmoji.alt = emoji.unicode;
|
||||
infoShortcode.textContent = `:${emoji.shortcode}:`;
|
||||
}
|
||||
|
||||
function hoverEmoji(e) {
|
||||
if (isTargetNotEmoji(e.target)) return;
|
||||
|
||||
const emoji = e.target;
|
||||
const { shortcodes, unicode } = getEmojiDataFromTarget(emoji);
|
||||
const { src } = e.target;
|
||||
|
||||
if (searchRef.current.placeholder === shortcodes[0]) return;
|
||||
searchRef.current.setAttribute('placeholder', shortcodes[0]);
|
||||
setEmojiInfo({ shortcode: shortcodes[0], src, unicode });
|
||||
setEmojiInfo({ shortcode: shortcodes[0], unicode });
|
||||
}
|
||||
|
||||
function handleSearchChange() {
|
||||
|
@ -318,9 +308,9 @@ function EmojiBoard({ onSelect, searchRef }) {
|
|||
</div>
|
||||
</ScrollView>
|
||||
</div>
|
||||
<div ref={emojiInfo} className="emoji-board__content__info">
|
||||
<div><span className="emoji" unicode="🙂" shortcodes="slight_smile">🙂</span></div>
|
||||
<Text>:slight_smile:</Text>
|
||||
<div className="emoji-board__content__info">
|
||||
<div><span className="emoji">{ emojiInfo ? emojiInfo.unicode : '' }</span></div>
|
||||
<Text>{emojiInfo ? emojiInfo.shortcode : ''}</Text>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
.emoji-board {
|
||||
--emoji-board-height: 390px;
|
||||
--emoji-board-width: 286px;
|
||||
--emoji-board-width: 218px;
|
||||
display: flex;
|
||||
max-width: 90vw;
|
||||
max-height: 90vh;
|
||||
|
@ -121,6 +121,7 @@
|
|||
@include dir.side(margin, var(--left-margin), var(--right-margin));
|
||||
}
|
||||
& .emoji {
|
||||
display: block;
|
||||
max-width: 38px;
|
||||
max-height: 38px;
|
||||
width: 100%;
|
||||
|
|
|
@ -128,7 +128,7 @@ function PeopleDrawer({ roomId }) {
|
|||
<div className="people-drawer">
|
||||
<Header>
|
||||
<TitleWrapper>
|
||||
<Text primary>
|
||||
<Text span primary>
|
||||
People
|
||||
<Text className="people-drawer__member-count" variant="b3">{`${room.getJoinedMemberCount()} members`}</Text>
|
||||
</Text>
|
||||
|
|
|
@ -3,7 +3,7 @@ import React, { useState, useEffect } from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import './RoomViewCmdBar.scss';
|
||||
|
||||
import { twemojify } from '../../../util/twemojify';
|
||||
import { singleEmojiToJSX, twemojify } from '../../../util/twemojify';
|
||||
|
||||
import initMatrix from '../../../client/initMatrix';
|
||||
import { getEmojiForCompletion } from '../emoji-board/custom-emoji';
|
||||
|
@ -49,6 +49,34 @@ function renderSuggestions({ prefix, option, suggestions }, fireCmd) {
|
|||
function renderEmojiSuggestion(emPrefix, emos) {
|
||||
const mx = initMatrix.matrixClient;
|
||||
|
||||
// Renders a small Twemoji
|
||||
function renderTwemoji(emoji) {
|
||||
return singleEmojiToJSX(emoji);
|
||||
}
|
||||
|
||||
// Render a custom emoji
|
||||
function renderCustomEmoji(emoji) {
|
||||
return (
|
||||
<img
|
||||
className="emoji"
|
||||
draggable="false"
|
||||
loading="lazy"
|
||||
referrerPolicy="no-referrer"
|
||||
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.shortcode}
|
||||
|
@ -59,7 +87,7 @@ function renderSuggestions({ prefix, option, suggestions }, fireCmd) {
|
|||
})
|
||||
}
|
||||
>
|
||||
<Text variant="b1">{emoji}</Text>
|
||||
<Text variant="b1">{renderEmoji(emoji)}</Text>
|
||||
<Text variant="b2">{`:${emoji.shortcode}:`}</Text>
|
||||
</CmdItem>
|
||||
));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react';
|
||||
import React, { StrictMode } from 'react';
|
||||
import ReactDom from 'react-dom';
|
||||
import './font';
|
||||
import './index.scss';
|
||||
|
@ -9,4 +9,9 @@ import App from './app/pages/App';
|
|||
|
||||
settings.applyTheme();
|
||||
|
||||
ReactDom.render(<App />, document.getElementById('root'));
|
||||
ReactDom.render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
|
|
@ -1,20 +1,65 @@
|
|||
import linkifyHtml from 'linkify-html';
|
||||
import parse from 'html-react-parser';
|
||||
import twemoji from 'twemoji';
|
||||
import { sanitizeText } from './sanitize';
|
||||
|
||||
export function twemojify(text, _opts=null, linkify=false, sanitize=true, _maths=false) {
|
||||
export const TWEMOJI_BASE_URL = 'https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/';
|
||||
|
||||
// Start modified block from `twemoji` code:
|
||||
// MIT License
|
||||
// Copyright (c) 2021 Twitter
|
||||
const UFE0Fg = /\uFE0F/g;
|
||||
const U200D = String.fromCharCode(0x200D);
|
||||
|
||||
function grabTheRightIcon(rawText) {
|
||||
// if variant is present as \uFE0F
|
||||
return twemoji.convert.toCodePoint(rawText.indexOf(U200D) < 0 ?
|
||||
rawText.replace(UFE0Fg, '') :
|
||||
rawText
|
||||
);
|
||||
}
|
||||
// End function from `twemoji`
|
||||
|
||||
export function singleEmojiToJSX({ shortcodes, unicode, hexcode }) {
|
||||
return <img
|
||||
className="emoji"
|
||||
draggable="false"
|
||||
loading="lazy"
|
||||
referrerPolicy="no-referrer"
|
||||
crossOrigin="anonymous"
|
||||
alt={unicode}
|
||||
unicode={unicode}
|
||||
shortcodes={shortcodes}
|
||||
hexcode={hexcode}
|
||||
src={`${TWEMOJI_BASE_URL}/72x72/${grabTheRightIcon(unicode)}.png`}
|
||||
></img>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text - text to twemojify
|
||||
* @param {object|undefined} opts - options for tweomoji.parse
|
||||
* @param {boolean} [linkify=false] - convert links to html tags (default: false)
|
||||
* @param {boolean} [sanitize=true] - sanitize html text (default: true)
|
||||
* @returns React component
|
||||
*/
|
||||
export function twemojify(text, opts, linkify = false, sanitize = true) {
|
||||
if (typeof text !== 'string') return text;
|
||||
let content = text;
|
||||
const options = opts ?? { base: TWEMOJI_BASE_URL };
|
||||
if (!options.base) {
|
||||
options.base = TWEMOJI_BASE_URL;
|
||||
}
|
||||
|
||||
if (sanitize) {
|
||||
content = sanitizeText(content);
|
||||
}
|
||||
|
||||
content = twemoji.parse(content, options);
|
||||
if (linkify) {
|
||||
content = linkifyHtml(content, {
|
||||
target: '_blank',
|
||||
rel: 'noreferrer noopener',
|
||||
});
|
||||
}
|
||||
return parse(content);
|
||||
return parse(content, null);
|
||||
}
|
||||
|
|
45
yarn.lock
45
yarn.lock
|
@ -1633,6 +1633,15 @@ fs-extra@^11.1.0:
|
|||
jsonfile "^6.0.1"
|
||||
universalify "^2.0.0"
|
||||
|
||||
fs-extra@^8.0.1:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
|
||||
integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.0"
|
||||
jsonfile "^4.0.0"
|
||||
universalify "^0.1.0"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
|
@ -2080,6 +2089,22 @@ json5@^2.2.2:
|
|||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
|
||||
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
||||
|
||||
jsonfile@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
|
||||
integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsonfile@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-5.0.0.tgz#e6b718f73da420d612823996fdf14a03f6ff6922"
|
||||
integrity sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w==
|
||||
dependencies:
|
||||
universalify "^0.1.2"
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsonfile@^6.0.1:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
|
||||
|
@ -2906,6 +2931,21 @@ tsutils@^3.21.0:
|
|||
dependencies:
|
||||
tslib "^1.8.1"
|
||||
|
||||
twemoji-parser@14.0.0:
|
||||
version "14.0.0"
|
||||
resolved "https://registry.yarnpkg.com/twemoji-parser/-/twemoji-parser-14.0.0.tgz#13dabcb6d3a261d9efbf58a1666b182033bf2b62"
|
||||
integrity sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA==
|
||||
|
||||
twemoji@14.0.2:
|
||||
version "14.0.2"
|
||||
resolved "https://registry.yarnpkg.com/twemoji/-/twemoji-14.0.2.tgz#c53adb01dab22bf4870f648ca8cc347ce99ee37e"
|
||||
integrity sha512-BzOoXIe1QVdmsUmZ54xbEH+8AgtOKUiG53zO5vVP2iUu6h5u9lN15NcuS6te4OY96qx0H7JK9vjjl9WQbkTRuA==
|
||||
dependencies:
|
||||
fs-extra "^8.0.1"
|
||||
jsonfile "^5.0.0"
|
||||
twemoji-parser "14.0.0"
|
||||
universalify "^0.1.2"
|
||||
|
||||
type-check@^0.4.0, type-check@~0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
|
||||
|
@ -2952,6 +2992,11 @@ unhomoglyph@^1.0.6:
|
|||
resolved "https://registry.yarnpkg.com/unhomoglyph/-/unhomoglyph-1.0.6.tgz#ea41f926d0fcf598e3b8bb2980c2ddac66b081d3"
|
||||
integrity sha512-7uvcWI3hWshSADBu4JpnyYbTVc7YlhF5GDW/oPD5AxIxl34k4wXR3WDkPnzLxkN32LiTCTKMQLtKVZiwki3zGg==
|
||||
|
||||
universalify@^0.1.0, universalify@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
||||
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
|
||||
|
||||
universalify@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
|
||||
|
|
Loading…
Reference in a new issue