diff --git a/src/libs/EmojiTrie.js b/src/libs/EmojiTrie.ts similarity index 53% rename from src/libs/EmojiTrie.js rename to src/libs/EmojiTrie.ts index 00e5fc1388e1..d0a53acf29c9 100644 --- a/src/libs/EmojiTrie.js +++ b/src/libs/EmojiTrie.ts @@ -1,29 +1,61 @@ -import _ from 'underscore'; +import React from 'react'; +import {SvgProps} from 'react-native-svg'; import emojis, {localeEmojis} from '../../assets/emojis'; import Trie from './Trie'; import Timing from './actions/Timing'; import CONST from '../CONST'; +type Emoji = { + code: string; + header?: boolean; + icon?: React.FC; + name?: string; + types?: string[]; +}; + +type LocalizedEmoji = { + name?: string; + keywords: string[]; +}; + +type LocalizedEmojis = Record; + +type Suggestion = { + code: string; + types?: string[]; + name?: string; +}; + +type EmojiMetaData = { + suggestions?: Suggestion[]; +}; + Timing.start(CONST.TIMING.TRIE_INITIALIZATION); -const supportedLanguages = [CONST.LOCALES.DEFAULT, CONST.LOCALES.ES]; +const supportedLanguages = [CONST.LOCALES.DEFAULT, CONST.LOCALES.ES] as const; + +type SupportedLanguage = (typeof supportedLanguages)[number]; + +type EmojiTrie = { + [key in SupportedLanguage]?: Trie; +}; /** * - * @param {Trie} trie The Trie object. - * @param {Array} keywords An array containing the keywords. - * @param {Object} item An object containing the properties of the emoji. - * @param {String} name The localized name of the emoji. - * @param {Boolean} shouldPrependKeyword Prepend the keyword (instead of append) to the suggestions + * @param trie The Trie object. + * @param keywords An array containing the keywords. + * @param item An object containing the properties of the emoji. + * @param name The localized name of the emoji. + * @param shouldPrependKeyword Prepend the keyword (instead of append) to the suggestions */ -function addKeywordsToTrie(trie, keywords, item, name, shouldPrependKeyword = false) { - _.forEach(keywords, (keyword) => { +function addKeywordsToTrie(trie: Trie, keywords: string[], item: Emoji, name: string, shouldPrependKeyword = false) { + keywords.forEach((keyword) => { const keywordNode = trie.search(keyword); if (!keywordNode) { trie.add(keyword, {suggestions: [{code: item.code, types: item.types, name}]}); } else { const suggestion = {code: item.code, types: item.types, name}; - const suggestions = shouldPrependKeyword ? [suggestion, ...keywordNode.metaData.suggestions] : [...keywordNode.metaData.suggestions, suggestion]; + const suggestions = shouldPrependKeyword ? [suggestion, ...(keywordNode.metaData.suggestions ?? [])] : [...(keywordNode.metaData.suggestions ?? []), suggestion]; trie.update(keyword, { ...keywordNode.metaData, suggestions, @@ -35,26 +67,27 @@ function addKeywordsToTrie(trie, keywords, item, name, shouldPrependKeyword = fa /** * Allows searching based on parts of the name. This turns 'white_large_square' into ['white_large_square', 'large_square', 'square']. * - * @param {String} name The emoji name - * @returns {Array} An array containing the name parts + * @param name The emoji name + * @returns An array containing the name parts */ -function getNameParts(name) { +function getNameParts(name: string): string[] { const nameSplit = name.split('_'); - return _.map(nameSplit, (_namePart, index) => nameSplit.slice(index).join('_')); + return nameSplit.map((namePart, index) => nameSplit.slice(index).join('_')); } -function createTrie(lang = CONST.LOCALES.DEFAULT) { +function createTrie(lang: SupportedLanguage = CONST.LOCALES.DEFAULT): Trie { const trie = new Trie(); - const langEmojis = localeEmojis[lang]; + const langEmojis: LocalizedEmojis = localeEmojis[lang]; + const defaultLangEmojis: LocalizedEmojis = localeEmojis[CONST.LOCALES.DEFAULT]; const isDefaultLocale = lang === CONST.LOCALES.DEFAULT; - _.forEach(emojis, (item) => { - if (item.header) { + emojis.forEach((item: Emoji) => { + if (!item.name) { return; } const englishName = item.name; - const localeName = _.get(langEmojis, [item.code, 'name'], englishName); + const localeName = langEmojis?.[item.code]?.name ?? englishName; const node = trie.search(localeName); if (!node) { @@ -67,7 +100,7 @@ function createTrie(lang = CONST.LOCALES.DEFAULT) { addKeywordsToTrie(trie, nameParts, item, localeName); // Add keywords for both the locale language and English to enable users to search using either language. - const keywords = _.get(langEmojis, [item.code, 'keywords'], []).concat(isDefaultLocale ? [] : _.get(localeEmojis, [CONST.LOCALES.DEFAULT, item.code, 'keywords'], [])); + const keywords = (langEmojis?.[item.code]?.keywords ?? []).concat(isDefaultLocale ? [] : defaultLangEmojis?.[item.code]?.keywords ?? []); addKeywordsToTrie(trie, keywords, item, localeName); /** @@ -83,7 +116,7 @@ function createTrie(lang = CONST.LOCALES.DEFAULT) { return trie; } -const emojiTrie = _.reduce(supportedLanguages, (prev, cur) => ({...prev, [cur]: createTrie(cur)}), {}); +const emojiTrie: EmojiTrie = supportedLanguages.reduce((prev, cur) => ({...prev, [cur]: createTrie(cur)}), {}); Timing.end(CONST.TIMING.TRIE_INITIALIZATION);