diff --git a/app/components/autocomplete/emoji_suggestion/emoji_suggestion.js b/app/components/autocomplete/emoji_suggestion/emoji_suggestion.js index d7c20750c..8f6d14402 100644 --- a/app/components/autocomplete/emoji_suggestion/emoji_suggestion.js +++ b/app/components/autocomplete/emoji_suggestion/emoji_suggestion.js @@ -94,13 +94,18 @@ export default class EmojiSuggestion extends PureComponent { const results = await fuse.search(matchTerm.toLowerCase()); const data = results.map((index) => emojis[index]); - this.setEmojiData(data); + this.setEmojiData(data, matchTerm); }; - setEmojiData = (data) => { + setEmojiData = (data, matchTerm = null) => { + let sorter = compareEmojis; + if (matchTerm) { + sorter = (a, b) => compareEmojis(a, b, matchTerm); + } + this.setState({ active: data.length > 0, - dataSource: data.sort(compareEmojis), + dataSource: data.sort(sorter), }); this.props.onResultCountChange(data.length); diff --git a/app/components/emoji_picker/emoji_picker_base.js b/app/components/emoji_picker/emoji_picker_base.js index f9889696c..429248a8e 100644 --- a/app/components/emoji_picker/emoji_picker_base.js +++ b/app/components/emoji_picker/emoji_picker_base.js @@ -24,6 +24,7 @@ import { makeStyleSheetFromTheme, changeOpacity, } from 'app/utils/theme'; +import {compareEmojis} from 'app/utils/emoji_utils'; import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing'; import EmojiPickerRow from './emoji_picker_row'; @@ -211,7 +212,9 @@ export default class EmojiPicker extends PureComponent { } const results = fuse.search(searchTermLowerCase); - const data = results.map((index) => emojis[index]); + const sorter = (a, b) => compareEmojis(a, b, searchTerm); + const data = results.map((index) => emojis[index]).sort(sorter); + return data; }; diff --git a/app/utils/emoji_utils.js b/app/utils/emoji_utils.js index d8b837cb7..ae092d11b 100644 --- a/app/utils/emoji_utils.js +++ b/app/utils/emoji_utils.js @@ -132,23 +132,45 @@ const customComparisonRules = { '+1': thumbsUpComparisonRule, }; +function doDefaultComparison(aName, bName) { + if (customComparisonRules[aName]) { + return customComparisonRules[aName](bName) || defaultComparisonRule(aName, bName); + } + + return defaultComparisonRule(aName, bName); +} + export function compareEmojis(emojiA, emojiB, searchedName) { const aName = emojiA.name || (emojiA.aliases ? emojiA.aliases[0] : emojiA); const bName = emojiB.name || (emojiB.aliases ? emojiB.aliases[0] : emojiB); - // Have the emojis that contain the search appear first + if (!searchedName) { + return doDefaultComparison(aName, bName); + } + + // Have the emojis that start with the search appear first const aPrefix = aName.startsWith(searchedName); const bPrefix = bName.startsWith(searchedName); - if (aPrefix === bPrefix) { - if (customComparisonRules[aName]) { - return customComparisonRules[aName](bName) || defaultComparisonRule(aName, bName); - } - - return defaultComparisonRule(aName, bName, searchedName); + if (aPrefix && bPrefix) { + return doDefaultComparison(aName, bName); } else if (aPrefix) { return -1; + } else if (bPrefix) { + return 1; } - return 1; + // Have the emojis that contain the search appear next + const aIncludes = aName.includes(searchedName); + const bIncludes = bName.includes(searchedName); + + if (aIncludes && bIncludes) { + return doDefaultComparison(aName, bName); + } else if (aIncludes) { + return -1; + } else if (bIncludes) { + return 1; + } + + return doDefaultComparison(aName, bName); } \ No newline at end of file diff --git a/app/utils/emoji_utils.test.js b/app/utils/emoji_utils.test.js index 690163352..052dc434c 100644 --- a/app/utils/emoji_utils.test.js +++ b/app/utils/emoji_utils.test.js @@ -411,4 +411,18 @@ describe('compareEmojis', () => { expect(emojiArray).toEqual([thumbsUpEmoji, thumbsDownEmoji, smileEmoji]); }); + + test('it sorts emojis that start with search term first, then includes search term, then alphabetically', () => { + const printerEmoji = 'printer'; + const pointDownEmoji = 'point_down'; + const paintBrushEmoji = 'paintbrush'; + const footPrintsEmoji = 'footprints'; + const disappointedEmoji = 'disappointed'; + const sixPointedStarEmoji = 'six_pointed_star'; + + const emojiArray = [printerEmoji, pointDownEmoji, paintBrushEmoji, footPrintsEmoji, disappointedEmoji, sixPointedStarEmoji]; + emojiArray.sort((a, b) => compareEmojis(a, b, 'point')); + + expect(emojiArray).toEqual([pointDownEmoji, disappointedEmoji, sixPointedStarEmoji, footPrintsEmoji, paintBrushEmoji, printerEmoji]); + }); });