diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8f9bfed --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "twemoji"] + path = twemoji + url = https://github.com/jdecked/twemoji diff --git a/package-lock.json b/package-lock.json index 1b65135..bdcede3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,8 +24,8 @@ "dateformat": "5.0.3", "dayjs": "1.11.10", "domhandler": "5.0.3", - "emojibase": "15.3.0", - "emojibase-data": "15.3.0", + "emojibase": "15.2.0", + "emojibase-data": "15.2.0", "file-saver": "2.0.5", "flux": "4.0.3", "focus-trap-react": "10.0.2", @@ -61,7 +61,6 @@ "slate-history": "0.93.0", "slate-react": "0.98.4", "tippy.js": "6.3.7", - "twemoji": "14.0.2", "ua-parser-js": "1.0.35" }, "devDependencies": { @@ -4076,18 +4075,18 @@ "dev": true }, "node_modules/emojibase": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/emojibase/-/emojibase-15.3.0.tgz", - "integrity": "sha512-lFdQb14hoznwDh1xDoOFzkPdeeexmbuJdhUUjDaJZf/+jK+6Z3HkI5hWOemWfEdaMxtTujc1vNRx9DKtdtiOXA==", + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/emojibase/-/emojibase-15.2.0.tgz", + "integrity": "sha512-gB6rIVtyJPersQvAo4nOGYPeILMhlcfZdiwCWVeRAtkJ7sm0tExZETGyLhrTQcHvZQhDEYI1vlCeqUhn5gZkQA==", "funding": { "type": "ko-fi", "url": "https://ko-fi.com/milesjohnson" } }, "node_modules/emojibase-data": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/emojibase-data/-/emojibase-data-15.3.0.tgz", - "integrity": "sha512-cYsGq57W8wOd1CqQCjmtP1DpmlTVvJY+Um5UobWUQuTnqb8cO2cuqrxJxSIqxLcYZ3rtialT5kivoWigszdslg==", + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/emojibase-data/-/emojibase-data-15.2.0.tgz", + "integrity": "sha512-hDiw4ugxnI4pcVQO+73NlKx6aZP/A+BAPfDgK/3A83RVbHZa0Ut6GHpd5r5XUV9G7BZhKejlIRuxhXialpbt6Q==", "funding": { "type": "ko-fi", "url": "https://ko-fi.com/milesjohnson" @@ -4988,27 +4987,6 @@ "react": ">=16.8.0" } }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-extra/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -5227,7 +5205,8 @@ "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true }, "node_modules/grapheme-splitter": { "version": "1.0.4", @@ -5870,17 +5849,6 @@ "node": ">=6" } }, - "node_modules/jsonfile": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-5.0.0.tgz", - "integrity": "sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w==", - "dependencies": { - "universalify": "^0.1.2" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/jsx-ast-utils": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", @@ -7686,22 +7654,6 @@ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "node_modules/twemoji": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/twemoji/-/twemoji-14.0.2.tgz", - "integrity": "sha512-BzOoXIe1QVdmsUmZ54xbEH+8AgtOKUiG53zO5vVP2iUu6h5u9lN15NcuS6te4OY96qx0H7JK9vjjl9WQbkTRuA==", - "dependencies": { - "fs-extra": "^8.0.1", - "jsonfile": "^5.0.0", - "twemoji-parser": "14.0.0", - "universalify": "^0.1.2" - } - }, - "node_modules/twemoji-parser": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/twemoji-parser/-/twemoji-parser-14.0.0.tgz", - "integrity": "sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA==" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -7777,14 +7729,6 @@ "resolved": "https://registry.npmjs.org/unhomoglyph/-/unhomoglyph-1.0.6.tgz", "integrity": "sha512-7uvcWI3hWshSADBu4JpnyYbTVc7YlhF5GDW/oPD5AxIxl34k4wXR3WDkPnzLxkN32LiTCTKMQLtKVZiwki3zGg==" }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/update-browserslist-db": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", diff --git a/package.json b/package.json index c4d0170..447624a 100644 --- a/package.json +++ b/package.json @@ -19,60 +19,16 @@ "author": "Ajay Bura", "license": "AGPL-3.0-only", "dependencies": { - "@fontsource/inter": "4.5.14", - "@khanacademy/simple-markdown": "0.8.6", - "@matrix-org/olm": "3.2.14", - "@tanstack/react-virtual": "3.0.0-beta.54", - "@tippyjs/react": "4.2.6", "@vanilla-extract/css": "1.9.3", "@vanilla-extract/recipes": "0.3.0", - "@vanilla-extract/vite-plugin": "3.7.1", - "await-to-js": "3.0.0", "blurhash": "2.0.4", - "browser-encrypt-attachment": "0.3.0", "classnames": "2.3.2", - "dateformat": "5.0.3", - "dayjs": "1.11.10", - "domhandler": "5.0.3", - "emojibase": "15.3.0", - "emojibase-data": "15.3.0", - "file-saver": "2.0.5", - "flux": "4.0.3", - "focus-trap-react": "10.0.2", - "folds": "1.5.0", - "formik": "2.2.9", - "html-dom-parser": "4.0.0", - "html-react-parser": "4.2.0", - "immer": "9.0.16", - "is-hotkey": "0.2.0", - "jotai": "1.12.0", - "katex": "0.16.4", - "linkify-html": "4.0.2", - "linkify-react": "4.1.1", + "emojibase": "15.2.0", "linkifyjs": "4.0.2", - "matrix-js-sdk": "24.1.0", - "millify": "6.1.0", - "pdfjs-dist": "3.10.111", - "prismjs": "1.29.0", "prop-types": "15.8.1", "react": "17.0.2", - "react-aria": "3.29.1", - "react-autosize-textarea": "7.1.0", - "react-blurhash": "0.2.0", - "react-dnd": "15.1.2", - "react-dnd-html5-backend": "15.1.3", "react-dom": "17.0.2", - "react-error-boundary": "4.0.10", - "react-google-recaptcha": "2.1.0", - "react-modal": "3.16.1", - "react-range": "1.8.14", - "sanitize-html": "2.8.0", - "slate": "0.94.1", - "slate-history": "0.93.0", - "slate-react": "0.98.4", - "tippy.js": "6.3.7", - "twemoji": "14.0.2", - "ua-parser-js": "1.0.35" + "slate": "0.94.1" }, "devDependencies": { "@esbuild-plugins/node-globals-polyfill": "0.2.3", @@ -103,4 +59,4 @@ "vite": "4.3.9", "vite-plugin-static-copy": "0.13.0" } -} +} \ No newline at end of file diff --git a/public/font/Twemoji.Mozilla.v0.7.0+sup39.240115.ttf b/public/font/Twemoji.Mozilla.v0.7.0+sup39.240115.ttf deleted file mode 100644 index e76d894..0000000 Binary files a/public/font/Twemoji.Mozilla.v0.7.0+sup39.240115.ttf and /dev/null differ diff --git a/public/font/Twemoji.Mozilla.v0.7.0+sup39.240115.woff2 b/public/font/Twemoji.Mozilla.v0.7.0+sup39.240115.woff2 deleted file mode 100644 index 9099020..0000000 Binary files a/public/font/Twemoji.Mozilla.v0.7.0+sup39.240115.woff2 and /dev/null differ diff --git a/src/app/components/editor/Elements.tsx b/src/app/components/editor/Elements.tsx index c4767ab..3f4fd49 100644 --- a/src/app/components/editor/Elements.tsx +++ b/src/app/components/editor/Elements.tsx @@ -11,6 +11,7 @@ import { import * as css from '../../styles/CustomHtml.css'; import { CommandElement, EmoticonElement, LinkElement, MentionElement } from './slate'; import { useMatrixClient } from '../../hooks/useMatrixClient'; +import { getEmojiUrl, isUsingTwemoji } from '../../plugins/emoji'; import { getBeginCommand } from './utils'; import { BlockType } from './types'; @@ -94,7 +95,11 @@ function RenderEmoticonElement({ alt={element.shortcode} /> ) : ( - element.key + isUsingTwemoji() ? {element.shortcode} : element.key )} {children} diff --git a/src/app/components/emoji-board/EmojiBoard.css.tsx b/src/app/components/emoji-board/EmojiBoard.css.tsx index ba4ca4e..58e8431 100644 --- a/src/app/components/emoji-board/EmojiBoard.css.tsx +++ b/src/app/components/emoji-board/EmojiBoard.css.tsx @@ -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([ DefaultReset, { diff --git a/src/app/components/emoji-board/EmojiBoard.tsx b/src/app/components/emoji-board/EmojiBoard.tsx index 5452722..6cb03d7 100644 --- a/src/app/components/emoji-board/EmojiBoard.tsx +++ b/src/app/components/emoji-board/EmojiBoard.tsx @@ -34,7 +34,15 @@ import { MatrixClient, Room } from 'matrix-js-sdk'; import { atom, useAtomValue, useSetAtom } from 'jotai'; 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 { IEmojiGroupIcons, useEmojiGroupIcons } from './useEmojiGroupIcons'; import { preventScrollWithArrowKey } from '../../utils/keyboard'; @@ -439,9 +447,13 @@ export function RecentEmojiGroup({ type={EmojiType.Emoji} data={emoji.unicode} shortcode={emoji.shortcode} - > - {emoji.unicode} - + >{ + isUsingTwemoji() ? {emoji.shortcode} : emoji.unicode + } ))} ); diff --git a/src/app/plugins/emoji.ts b/src/app/plugins/emoji.ts index 2462b7f..24217cc 100644 --- a/src/app/plugins/emoji.ts +++ b/src/app/plugins/emoji.ts @@ -112,3 +112,13 @@ emojisData.forEach((emoji) => { 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`; +} diff --git a/src/app/plugins/react-custom-html-parser.tsx b/src/app/plugins/react-custom-html-parser.tsx index ee41687..2924961 100644 --- a/src/app/plugins/react-custom-html-parser.tsx +++ b/src/app/plugins/react-custom-html-parser.tsx @@ -17,7 +17,7 @@ import * as css from '../styles/CustomHtml.css'; import { getMxIdLocalPart, getRoomWithCanonicalAlias } from '../utils/matrix'; import { getMemberDisplayName } from '../utils/room'; 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'; const ReactPrism = lazy(() => import('./react-prism/ReactPrism')); @@ -39,13 +39,21 @@ const textToEmojifyJSX = (text: string): (string | JSX.Element)[] => findAndReplace( text, EMOJI_REG_G, - (match, pushIndex) => ( - - - {match[0]} - - - ), + (match, pushIndex) => { + const char = match[0]; + const className = css.Emoticon(); + const title = getShortcodeFor(getHexcodeForEmoji(char)); + return { + isUsingTwemoji() ? : {match[0]} + }; + }, (txt) => txt ); diff --git a/src/index.scss b/src/index.scss index f7f286e..c3cd13c 100644 --- a/src/index.scss +++ b/src/index.scss @@ -1,12 +1,5 @@ @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 { /* background color | --bg-[background type]: value */ --bg-surface: #ffffff; diff --git a/twemoji b/twemoji new file mode 160000 index 0000000..310184b --- /dev/null +++ b/twemoji @@ -0,0 +1 @@ +Subproject commit 310184baaae6f797e9ef2650bea35187242ffafb diff --git a/vite.config.js b/vite.config.js index 8357339..294bcfe 100644 --- a/vite.config.js +++ b/vite.config.js @@ -33,6 +33,10 @@ const copyFiles = { src: 'public/res/android', dest: 'public/', }, + { + src: 'twemoji/assets/svg/*', + dest: 'twemoji/', + }, ], }