From 749c2f7961f9fa8307a53f338ada77b888e71553 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Tue, 31 Jan 2023 11:26:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=8D=87=E7=BA=A7emoji-mart=E7=9A=84?= =?UTF-8?q?=E7=89=88=E6=9C=AC:=20v3=20->=20v5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/web/package.json | 5 +- .../ChatBox/ChatMessageList/Item.less | 1 - .../ChatMessageList/VirtualizedList.tsx | 12 +++-- client/web/src/components/Emoji/Emoji.tsx | 17 ++++--- client/web/src/components/Emoji/Picker.tsx | 26 +++++----- client/web/src/components/Emoji/const.ts | 51 +------------------ client/web/src/components/Emoji/index.tsx | 17 +------ client/web/src/components/Emoji/types.ts | 8 +++ .../web/src/routes/Main/Navbar/GroupNav.tsx | 2 +- pnpm-lock.yaml | 46 +++++++++-------- 10 files changed, 75 insertions(+), 110 deletions(-) create mode 100644 client/web/src/components/Emoji/types.ts diff --git a/client/web/package.json b/client/web/package.json index e2985b46..6181b5c8 100644 --- a/client/web/package.json +++ b/client/web/package.json @@ -25,6 +25,8 @@ "plugins:declaration:generate": "cross-env TS_NODE_PROJECT='tsconfig.node.json' ts-node ./scripts/generate-plugin-declaration.typescript.ts" }, "dependencies": { + "@emoji-mart/data": "^1.1.2", + "@emoji-mart/react": "^1.1.1", "@loadable/component": "^5.15.2", "@tanstack/react-query-devtools": "^4.3.5", "@use-gesture/react": "^10.2.23", @@ -35,7 +37,7 @@ "compressorjs": "^1.1.1", "copy-to-clipboard": "^3.3.3", "detect-browser": "^5.3.0", - "emoji-mart": "^3.0.1", + "emoji-mart": "^5.5.2", "immer": "^9.0.16", "is-electron": "^2.2.1", "is-hotkey": "^0.2.0", @@ -81,7 +83,6 @@ "@testing-library/react-hooks": "^8.0.1", "@types/copy-webpack-plugin": "^8.0.1", "@types/dts-generator": "^2.1.7", - "@types/emoji-mart": "^3.0.9", "@types/fs-extra": "^9.0.13", "@types/is-hotkey": "^0.1.7", "@types/jest": "^29.2.4", diff --git a/client/web/src/components/ChatBox/ChatMessageList/Item.less b/client/web/src/components/ChatBox/ChatMessageList/Item.less index d62d9f51..dbae7a48 100644 --- a/client/web/src/components/ChatBox/ChatMessageList/Item.less +++ b/client/web/src/components/ChatBox/ChatMessageList/Item.less @@ -16,7 +16,6 @@ .chat-message-item_body { .emoji-mart-emoji { height: 16px; - vertical-align: middle; display: inline-block; margin: 0 4px; diff --git a/client/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx b/client/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx index a2922152..c263743c 100644 --- a/client/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx +++ b/client/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx @@ -69,9 +69,15 @@ export const VirtualizedMessageList: React.FC = React.memo( } ); - const computeItemKey = useMemoizedFn((index: number, item: ChatMessage) => { - return item?._id ?? index; - }); + const computeItemKey = useMemoizedFn( + (index: number, item?: ChatMessage) => { + if (!item) { + return index; + } + + return item._id; + } + ); const itemContent = useMemoizedFn((virtuosoIndex: number) => { const index = virtuosoIndex + numItemsPrepended - PREPEND_OFFSET; diff --git a/client/web/src/components/Emoji/Emoji.tsx b/client/web/src/components/Emoji/Emoji.tsx index 54c2746d..592b963a 100644 --- a/client/web/src/components/Emoji/Emoji.tsx +++ b/client/web/src/components/Emoji/Emoji.tsx @@ -1,12 +1,17 @@ -import { Emoji as OriginEmoji, EmojiProps } from 'emoji-mart'; import React from 'react'; +import { init } from 'emoji-mart'; +import { emojiData } from './const'; -interface Props extends Omit { +init({ set: 'twitter', data: emojiData }); + +interface Props { size?: number; + emoji: string; } -const Emoji: React.FC = React.memo((props) => { - return ; +export const Emoji: React.FC = React.memo((props) => { + const code = props.emoji.startsWith(':') ? props.emoji : `:${props.emoji}:`; // 对旧版兼容 + + // @ts-ignore + return ; }); Emoji.displayName = 'Emoji'; - -export default Emoji; diff --git a/client/web/src/components/Emoji/Picker.tsx b/client/web/src/components/Emoji/Picker.tsx index 4f2efa32..0651efd5 100644 --- a/client/web/src/components/Emoji/Picker.tsx +++ b/client/web/src/components/Emoji/Picker.tsx @@ -1,9 +1,10 @@ import React, { useCallback } from 'react'; -import { NimblePicker, EmojiData } from 'emoji-mart'; -import { isValidStr, useColorScheme } from 'tailchat-shared'; +import { isValidStr, useColorScheme, useLanguage } from 'tailchat-shared'; import { emojiData } from './const'; +import Picker from '@emoji-mart/react'; +import type { EmojiData } from './types'; +import i18n from '@emoji-mart/data/i18n/zh.json'; -import 'emoji-mart/css/emoji-mart.css'; import './Picker.less'; interface EmojiPickerProps { @@ -12,12 +13,15 @@ interface EmojiPickerProps { /** * emoji表情面板 + * + * Reference: https://www.npmjs.com/package/emoji-mart */ -const EmojiPicker: React.FC = React.memo((props) => { +export const EmojiPicker: React.FC = React.memo((props) => { const { isDarkMode } = useColorScheme(); + const { language } = useLanguage(); const handleSelect = useCallback( (emoji: EmojiData) => { - const code = emoji.colons; + const code = emoji.shortcodes; if (isValidStr(code)) { props.onSelect(code); } @@ -27,18 +31,16 @@ const EmojiPicker: React.FC = React.memo((props) => { return (
-
); }); EmojiPicker.displayName = 'EmojiPicker'; - -export default EmojiPicker; diff --git a/client/web/src/components/Emoji/const.ts b/client/web/src/components/Emoji/const.ts index 0636961f..b7d1e31a 100644 --- a/client/web/src/components/Emoji/const.ts +++ b/client/web/src/components/Emoji/const.ts @@ -1,50 +1,3 @@ -import type { Data } from 'emoji-mart'; -import data from 'emoji-mart/data/twitter.json'; +import data from '@emoji-mart/data/sets/5/twitter.json'; -export const emojiData: Data = { - compressed: true, - categories: [ - { - id: 'people', - name: 'Smileys & People', - emojis: data.categories[0].emojis, - }, - { - id: 'nature', - name: 'Animals & Nature', - emojis: data.categories[1].emojis, - }, - // { - // id: 'foods', - // name: 'Food & Drink', - // emojis: data.categories[2].emojis, - // }, - // { - // id: 'activity', - // name: 'Activities', - // emojis: data.categories[3].emojis, - // }, - // { - // id: 'places', - // name: 'Travel & Places', - // emojis: data.categories[4].emojis, - // }, - // { - // id: 'objects', - // name: 'Objects', - // emojis: data.categories[5].emojis, - // }, - // { - // id: 'symbols', - // name: 'Symbols', - // emojis: data.categories[6].emojis, - // }, - // { - // id: 'flags', - // name: 'Flags', - // emojis: data.categories[7].emojis, - // }, - ], - emojis: data.emojis, - aliases: data.aliases, -}; +export const emojiData = data; diff --git a/client/web/src/components/Emoji/index.tsx b/client/web/src/components/Emoji/index.tsx index cf731c11..bc8ee88b 100644 --- a/client/web/src/components/Emoji/index.tsx +++ b/client/web/src/components/Emoji/index.tsx @@ -1,19 +1,6 @@ import React from 'react'; -import { Loadable } from '../Loadable'; - -const Emoji = Loadable( - () => - import(/* webpackChunkName: 'emoji' */ /* webpackPreload: true */ './Emoji') -); - -const EmojiPicker = Loadable( - () => - import( - /* webpackChunkName: 'emoji-picker' */ /* webpackPreload: true */ './Picker' - ) -); - -export { Emoji }; +import { EmojiPicker } from './Picker'; +export { Emoji } from './Emoji'; /** * emoji表情面板 diff --git a/client/web/src/components/Emoji/types.ts b/client/web/src/components/Emoji/types.ts new file mode 100644 index 00000000..b5cccb06 --- /dev/null +++ b/client/web/src/components/Emoji/types.ts @@ -0,0 +1,8 @@ +export interface EmojiData { + id: string; + name: string; + native: string; + unified: string; + keywords: string[]; + shortcodes: string; +} diff --git a/client/web/src/routes/Main/Navbar/GroupNav.tsx b/client/web/src/routes/Main/Navbar/GroupNav.tsx index f4a9e8a0..7669f6af 100644 --- a/client/web/src/routes/Main/Navbar/GroupNav.tsx +++ b/client/web/src/routes/Main/Navbar/GroupNav.tsx @@ -11,7 +11,7 @@ import { useGroupUnread, } from 'tailchat-shared'; import { NavbarNavItem } from './NavItem'; -import { Dropdown, Menu } from 'antd'; +import { Dropdown } from 'antd'; /** * 群组导航栏栏项 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6a077a45..3fb086fc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -333,6 +333,8 @@ importers: client/web: specifiers: + '@emoji-mart/data': ^1.1.2 + '@emoji-mart/react': ^1.1.1 '@loadable/component': ^5.15.2 '@perfsee/webpack': 1.0.0-alpha.4 '@tanstack/react-query-devtools': ^4.3.5 @@ -341,7 +343,6 @@ importers: '@testing-library/react-hooks': ^8.0.1 '@types/copy-webpack-plugin': ^8.0.1 '@types/dts-generator': ^2.1.7 - '@types/emoji-mart': ^3.0.9 '@types/fs-extra': ^9.0.13 '@types/is-hotkey': ^0.1.7 '@types/jest': ^29.2.4 @@ -379,7 +380,7 @@ importers: detect-browser: ^5.3.0 dotenv: ^10.0.0 dts-generator: ^3.0.0 - emoji-mart: ^3.0.1 + emoji-mart: ^5.5.2 esbuild-loader: ^2.20.0 execa: ^5.1.1 file-loader: ^6.2.0 @@ -455,6 +456,8 @@ importers: yup: ^0.32.11 zustand: ^4.1.5 dependencies: + '@emoji-mart/data': 1.1.2 + '@emoji-mart/react': 1.1.1_kyrnz3vmphzqyjjk2ivrm6bcsu '@loadable/component': 5.15.2_react@18.2.0 '@tanstack/react-query-devtools': 4.3.5_biqbaboplfbrettd7655fr4n2y '@use-gesture/react': 10.2.23_react@18.2.0 @@ -465,7 +468,7 @@ importers: compressorjs: 1.1.1 copy-to-clipboard: 3.3.3 detect-browser: 5.3.0 - emoji-mart: 3.0.1_react@18.2.0 + emoji-mart: 5.5.2 immer: 9.0.16 is-electron: 2.2.1 is-hotkey: 0.2.0 @@ -510,7 +513,6 @@ importers: '@testing-library/react-hooks': 8.0.1_7ey2zzynotv32rpkwno45fsx4e '@types/copy-webpack-plugin': 8.0.1_webpack-cli@4.10.0 '@types/dts-generator': 2.1.7 - '@types/emoji-mart': 3.0.9 '@types/fs-extra': 9.0.13 '@types/is-hotkey': 0.1.7 '@types/jest': 29.2.4 @@ -6596,6 +6598,20 @@ packages: - webpack-cli dev: false + /@emoji-mart/data/1.1.2: + resolution: {integrity: sha512-1HP8BxD2azjqWJvxIaWAMyTySeZY0Osr83ukYjltPVkNXeJvTz7yDrPLBtnrD5uqJ3tg4CcLuuBW09wahqL/fg==} + dev: false + + /@emoji-mart/react/1.1.1_kyrnz3vmphzqyjjk2ivrm6bcsu: + resolution: {integrity: sha512-NMlFNeWgv1//uPsvLxvGQoIerPuVdXwK/EUek8OOkJ6wVOWPUizRBJU0hDqWZCOROVpfBgCemaC3m6jDOXi03g==} + peerDependencies: + emoji-mart: ^5.2 + react: ^16.8 || ^17 || ^18 + dependencies: + emoji-mart: 5.5.2 + react: 18.2.0 + dev: false + /@emotion/babel-plugin/11.10.2: resolution: {integrity: sha512-xNQ57njWTFVfPAc3cjfuaPdsgLp5QOSuRsj9MA6ndEhH/AzuZM86qIQzt6rq+aGBwj3n5/TkLmU5lhAfdRmogA==} peerDependencies: @@ -12861,12 +12877,6 @@ packages: resolution: {integrity: sha512-RQul5wEfY7BjWm0sYY86cmUN/pcXWGyVxWX93DFFJvcrxax5zKlieLwA3T77xJGwNcZW0YW6CYG70p1m8xPFmA==} dev: true - /@types/emoji-mart/3.0.9: - resolution: {integrity: sha512-qdBo/2Y8MXaJ/2spKjDZocuq79GpnOhkwMHnK2GnVFa8WYFgfA+ei6sil3aeWQPCreOKIx9ogPpR5+7MaOqYAA==} - dependencies: - '@types/react': 18.0.26 - dev: true - /@types/eslint-scope/3.7.4: resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==} dependencies: @@ -15697,7 +15707,7 @@ packages: babel-plugin-syntax-jsx: 6.18.0 lodash: 4.17.21 picomatch: 2.3.1 - styled-components: 5.3.6_react@18.2.0 + styled-components: 5.3.6_7i5myeigehqah43i5u7wbekgba /babel-plugin-syntax-jsx/6.18.0: resolution: {integrity: sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==} @@ -19458,14 +19468,8 @@ packages: engines: {node: '>=10'} dev: true - /emoji-mart/3.0.1_react@18.2.0: - resolution: {integrity: sha512-sxpmMKxqLvcscu6mFn9ITHeZNkGzIvD0BSNFE/LJESPbCA8s1jM6bCDPjWbV31xHq7JXaxgpHxLB54RCbBZSlg==} - peerDependencies: - react: ^0.14.0 || ^15.0.0-0 || ^16.0.0 || ^17.0.0 - dependencies: - '@babel/runtime': 7.20.6 - prop-types: 15.8.1 - react: 18.2.0 + /emoji-mart/5.5.2: + resolution: {integrity: sha512-Sqc/nso4cjxhOwWJsp9xkVm8OF5c+mJLZJFoFfzRuKO+yWiN7K8c96xmtughYb0d/fZ8UC6cLIQ/p4BR6Pv3/A==} dev: false /emoji-regex/7.0.3: @@ -24435,7 +24439,7 @@ packages: pretty-format: 27.5.1 slash: 3.0.0 strip-json-comments: 3.1.1 - ts-node: 10.9.1_k2dsl7zculo2nmh5s33pladmoa + ts-node: 10.9.1_nzafxra4mdyuer2ejmql6rdadq transitivePeerDependencies: - bufferutil - canvas @@ -35903,7 +35907,6 @@ packages: react-is: 18.2.0 shallowequal: 1.1.0 supports-color: 5.5.0 - dev: false /styled-components/5.3.6_mdz3marskokvq6744hhidi3r5a: resolution: {integrity: sha512-hGTZquGAaTqhGWldX7hhfzjnIYBZ0IXQXkCYdvF1Sq3DsUaLx6+NTHC5Jj1ooM2F68sBiVz3lvhfwQs/S3l6qg==} @@ -35949,6 +35952,7 @@ packages: react: 18.2.0 shallowequal: 1.1.0 supports-color: 5.5.0 + dev: true /styled-system/5.1.5: resolution: {integrity: sha512-7VoD0o2R3RKzOzPK0jYrVnS8iJdfkKsQJNiLRDjikOpQVqQHns/DXWaPZOH4tIKkhAT7I6wIsy9FWTWh2X3q+A==}