refactor: use Twemoji as img

This commit is contained in:
sup39 2024-01-16 09:50:50 +09:00
parent 52f273356c
commit 30808721af
Signed by: sup39
GPG key ID: 111C00916C1641E5
13 changed files with 75 additions and 30 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "twemoji"]
path = twemoji
url = https://github.com/jdecked/twemoji

16
package-lock.json generated
View file

@ -23,8 +23,8 @@
"dateformat": "5.0.3", "dateformat": "5.0.3",
"dayjs": "1.11.10", "dayjs": "1.11.10",
"domhandler": "5.0.3", "domhandler": "5.0.3",
"emojibase": "15.3.0", "emojibase": "15.2.0",
"emojibase-data": "15.3.0", "emojibase-data": "15.2.0",
"file-saver": "2.0.5", "file-saver": "2.0.5",
"flux": "4.0.3", "flux": "4.0.3",
"focus-trap-react": "10.0.2", "focus-trap-react": "10.0.2",
@ -3730,18 +3730,18 @@
"dev": true "dev": true
}, },
"node_modules/emojibase": { "node_modules/emojibase": {
"version": "15.3.0", "version": "15.2.0",
"resolved": "https://registry.npmjs.org/emojibase/-/emojibase-15.3.0.tgz", "resolved": "https://registry.npmjs.org/emojibase/-/emojibase-15.2.0.tgz",
"integrity": "sha512-lFdQb14hoznwDh1xDoOFzkPdeeexmbuJdhUUjDaJZf/+jK+6Z3HkI5hWOemWfEdaMxtTujc1vNRx9DKtdtiOXA==", "integrity": "sha512-gB6rIVtyJPersQvAo4nOGYPeILMhlcfZdiwCWVeRAtkJ7sm0tExZETGyLhrTQcHvZQhDEYI1vlCeqUhn5gZkQA==",
"funding": { "funding": {
"type": "ko-fi", "type": "ko-fi",
"url": "https://ko-fi.com/milesjohnson" "url": "https://ko-fi.com/milesjohnson"
} }
}, },
"node_modules/emojibase-data": { "node_modules/emojibase-data": {
"version": "15.3.0", "version": "15.2.0",
"resolved": "https://registry.npmjs.org/emojibase-data/-/emojibase-data-15.3.0.tgz", "resolved": "https://registry.npmjs.org/emojibase-data/-/emojibase-data-15.2.0.tgz",
"integrity": "sha512-cYsGq57W8wOd1CqQCjmtP1DpmlTVvJY+Um5UobWUQuTnqb8cO2cuqrxJxSIqxLcYZ3rtialT5kivoWigszdslg==", "integrity": "sha512-hDiw4ugxnI4pcVQO+73NlKx6aZP/A+BAPfDgK/3A83RVbHZa0Ut6GHpd5r5XUV9G7BZhKejlIRuxhXialpbt6Q==",
"funding": { "funding": {
"type": "ko-fi", "type": "ko-fi",
"url": "https://ko-fi.com/milesjohnson" "url": "https://ko-fi.com/milesjohnson"

View file

@ -33,8 +33,8 @@
"dateformat": "5.0.3", "dateformat": "5.0.3",
"dayjs": "1.11.10", "dayjs": "1.11.10",
"domhandler": "5.0.3", "domhandler": "5.0.3",
"emojibase": "15.3.0", "emojibase": "15.2.0",
"emojibase-data": "15.3.0", "emojibase-data": "15.2.0",
"file-saver": "2.0.5", "file-saver": "2.0.5",
"flux": "4.0.3", "flux": "4.0.3",
"focus-trap-react": "10.0.2", "focus-trap-react": "10.0.2",

View file

@ -11,6 +11,7 @@ import {
import * as css from '../../styles/CustomHtml.css'; import * as css from '../../styles/CustomHtml.css';
import { CommandElement, EmoticonElement, LinkElement, MentionElement } from './slate'; import { CommandElement, EmoticonElement, LinkElement, MentionElement } from './slate';
import { useMatrixClient } from '../../hooks/useMatrixClient'; import { useMatrixClient } from '../../hooks/useMatrixClient';
import { getEmojiUrl, isUsingTwemoji } from '../../plugins/emoji';
import { getBeginCommand } from './utils'; import { getBeginCommand } from './utils';
import { BlockType } from './types'; import { BlockType } from './types';
@ -94,7 +95,11 @@ function RenderEmoticonElement({
alt={element.shortcode} alt={element.shortcode}
/> />
) : ( ) : (
element.key isUsingTwemoji() ? <img
className={css.EmoticonImg}
src={getEmojiUrl(element.key)}
alt={element.shortcode}
/> : element.key
)} )}
{children} {children}
</span> </span>

View file

@ -126,6 +126,15 @@ export const CustomEmojiImg = style([
}, },
]); ]);
export const EmoticonImg = style([
DefaultReset,
{
width: toRem(32),
height: toRem(32),
objectFit: 'contain',
},
]);
export const StickerImg = style([ export const StickerImg = style([
DefaultReset, DefaultReset,
{ {

View file

@ -34,7 +34,15 @@ import { MatrixClient, Room } from 'matrix-js-sdk';
import { atom, useAtomValue, useSetAtom } from 'jotai'; import { atom, useAtomValue, useSetAtom } from 'jotai';
import * as css from './EmojiBoard.css'; import * as css from './EmojiBoard.css';
import { EmojiGroupId, IEmoji, IEmojiGroup, emojiGroups, emojis } from '../../plugins/emoji'; import {
EmojiGroupId,
IEmoji,
IEmojiGroup,
emojiGroups,
emojis,
getEmojiUrl,
isUsingTwemoji,
} from '../../plugins/emoji';
import { IEmojiGroupLabels, useEmojiGroupLabels } from './useEmojiGroupLabels'; import { IEmojiGroupLabels, useEmojiGroupLabels } from './useEmojiGroupLabels';
import { IEmojiGroupIcons, useEmojiGroupIcons } from './useEmojiGroupIcons'; import { IEmojiGroupIcons, useEmojiGroupIcons } from './useEmojiGroupIcons';
import { preventScrollWithArrowKey } from '../../utils/keyboard'; import { preventScrollWithArrowKey } from '../../utils/keyboard';
@ -439,9 +447,13 @@ export function RecentEmojiGroup({
type={EmojiType.Emoji} type={EmojiType.Emoji}
data={emoji.unicode} data={emoji.unicode}
shortcode={emoji.shortcode} shortcode={emoji.shortcode}
> >{
{emoji.unicode} isUsingTwemoji() ? <img
</EmojiItem> className={css.EmoticonImg}
src={getEmojiUrl(emoji.unicode)}
alt={emoji.shortcode}
/> : emoji.unicode
}</EmojiItem>
))} ))}
</EmojiGroup> </EmojiGroup>
); );

View file

@ -112,3 +112,13 @@ emojisData.forEach((emoji) => {
emojis.push(em); emojis.push(em);
} }
}); });
export const isUsingTwemoji = () =>
document.documentElement.style.getPropertyValue('--font-emoji') !== 'Twemoji_DISABLED';
const TWEMOJI_BASE_URL = '/twemoji'; // TODO
export function getEmojiUrl(char: string): string {
let codes = Array.from(char).flatMap(x => x.codePointAt(0)?.toString(16) ?? []);
if (!codes.includes('200d')) codes = codes.filter(x => x !== 'fe0f');
return `${TWEMOJI_BASE_URL}/${codes.join('-')}.svg`;
}

View file

@ -17,7 +17,7 @@ import * as css from '../styles/CustomHtml.css';
import { getMxIdLocalPart, getRoomWithCanonicalAlias } from '../utils/matrix'; import { getMxIdLocalPart, getRoomWithCanonicalAlias } from '../utils/matrix';
import { getMemberDisplayName } from '../utils/room'; import { getMemberDisplayName } from '../utils/room';
import { EMOJI_PATTERN, URL_NEG_LB } from '../utils/regex'; import { EMOJI_PATTERN, URL_NEG_LB } from '../utils/regex';
import { getHexcodeForEmoji, getShortcodeFor } from './emoji'; import { getHexcodeForEmoji, getShortcodeFor, getEmojiUrl, isUsingTwemoji } from './emoji';
import { findAndReplace } from '../utils/findAndReplace'; import { findAndReplace } from '../utils/findAndReplace';
const ReactPrism = lazy(() => import('./react-prism/ReactPrism')); const ReactPrism = lazy(() => import('./react-prism/ReactPrism'));
@ -39,13 +39,21 @@ const textToEmojifyJSX = (text: string): (string | JSX.Element)[] =>
findAndReplace( findAndReplace(
text, text,
EMOJI_REG_G, EMOJI_REG_G,
(match, pushIndex) => ( (match, pushIndex) => {
<span key={pushIndex} className={css.EmoticonBase}> const char = match[0];
<span className={css.Emoticon()} title={getShortcodeFor(getHexcodeForEmoji(match[0]))}> const className = css.Emoticon();
{match[0]} const title = getShortcodeFor(getHexcodeForEmoji(char));
</span> return <span key={pushIndex} className={css.EmoticonBase}>{
</span> isUsingTwemoji() ? <img
), className={className}
title={title}
src={getEmojiUrl(char)}
/> : <span
className={className}
title={title}
>{match[0]}</span>
}</span>;
},
(txt) => txt (txt) => txt
); );

View file

@ -1,12 +1,5 @@
@use './app/partials/screen'; @use './app/partials/screen';
@font-face {
font-family: Twemoji;
src: url('../public/font/Twemoji.Mozilla.v0.7.0+sup39.240115.woff2'),
url('../public/font/Twemoji.Mozilla.v0.7.0+sup39.240115.ttf');
font-display: swap;
}
:root { :root {
/* background color | --bg-[background type]: value */ /* background color | --bg-[background type]: value */
--bg-surface: #ffffff; --bg-surface: #ffffff;

1
twemoji Submodule

@ -0,0 +1 @@
Subproject commit 310184baaae6f797e9ef2650bea35187242ffafb

View file

@ -33,6 +33,10 @@ const copyFiles = {
src: 'public/res/android', src: 'public/res/android',
dest: 'public/', dest: 'public/',
}, },
{
src: 'twemoji/assets/svg/*',
dest: 'twemoji/',
},
], ],
} }