Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: index emoji name parts #26910

Merged
merged 5 commits into from
Sep 11, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 45 additions & 22 deletions src/libs/EmojiTrie.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,41 @@ Timing.start(CONST.TIMING.TRIE_INITIALIZATION);

const supportedLanguages = [CONST.LOCALES.DEFAULT, CONST.LOCALES.ES];

/**
*
* @param {Trie} trie The Trie object.
* @param {Array<String>} 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
*/
function addKeywordsToTrie(trie, keywords, item, name, shouldPrependKeyword = false) {
_.forEach(keywords, (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];
trie.update(keyword, {
...keywordNode.metaData,
suggestions,
});
}
});
}

/**
* 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<String>} An array containing the name parts
*/
function getNameParts(name) {
const nameSplit = name.split('_');
return _.map(nameSplit, (_namePart, index) => nameSplit.slice(index).join('_'));
}

function createTrie(lang = CONST.LOCALES.DEFAULT) {
const trie = new Trie();
const langEmojis = localeEmojis[lang];
Expand All @@ -28,32 +63,20 @@ function createTrie(lang = CONST.LOCALES.DEFAULT) {
trie.update(localeName, {code: item.code, types: item.types, name: localeName, suggestions: node.metaData.suggestions});
}

const nameParts = getNameParts(localeName).slice(1); // We remove the first part because we already index the full name.
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'], []));
for (let j = 0; j < keywords.length; j++) {
const keywordNode = trie.search(keywords[j]);
if (!keywordNode) {
trie.add(keywords[j], {suggestions: [{code: item.code, types: item.types, name: localeName}]});
} else {
trie.update(keywords[j], {
...keywordNode.metaData,
suggestions: [...keywordNode.metaData.suggestions, {code: item.code, types: item.types, name: localeName}],
});
}
}
addKeywordsToTrie(trie, keywords, item, localeName);

// If current language isn't the default, prepend the English name of the emoji in the suggestions as well.
// We do this because when the user types the english name of the emoji, we want to show the emoji in the suggestions before all the others.
/**
* If current language isn't the default, prepend the English name of the emoji in the suggestions as well.
* We do this because when the user types the english name of the emoji, we want to show the emoji in the suggestions before all the others.
*/
if (!isDefaultLocale) {
const englishNode = trie.search(englishName);
if (!englishNode) {
trie.add(englishName, {suggestions: [{code: item.code, types: item.types, name: localeName}]});
} else {
trie.update(englishName, {
...englishNode.metaData,
suggestions: [{code: item.code, types: item.types, name: localeName}, ...englishNode.metaData.suggestions],
});
}
const englishNameParts = getNameParts(englishName);
addKeywordsToTrie(trie, englishNameParts, item, localeName, true);
}
});

Expand Down