Skip to content

Commit 171be6e

Browse files
committed
emoji: Make emoji autocomplete explicitly case-insensitive
I'm not sure if emoji names/aliases can actually have capital letters in them, but it seemed helpful for review if I added a normalization step here in its own commit. Soon, for #1067, we'll change the normalization so it strips diacritics too. Greg comments: #1806 (comment) > I think we systematically avoid capital letters in the names and > aliases of Unicode emoji. Then for custom/realm emoji… looking on > CZO, there are no capital letters there, so I suspect we disallow > them. > > But seems harmless to do the normalization, especially given that > we need to process each of these strings anyway to normalize out > the diacritics.
1 parent 6e305f7 commit 171be6e

File tree

1 file changed

+20
-9
lines changed

1 file changed

+20
-9
lines changed

lib/model/emoji.dart

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,23 @@ final class EmojiCandidate {
7474
/// This might not be the only name this emoji has; see [aliases].
7575
final String emojiName;
7676

77+
/// [emojiName], but lowercased to support fuzzy matching.
78+
// TODO(#1067) also remove diacritics
79+
String get normalizedEmojiName => _normalizedEmojiName
80+
??= emojiName.toLowerCase();
81+
String? _normalizedEmojiName;
82+
7783
/// Additional Zulip "emoji name" values for this emoji,
7884
/// to show in the emoji picker UI.
7985
Iterable<String> get aliases => _aliases ?? const [];
8086
final List<String>? _aliases;
8187

88+
/// [aliases], but lowercased to support fuzzy matching.
89+
// TODO(#1067) also remove diacritics
90+
Iterable<String> get normalizedAliases => _normalizedAliases
91+
??= aliases.map((alias) => alias.toLowerCase());
92+
Iterable<String>? _normalizedAliases;
93+
8294
final EmojiDisplay emojiDisplay;
8395

8496
EmojiCandidate({
@@ -533,29 +545,28 @@ class EmojiAutocompleteQuery extends ComposeAutocompleteQuery {
533545
}
534546
}
535547

536-
EmojiMatchQuality? result = _matchName(candidate.emojiName);
537-
for (final alias in candidate.aliases) {
548+
EmojiMatchQuality? result = _matchName(candidate.normalizedEmojiName);
549+
for (final normalizedAlias in candidate.normalizedAliases) {
538550
if (result == EmojiMatchQuality.best) return result;
539-
result = EmojiMatchQuality.bestOf(result, _matchName(alias));
551+
result = EmojiMatchQuality.bestOf(result, _matchName(normalizedAlias));
540552
}
541553
return result;
542554
}
543555

544-
EmojiMatchQuality? _matchName(String emojiName) {
556+
EmojiMatchQuality? _matchName(String normalizedName) {
545557
// Compare query_matches_string_in_order in Zulip web:shared/src/typeahead.ts
546558
// for a Boolean version of this logic (match vs. no match),
547559
// and triage_raw in the same file web:shared/src/typeahead.ts
548560
// for the finer distinctions.
549561
// See also commentary in [_rankResult].
550562

551-
// TODO(#1067) this assumes emojiName is already lower-case (and no diacritics)
552-
if (emojiName == _adjusted) return EmojiMatchQuality.exact;
553-
if (emojiName.startsWith(_adjusted)) return EmojiMatchQuality.prefix;
554-
if (emojiName.contains(_sepAdjusted)) return EmojiMatchQuality.wordAligned;
563+
if (normalizedName == _adjusted) return EmojiMatchQuality.exact;
564+
if (normalizedName.startsWith(_adjusted)) return EmojiMatchQuality.prefix;
565+
if (normalizedName.contains(_sepAdjusted)) return EmojiMatchQuality.wordAligned;
555566
if (!_adjusted.contains(_separator)) {
556567
// If the query is a single token (doesn't contain a separator),
557568
// allow a match anywhere in the string, too.
558-
if (emojiName.contains(_adjusted)) return EmojiMatchQuality.other;
569+
if (normalizedName.contains(_adjusted)) return EmojiMatchQuality.other;
559570
} else {
560571
// Otherwise, require at least a word-aligned match.
561572
}

0 commit comments

Comments
 (0)