|  | 
|  | 1 | +import 'package:collection/collection.dart'; | 
|  | 2 | + | 
| 1 | 3 | import '../api/model/events.dart'; | 
| 2 | 4 | import '../api/model/initial_snapshot.dart'; | 
| 3 | 5 | import '../api/model/model.dart'; | 
| @@ -188,28 +190,51 @@ class EmojiStoreImpl with EmojiStore { | 
| 188 | 190 |   } | 
| 189 | 191 | 
 | 
| 190 | 192 |   List<EmojiCandidate> _generateAllCandidates() { | 
| 191 |  | -    final byEmojiName = <String, EmojiCandidate>{}; | 
|  | 193 | +    final results = <EmojiCandidate>[]; | 
|  | 194 | + | 
|  | 195 | +    final namesOverridden = { | 
|  | 196 | +      for (final emoji in realmEmoji.values) emoji.name, | 
|  | 197 | +      'zulip', | 
|  | 198 | +    }; | 
| 192 | 199 |     for (final entry in _serverEmojiData.entries) { | 
| 193 |  | -      final emojiName = entry.value.first; | 
| 194 |  | -      byEmojiName[emojiName] = _emojiCandidateFor( | 
|  | 200 | +      final allNames = entry.value; | 
|  | 201 | +      final String emojiName; | 
|  | 202 | +      final List<String>? aliases; | 
|  | 203 | +      if (allNames.any(namesOverridden.contains)) { | 
|  | 204 | +        final names = allNames.whereNot(namesOverridden.contains).toList(); | 
|  | 205 | +        if (names.isEmpty) continue; | 
|  | 206 | +        emojiName = names.removeAt(0); | 
|  | 207 | +        aliases = names; | 
|  | 208 | +      } else { | 
|  | 209 | +        // Most emoji aren't overridden, so avoid copying the list. | 
|  | 210 | +        emojiName = allNames.first; | 
|  | 211 | +        aliases = allNames.length > 1 ? allNames.sublist(1) : null; | 
|  | 212 | +      } | 
|  | 213 | +      results.add(_emojiCandidateFor( | 
| 195 | 214 |         emojiType: ReactionType.unicodeEmoji, | 
| 196 | 215 |         emojiCode: entry.key, emojiName: emojiName, | 
| 197 |  | -        aliases: entry.value.length > 1 ? entry.value.sublist(1) : null); | 
|  | 216 | +        aliases: aliases)); | 
| 198 | 217 |     } | 
|  | 218 | + | 
| 199 | 219 |     for (final entry in realmEmoji.entries) { | 
| 200 | 220 |       final emojiName = entry.value.name; | 
| 201 |  | -      byEmojiName[emojiName] = _emojiCandidateFor( | 
|  | 221 | +      if (emojiName == 'zulip') { | 
|  | 222 | +        // TODO does 'zulip' really override realm emoji? | 
|  | 223 | +        //   (This is copied from zulip-mobile's behavior.) | 
|  | 224 | +        continue; | 
|  | 225 | +      } | 
|  | 226 | +      results.add(_emojiCandidateFor( | 
| 202 | 227 |         emojiType: ReactionType.realmEmoji, | 
| 203 | 228 |         emojiCode: entry.key, emojiName: emojiName, | 
| 204 |  | -        aliases: null); | 
|  | 229 | +        aliases: null)); | 
| 205 | 230 |     } | 
| 206 |  | -    // TODO does 'zulip' really override realm emoji? | 
| 207 |  | -    //   (This is copied from zulip-mobile's behavior.) | 
| 208 |  | -    byEmojiName['zulip'] = _emojiCandidateFor( | 
|  | 231 | + | 
|  | 232 | +    results.add(_emojiCandidateFor( | 
| 209 | 233 |       emojiType: ReactionType.zulipExtraEmoji, | 
| 210 | 234 |       emojiCode: 'zulip', emojiName: 'zulip', | 
| 211 |  | -      aliases: null); | 
| 212 |  | -    return byEmojiName.values.toList(growable: false); | 
|  | 235 | +      aliases: null)); | 
|  | 236 | + | 
|  | 237 | +    return results; | 
| 213 | 238 |   } | 
| 214 | 239 | 
 | 
| 215 | 240 |   // Compare query_matches_string_in_order in Zulip web:shared/src/typeahead.ts . | 
|  | 
0 commit comments