From eca880ac1f75b3dfe138965e41ea528e9b6d06a2 Mon Sep 17 00:00:00 2001 From: mahmed2000 Date: Sat, 9 Nov 2024 21:58:38 +0000 Subject: [PATCH] Replace picmo with emoji-mart (#4001) * Add emoji-mart deps * Change EmojiPicker to use emoji-mart * Change ChatTextField to work with the emoji-mart data object * Remove picmo, commit package-lock * Fix mutant svgs having a size of 0 * Get the custom emojis to show up earlier in the picker * Set emoji-mart to exact semver. Later versions break custom category sorting. --- .../chat/ChatTextField/ChatTextField.tsx | 25 +++----- .../chat/ChatTextField/EmojiPicker.tsx | 60 ++++++++++--------- web/package-lock.json | 49 +++++++-------- web/package.json | 8 ++- 4 files changed, 72 insertions(+), 70 deletions(-) diff --git a/web/components/chat/ChatTextField/ChatTextField.tsx b/web/components/chat/ChatTextField/ChatTextField.tsx index 1183a37b2..224fb5725 100644 --- a/web/components/chat/ChatTextField/ChatTextField.tsx +++ b/web/components/chat/ChatTextField/ChatTextField.tsx @@ -152,15 +152,14 @@ export const ChatTextField: FC = ({ defaultText, enabled, fo contentEditable.innerHTML += textToInsert; }; - // Native emoji - const onEmojiSelect = (emoji: string) => { - insertTextAtEnd(emoji); - }; - - // Custom emoji images - const onCustomEmojiSelect = (name: string, emoji: string) => { - const html = `:${name}:`; - insertTextAtEnd(html); + const onEmojiSelect = emoji => { + if (emoji.native) { + insertTextAtEnd(emoji.native); + } else { + // Custom emoji images + const html = `:${emoji.name}:`; + insertTextAtEnd(html); + } }; const onKeyDown = (e: React.KeyboardEvent) => { @@ -277,13 +276,7 @@ export const ChatTextField: FC = ({ defaultText, enabled, fo {enabled && (
- } + content={} trigger="click" placement="topRight" > diff --git a/web/components/chat/ChatTextField/EmojiPicker.tsx b/web/components/chat/ChatTextField/EmojiPicker.tsx index fbaf341f8..fc8fef0a1 100644 --- a/web/components/chat/ChatTextField/EmojiPicker.tsx +++ b/web/components/chat/ChatTextField/EmojiPicker.tsx @@ -1,42 +1,44 @@ -import React, { FC, useEffect, useRef } from 'react'; -import { createPicker } from 'picmo'; +import React, { FC, useEffect, useState } from 'react'; +import Picker from '@emoji-mart/react'; +import data from '@emoji-mart/data'; export type EmojiPickerProps = { - onEmojiSelect: (emoji: string) => void; - onCustomEmojiSelect: (name: string, url: string) => void; + onEmojiSelect: (emoji) => void; customEmoji: any[]; }; -export const EmojiPicker: FC = ({ - onEmojiSelect, - onCustomEmojiSelect, - customEmoji, -}) => { - const ref = useRef(); - +export const EmojiPicker: FC = ({ onEmojiSelect, customEmoji }) => { + const [custom, setCustom] = useState({}); + const categories = [ + 'frequent', + 'custom', // same id as in the setCustom call below + 'people', + 'nature', + 'foods', + 'activity', + 'places', + 'objects', + 'symbols', + 'flags', + ]; // Recreate the emoji picker when the custom emoji changes. useEffect(() => { const e = customEmoji.map(emoji => ({ - emoji: emoji.name, - label: emoji.name, - url: emoji.url, + id: emoji.name, + name: emoji.name, + skins: [{ src: emoji.url }], })); - const picker = createPicker({ - rootElement: ref.current, - custom: e, - initialCategory: 'custom', - showPreview: false, - showRecents: true, - }); - picker.addEventListener('emoji:select', event => { - if (event.url) { - onCustomEmojiSelect(event.label, event.url); - } else { - onEmojiSelect(event.emoji); - } - }); + setCustom([{ id: 'custom', name: 'Custom', emojis: e }]); + + // hack to make the picker work with viewbox only svgs, 24px is default size + const shadow = document.querySelector('em-emoji-picker').shadowRoot; + const pickerStyles = new CSSStyleSheet(); + pickerStyles.replaceSync('.emoji-mart-emoji {width: 24px;}'); + shadow.adoptedStyleSheets = [pickerStyles]; }, []); - return
; + return ( + + ); }; diff --git a/web/package-lock.json b/web/package-lock.json index 32eb3f3f0..98f4440e5 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -14,6 +14,8 @@ "@codemirror/lang-javascript": "^6.1.2", "@codemirror/lang-markdown": "6.3.1", "@codemirror/language-data": "6.5.1", + "@emoji-mart/data": "^1.2.1", + "@emoji-mart/react": "^1.1.1", "@fontsource/inter": "^5.0.0", "@fontsource/poppins": "5.1.0", "@next/bundle-analyzer": "^14.0.0", @@ -33,7 +35,6 @@ "next": "14.2.17", "next-pwa": "^5.6.0", "next-with-less": "3.0.1", - "picmo": "5.8.5", "postcss-flexbugs-fixes": "5.0.2", "react": "18.3.1", "react-chartjs-2": "^5.2.0", @@ -3278,6 +3279,22 @@ "tslib": "^2.4.0" } }, + "node_modules/@emoji-mart/data": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emoji-mart/data/-/data-1.2.1.tgz", + "integrity": "sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw==", + "license": "MIT" + }, + "node_modules/@emoji-mart/react": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@emoji-mart/react/-/react-1.1.1.tgz", + "integrity": "sha512-NMlFNeWgv1//uPsvLxvGQoIerPuVdXwK/EUek8OOkJ6wVOWPUizRBJU0hDqWZCOROVpfBgCemaC3m6jDOXi03g==", + "license": "MIT", + "peerDependencies": { + "emoji-mart": "^5.2", + "react": "^16.8 || ^17 || ^18" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", @@ -14563,6 +14580,13 @@ "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, + "node_modules/emoji-mart": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-5.2.2.tgz", + "integrity": "sha512-BvcrX+Ps9MxSVEjnvxupclU3MBD6WVC4WZOY26csfC6oFdaWpFhdrzeVNVBmCLPOmzY1SE0aAsqZJRNVbZ1yhQ==", + "license": "MIT", + "peer": true + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -14570,16 +14594,6 @@ "dev": true, "license": "MIT" }, - "node_modules/emojibase": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/emojibase/-/emojibase-6.1.0.tgz", - "integrity": "sha512-1GkKJPXP6tVkYJHOBSJHoGOr/6uaDxZ9xJ6H7m6PfdGXTmQgbALHLWaVRY4Gi/qf5x/gT/NUXLPuSHYLqtLtrQ==", - "license": "MIT", - "funding": { - "type": "ko-fi", - "url": "https://ko-fi.com/milesjohnson" - } - }, "node_modules/emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", @@ -32757,19 +32771,6 @@ "dev": true, "license": "MIT" }, - "node_modules/picmo": { - "version": "5.8.5", - "resolved": "https://registry.npmjs.org/picmo/-/picmo-5.8.5.tgz", - "integrity": "sha512-7I8jfuHALF9lkt3d+XCZGP+IwH7g91vYZv6XtRnJ99IDjnm92zel0L5DEo2FX0oaHUwRMBD/kn2knTZqwItudQ==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "license": "MIT", - "dependencies": { - "emojibase": "^6.1.0" - }, - "funding": { - "url": "https://github.com/sponsors/joeattardi" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", diff --git a/web/package.json b/web/package.json index 2c846b6a8..10c4e8ae3 100644 --- a/web/package.json +++ b/web/package.json @@ -23,6 +23,8 @@ "@codemirror/lang-javascript": "^6.1.2", "@codemirror/lang-markdown": "6.3.1", "@codemirror/language-data": "6.5.1", + "@emoji-mart/data": "^1.2.1", + "@emoji-mart/react": "^1.1.1", "@fontsource/inter": "^5.0.0", "@fontsource/poppins": "5.1.0", "@next/bundle-analyzer": "^14.0.0", @@ -42,7 +44,6 @@ "next": "14.2.17", "next-pwa": "^5.6.0", "next-with-less": "3.0.1", - "picmo": "5.8.5", "postcss-flexbugs-fixes": "5.0.2", "react": "18.3.1", "react-chartjs-2": "^5.2.0", @@ -137,5 +138,10 @@ "stylelint-config-standard-scss": "^13.0.0", "ts-jest": "^29.1.0", "typescript": "5.6.3" + }, + "overrides": { + "@emoji-mart/react": { + "emoji-mart": "~5.2.2" + } } }