refactor: use Twemoji as img
This commit is contained in:
parent
aca74157a1
commit
4e58dbda99
13 changed files with 78 additions and 30 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "twemoji"]
|
||||||
|
path = twemoji
|
||||||
|
url = https://github.com/jdecked/twemoji
|
16
package-lock.json
generated
16
package-lock.json
generated
|
@ -24,8 +24,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",
|
||||||
|
@ -4189,18 +4189,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"
|
||||||
|
|
|
@ -34,8 +34,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",
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -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>
|
||||||
|
|
|
@ -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,
|
||||||
{
|
{
|
||||||
|
|
|
@ -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';
|
||||||
|
@ -270,6 +278,13 @@ export const EmojiGroup = as<
|
||||||
</Box>
|
</Box>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
const NativeEmoji = (emoji: IEmoji) =>
|
||||||
|
isUsingTwemoji() ? <img
|
||||||
|
className={css.EmoticonImg}
|
||||||
|
src={getEmojiUrl(emoji.unicode)}
|
||||||
|
alt={emoji.shortcode}
|
||||||
|
/> : emoji.unicode;
|
||||||
|
|
||||||
export function EmojiItem({
|
export function EmojiItem({
|
||||||
label,
|
label,
|
||||||
type,
|
type,
|
||||||
|
@ -440,7 +455,7 @@ export function RecentEmojiGroup({
|
||||||
data={emoji.unicode}
|
data={emoji.unicode}
|
||||||
shortcode={emoji.shortcode}
|
shortcode={emoji.shortcode}
|
||||||
>
|
>
|
||||||
{emoji.unicode}
|
{NativeEmoji(emoji)}
|
||||||
</EmojiItem>
|
</EmojiItem>
|
||||||
))}
|
))}
|
||||||
</EmojiGroup>
|
</EmojiGroup>
|
||||||
|
@ -472,7 +487,7 @@ export function SearchEmojiGroup({
|
||||||
data={emoji.unicode}
|
data={emoji.unicode}
|
||||||
shortcode={emoji.shortcode}
|
shortcode={emoji.shortcode}
|
||||||
>
|
>
|
||||||
{emoji.unicode}
|
{NativeEmoji(emoji)}
|
||||||
</EmojiItem>
|
</EmojiItem>
|
||||||
) : (
|
) : (
|
||||||
<EmojiItem
|
<EmojiItem
|
||||||
|
@ -595,7 +610,7 @@ export const NativeEmojiGroups = memo(
|
||||||
data={emoji.unicode}
|
data={emoji.unicode}
|
||||||
shortcode={emoji.shortcode}
|
shortcode={emoji.shortcode}
|
||||||
>
|
>
|
||||||
{emoji.unicode}
|
{NativeEmoji(emoji)}
|
||||||
</EmojiItem>
|
</EmojiItem>
|
||||||
))}
|
))}
|
||||||
</EmojiGroup>
|
</EmojiGroup>
|
||||||
|
|
|
@ -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`;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -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
1
twemoji
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 310184baaae6f797e9ef2650bea35187242ffafb
|
|
@ -33,6 +33,10 @@ const copyFiles = {
|
||||||
src: 'public/res/android',
|
src: 'public/res/android',
|
||||||
dest: 'public/',
|
dest: 'public/',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
src: 'twemoji/assets/svg/*',
|
||||||
|
dest: 'twemoji/',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue