diff --git a/lib/model/emoji.dart b/lib/model/emoji.dart index e5035085c8..03b3d36241 100644 --- a/lib/model/emoji.dart +++ b/lib/model/emoji.dart @@ -242,6 +242,17 @@ class EmojiStoreImpl with EmojiStore { /// retrieving the data. Map>? _serverEmojiData; + static final _popularEmojiCodes = (() { + assert(zulipPopularEmojis.every((c) => + c.emojiType == ReactionType.unicodeEmoji)); + return Set.of(zulipPopularEmojis.map((c) => c.emojiCode)); + })(); + + static bool _isPopularEmoji(EmojiCandidate candidate) { + return candidate.emojiType == ReactionType.unicodeEmoji + && _popularEmojiCodes.contains(candidate.emojiCode); + } + List? _allEmojiCandidates; EmojiCandidate _emojiCandidateFor({ @@ -376,21 +387,28 @@ class EmojiAutocompleteView extends AutocompleteView custom emoji > others; we don't yet. // * Web ranks matches starting at a word boundary ahead of // other non-prefix matches; we don't yet. + // * Relatedly, web favors popular emoji only upon a word-aligned match. // * Web ranks each name of a Unicode emoji separately. // // Behavior differences that web should probably fix, TODO(web): + // * Among popular emoji with non-exact matches, + // web doesn't prioritize prefix over word-aligned; we do. + // (This affects just one case: for query "o", + // we put :octopus: before :working_on_it:.) + // * Web only counts an emoji as "popular" for ranking if the query + // is a prefix of a single word in the name; so "thumbs_" or "working_on_i" + // lose the ranking boost for :thumbs_up: and :working_on_it: respectively. // * Web starts with only case-sensitive exact matches ("perfect matches"), // and puts case-insensitive exact matches just ahead of prefix matches; // it also distinguishes prefix matches by case-sensitive vs. not. @@ -401,15 +419,24 @@ class EmojiAutocompleteView extends AutocompleteView true, + ReactionType.unicodeEmoji => false, + }; return switch (matchQuality) { EmojiMatchQuality.exact => 0, - EmojiMatchQuality.prefix => 1, - EmojiMatchQuality.other => 2, + EmojiMatchQuality.prefix => isPopular ? 1 : isCustomEmoji ? 3 : 4, + // TODO word-boundary vs. not + EmojiMatchQuality.other => isPopular ? 2 : isCustomEmoji ? 5 : 6, }; } /// The number of possible values returned by [_rankResult]. - static const _numResultRanks = 3; + static const _numResultRanks = 7; } class EmojiAutocompleteQuery extends ComposeAutocompleteQuery {