Skip to content

Commit

Permalink
wip emoji: Recognize word-aligned matches in ranking; TODO test
Browse files Browse the repository at this point in the history
  • Loading branch information
gnprice committed Dec 7, 2024
1 parent dc856ed commit f1bcb6b
Showing 1 changed file with 26 additions and 29 deletions.
55 changes: 26 additions & 29 deletions lib/model/emoji.dart
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,12 @@ enum EmojiMatchQuality {
/// The query matches a prefix of the emoji name, but not the whole name.
prefix,

/// The query matches somewhere in the emoji name, but not at the start.
/// The query matches starting at the start of a word in the emoji name,
/// but not the start of the whole name.
wordAligned,

/// The query matches somewhere in the emoji name,
/// but not at the start of any word.
other;

/// The best possible quality of match.
Expand Down Expand Up @@ -385,10 +390,8 @@ class EmojiAutocompleteView extends AutocompleteView<EmojiAutocompleteQuery, Emo
// Compare sort_emojis in Zulip web:shared/src/typeahead.ts .
//
// Behavior differences we might copy, TODO:
// * 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.
// * Web recognizes a word-aligned match starting after [ /-] as well as [_].
//
// Behavior differences that web should probably fix, TODO(web):
// * Among popular emoji with non-exact matches,
Expand Down Expand Up @@ -417,15 +420,15 @@ class EmojiAutocompleteView extends AutocompleteView<EmojiAutocompleteQuery, Emo
ReactionType.unicodeEmoji => false,
};
return switch (matchQuality) {
EmojiMatchQuality.exact => 0,
EmojiMatchQuality.prefix => isPopular ? 1 : isCustomEmoji ? 3 : 4,
// TODO word-boundary vs. not
EmojiMatchQuality.other => isPopular ? 2 : isCustomEmoji ? 5 : 6,
EmojiMatchQuality.exact => 0,
EmojiMatchQuality.prefix => isPopular ? 1 : isCustomEmoji ? 3 : 5,
EmojiMatchQuality.wordAligned => isPopular ? 2 : isCustomEmoji ? 4 : 6,
EmojiMatchQuality.other => isCustomEmoji ? 7 : 8,
};
}

/// The number of possible values returned by [_rankResult].
static const _numResultRanks = 7;
static const _numResultRanks = 9;

static bool _isPopularEmoji(EmojiCandidate candidate) {
return candidate.emojiType == ReactionType.unicodeEmoji
Expand Down Expand Up @@ -473,29 +476,23 @@ class EmojiAutocompleteQuery extends ComposeAutocompleteQuery {
}

EmojiMatchQuality? _matchName(String emojiName) {
// Compare query_matches_string_in_order in Zulip web:shared/src/typeahead.ts .
// TODO(#1067) this assumes emojiName is already lower-case (and no diacritics)
if (emojiName == _adjusted) return EmojiMatchQuality.exact;
if (emojiName.startsWith(_adjusted)) return EmojiMatchQuality.prefix;
if (_nameMatches(emojiName)) return EmojiMatchQuality.other;
return null;
}

// Compare query_matches_string_in_order in Zulip web:shared/src/typeahead.ts .
bool _nameMatches(String emojiName) {
const String separator = '_';

if (!_adjusted.contains(separator)) {
if (emojiName == _adjusted) return EmojiMatchQuality.exact;
if (emojiName.startsWith(_adjusted)) return EmojiMatchQuality.prefix;
const String sep = '_';
if (emojiName.contains(sep + _adjusted)) return EmojiMatchQuality.wordAligned;
if (!_adjusted.contains(sep)) {
// If the query is a single token (doesn't contain a separator),
// the match can be anywhere in the string.
return emojiName.contains(_adjusted);
// allow a match anywhere in the string, too.
if (emojiName.contains(_adjusted)) return EmojiMatchQuality.other;
} else {
// Otherwise, when there is a separator in the query,
// require the match to start at the start of a token.
// (E.g. for 'ab_cd_ef', query could be 'ab_c' or 'cd_ef',
// but not 'b_cd_ef'.)
}

// If there is a separator in the query, then we
// require the match to start at the start of a token.
// (E.g. for 'ab_cd_ef', query could be 'ab_c' or 'cd_ef',
// but not 'b_cd_ef'.)
assert(!emojiName.startsWith(_adjusted)); // checked before calling this method
return emojiName.contains(separator + _adjusted);
return null;
}

@override
Expand Down

0 comments on commit f1bcb6b

Please sign in to comment.