diff --git a/app/soapbox/actions/compose.ts b/app/soapbox/actions/compose.ts index 23913de151..3aa80fe1db 100644 --- a/app/soapbox/actions/compose.ts +++ b/app/soapbox/actions/compose.ts @@ -484,7 +484,9 @@ const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) => }, 200, { leading: true, trailing: true }); const fetchComposeSuggestionsEmojis = (dispatch: AppDispatch, getState: () => RootState, token: string) => { - const results = emojiSearch(token.replace(':', ''), { maxResults: 5 } as any); + const state = getState(); + const results = emojiSearch(token.replace(':', ''), { maxResults: 5 }, state.custom_emojis); + dispatch(readyComposeSuggestionsEmojis(token, results)); }; diff --git a/app/soapbox/features/emoji/index.ts b/app/soapbox/features/emoji/index.ts index 676cfbcd73..91e57c5d5a 100644 --- a/app/soapbox/features/emoji/index.ts +++ b/app/soapbox/features/emoji/index.ts @@ -5,7 +5,7 @@ import { parseDocument } from 'htmlparser2'; import unicodeMapping from './mapping'; import type { Node as CheerioNode } from 'cheerio'; -import type { Emoji as EmojiMartEmoji } from 'emoji-mart'; +import type { Emoji as EmojiMart, CustomEmoji } from 'emoji-mart'; // export interface Emoji { // id: string, @@ -150,7 +150,7 @@ const emojify = (str: string, customEmojis = {}) => { export default emojify; export const buildCustomEmojis = (customEmojis: any) => { - const emojis: EmojiMartEmoji[] = []; + const emojis: EmojiMart[] = []; customEmojis.forEach((emoji: any) => { const shortcode = emoji.get('shortcode'); diff --git a/app/soapbox/features/emoji/search.ts b/app/soapbox/features/emoji/search.ts index 33a090cd10..7f5a6b9eef 100644 --- a/app/soapbox/features/emoji/search.ts +++ b/app/soapbox/features/emoji/search.ts @@ -1,20 +1,54 @@ -// import data from './data'; -// import { getData, getSanitizedData, uniq, intersect } from './utils'; +import { Index } from 'flexsearch'; + +import data from './data'; + +import type { Emoji, CustomEmoji } from 'emoji-mart'; + +const index = new Index({ + tokenize: 'forward', + optimize: true, +}); + +for (const [key, emoji] of Object.entries(data.emojis)) { + index.add(key, emoji.name); +} export interface searchOptions { maxResults?: number; } -export interface Emoji { +export const addCustomToPool = (customEmojis: Emoji[]) => { + let i = 0; -} - -export const addCustomToPool = (customEmojis: Emoji[]) => { + for (const emoji of customEmojis) { + index.add(i++, emoji.id); + } }; -const search = (str: string, options: searchOptions) => { - console.log(str, options); - return []; +const search = (str: string, options: searchOptions, custom_emojis: any) => { + return index.search(str, options.maxResults) + .flatMap(id => { + if (Number.isInteger(id)) { + const { shortcode, static_url } = custom_emojis.get(id).toJS(); + return { + id: shortcode, + colons: ':' + shortcode + ':', + emoticons: [], + custom: true, + imageUrl: static_url, + }; + } + + const { name, skins } = data.emojis[id]; + + return { + id: name, + colons: ':' + name + ':', + emoticons: [], + unified: skins[0].unified, + native: skins[0].native, + }; + }); }; export default search; diff --git a/package.json b/package.json index 240b31ee40..5cf5c53b84 100644 --- a/package.json +++ b/package.json @@ -115,12 +115,12 @@ "dotenv": "^8.0.0", "emoji-datasource": "5.0.0", "emoji-mart": "^5.1.0", - "emoji-mart-old": "npm:emoji-mart-lazyload", "entities": "^4.3.1", "es6-symbol": "^3.1.1", "escape-html": "^1.0.3", "exif-js": "^2.3.0", "feather-icons": "^4.28.0", + "flexsearch": "^0.7.21", "fork-ts-checker-webpack-plugin": "^7.2.11", "history": "^4.10.1", "html-webpack-harddisk-plugin": "^2.0.0", @@ -209,6 +209,7 @@ "@testing-library/jest-dom": "^5.16.4", "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.0.3", + "@types/flexsearch": "^0.7.3", "@typescript-eslint/eslint-plugin": "^5.15.0", "@typescript-eslint/parser": "^5.15.0", "babel-eslint": "^10.1.0", @@ -225,7 +226,6 @@ "fake-indexeddb": "^3.1.7", "husky": "^7.0.2", "jest": "^27.5.1", - "jest-bench": "^27.5.1", "jest-junit": "^13.2.0", "lint-staged": ">=10", "raf": "^3.4.1", diff --git a/types/emoji-mart/index.d.ts b/types/emoji-mart/index.d.ts index 0be86505b8..d7e809b35d 100644 --- a/types/emoji-mart/index.d.ts +++ b/types/emoji-mart/index.d.ts @@ -1,17 +1,26 @@ + declare module 'emoji-mart' { - export interface EmojiSkin { + export interface NativeEmoji { + unified: string, + native: string, + x: number, + y: number, + } + + export interface CustomEmoji { src: string } - export interface Emoji { + export interface Emoji { id: string, name: string, keywords: string[], - skins: EmojiSkin[], + skins: T[], + version?: number, } export interface PickerProps { - custom?: { emojis: Emoji[] }[], + custom?: { emojis: Emoji }[], set?: string, title?: string, theme?: string, @@ -22,8 +31,6 @@ declare module 'emoji-mart' { emojiSize?: number, emojiButtonSize?: number, navPosition?: string, - set?: string, - theme?: string, autoFocus?: boolean, i18n?: any, } @@ -37,28 +44,32 @@ declare module 'emoji-mart' { } declare module '@emoji-mart/data/sets/14/twitter.json' { - export interface EmojiSkin { + export interface NativeEmoji { unified: string, native: string, x: number, y: number, } + export interface CustomEmoji { + src: string + } + + export interface Emoji { + id: string, + name: string, + keywords: string[], + skins: T[], + version?: number, + } + export interface EmojiCategory { id: string, emojis: string[], } - export interface Emoji { - id: string, - name: string, - keywords: string[], - skins: EmojiSkin[], - version: number, - } - export interface EmojiMap { - [s: string]: Emoji, + [s: string]: Emoji, } export interface EmojiAlias { diff --git a/yarn.lock b/yarn.lock index 4963eb84da..61cfe48636 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2527,6 +2527,11 @@ resolved "https://registry.yarnpkg.com/@types/filewriter/-/filewriter-0.0.29.tgz#a48795ecadf957f6c0d10e0c34af86c098fa5bee" integrity sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ== +"@types/flexsearch@^0.7.3": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@types/flexsearch/-/flexsearch-0.7.3.tgz#ee79b1618035c82284278e05652e91116765b634" + integrity sha512-HXwADeHEP4exXkCIwy2n1+i0f1ilP1ETQOH5KDOugjkTFZPntWo0Gr8stZOaebkxsdx+k0X/K6obU/+it07ocg== + "@types/fs-extra@^9.0.1": version "9.0.13" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.13.tgz#7594fbae04fe7f1918ce8b3d213f74ff44ac1f45" @@ -3770,14 +3775,6 @@ before-after-hook@^2.2.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e" integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ== -benchmark@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/benchmark/-/benchmark-2.1.4.tgz#09f3de31c916425d498cc2ee565a0ebf3c2a5629" - integrity sha512-l9MlfN4M1K/H2fbhfMy3B7vJd6AGKJVQn2h6Sg/Yx+KckoUA7ewS5Vv6TjSq18ooE1kS9hhAlQRH3AkXIh/aOQ== - dependencies: - lodash "^4.17.4" - platform "^1.3.3" - big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" @@ -5900,6 +5897,11 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561" integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA== +flexsearch@^0.7.21: + version "0.7.21" + resolved "https://registry.yarnpkg.com/flexsearch/-/flexsearch-0.7.21.tgz#0f5ede3f2aae67ddc351efbe3b24b69d29e9d48b" + integrity sha512-W7cHV7Hrwjid6lWmy0IhsWDFQboWSng25U3VVywpHOTJnnAZNPScog67G+cVpeX9f7yDD21ih0WDrMMT+JoaYg== + follow-redirects@^1.0.0: version "1.14.4" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379" @@ -7139,18 +7141,6 @@ istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jest-bench@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-bench/-/jest-bench-27.5.1.tgz#407077e8d84883e6dffe7f449671be4639d0d255" - integrity sha512-mGdENN4ozZE5LMM8bZUfPFZUgCpb5UNIRgzOGGF1DtZ5iIVqpzR0nybdLfbGWSTZt42jZ+cam4Y0Ge//izJ33A== - dependencies: - "@jest/globals" "^27.5.1" - "@jest/reporters" "^27.5.1" - benchmark "^2.1.4" - chalk "^4.1.0" - lodash "^4.17.20" - ndjson "^2.0.0" - jest-changed-files@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5" @@ -7768,11 +7758,6 @@ json-stable-stringify@^1.0.1: dependencies: jsonify "~0.0.0" -json-stringify-safe@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== - json5@2.x: version "2.2.0" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" @@ -8196,7 +8181,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.0.1, lodash@^4.17.10, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0, lodash@^4.7.11: +lodash@^4.0.1, lodash@^4.17.10, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0, lodash@^4.7.11: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -8596,17 +8581,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -ndjson@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ndjson/-/ndjson-2.0.0.tgz#320ac86f6fe53f5681897349b86ac6f43bfa3a19" - integrity sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ== - dependencies: - json-stringify-safe "^5.0.1" - minimist "^1.2.5" - readable-stream "^3.6.0" - split2 "^3.0.0" - through2 "^4.0.0" - negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" @@ -9164,11 +9138,6 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -platform@^1.3.3: - version "1.3.6" - resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7" - integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg== - please-upgrade-node@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" @@ -10099,15 +10068,6 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - readable-stream@^2.0.1, readable-stream@^2.3.3: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" @@ -10121,6 +10081,15 @@ readable-stream@^2.0.1, readable-stream@^2.3.3: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^3.0.6, readable-stream@^3.1.1: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -10871,13 +10840,6 @@ split-on-first@^1.0.0: resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== -split2@^3.0.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" - integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg== - dependencies: - readable-stream "^3.0.0" - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -11366,13 +11328,6 @@ throat@^6.0.1: resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== -through2@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764" - integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw== - dependencies: - readable-stream "3" - through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"