@@ -187,7 +187,7 @@ class AutocompleteViewManager {
187187///  * On reassemble, call [reassemble] . 
188188///  * When the object will no longer be used, call [dispose]  to free 
189189///    resources on the [PerAccountStore].  
190- abstract  class  AutocompleteView <QueryT  extends  AutocompleteQuery , ResultT  extends  AutocompleteResult ,  CandidateT > extends  ChangeNotifier  {
190+ abstract  class  AutocompleteView <QueryT  extends  AutocompleteQuery , ResultT  extends  AutocompleteResult > extends  ChangeNotifier  {
191191  AutocompleteView ({required  this .store});
192192
193193  final  PerAccountStore  store;
@@ -284,46 +284,33 @@ abstract class AutocompleteView<QueryT extends AutocompleteQuery, ResultT extend
284284  }
285285}
286286
287- class  MentionAutocompleteView  extends  AutocompleteView <MentionAutocompleteQuery , MentionAutocompleteResult ,  User > {
287+ class  MentionAutocompleteView  extends  AutocompleteView <MentionAutocompleteQuery , MentionAutocompleteResult > {
288288  MentionAutocompleteView ._({
289289    required  super .store,
290290    required  this .narrow,
291+     required  this .wildcards,
291292    required  this .sortedUsers,
292293  });
293294
294295  factory  MentionAutocompleteView .init ({
295296    required  PerAccountStore  store,
296297    required  Narrow  narrow,
298+     required  List <Wildcard > wildcards,
297299  }) {
298300    final  view =  MentionAutocompleteView ._(
299301      store:  store,
300302      narrow:  narrow,
303+       wildcards:  wildcards,
301304      sortedUsers:  _usersByRelevance (store:  store, narrow:  narrow),
302305    );
303306    store.autocompleteViewManager.registerMentionAutocomplete (view);
304307    return  view;
305308  }
306309
307310  final  Narrow  narrow;
311+   final  List <Wildcard > wildcards;
308312  final  List <User > sortedUsers;
309313
310-   @override 
311-   Future <List <MentionAutocompleteResult >?> computeResults () async  {
312-     final  results =  < MentionAutocompleteResult > [];
313-     if  (await  filterCandidates (filter:  _testUser,
314-           candidates:  sortedUsers, results:  results)) {
315-       return  null ;
316-     }
317-     return  results;
318-   }
319- 
320-   MentionAutocompleteResult ?  _testUser (MentionAutocompleteQuery  query, User  user) {
321-     if  (query.testUser (user, store.autocompleteViewManager.autocompleteDataCache)) {
322-       return  UserMentionAutocompleteResult (userId:  user.userId);
323-     }
324-     return  null ;
325-   }
326- 
327314  static  List <User > _usersByRelevance ({
328315    required  PerAccountStore  store,
329316    required  Narrow  narrow,
@@ -377,8 +364,6 @@ class MentionAutocompleteView extends AutocompleteView<MentionAutocompleteQuery,
377364    required  String ?  topic,
378365    required  PerAccountStore  store,
379366  }) {
380-     // TODO(#234): give preference to "all", "everyone" or "stream" 
381- 
382367    // TODO(#618): give preference to subscribed users first 
383368
384369    if  (streamId !=  null ) {
@@ -483,6 +468,42 @@ class MentionAutocompleteView extends AutocompleteView<MentionAutocompleteQuery,
483468    return  userAName.compareTo (userBName); // TODO(i18n): add locale-aware sorting 
484469  }
485470
471+   bool  _isChannelWildcardIncluded =  false ;
472+ 
473+   @override 
474+   Future <List <MentionAutocompleteResult >?> computeResults () async  {
475+     _isChannelWildcardIncluded =  false ;
476+     final  results =  < MentionAutocompleteResult > [];
477+     // give priority to wildcard mentions 
478+     if  (await  filterCandidates (filter:  _testWildcard,
479+         candidates:  wildcards, results:  results)) {
480+       return  null ;
481+     }
482+     if  (await  filterCandidates (filter:  _testUser,
483+         candidates:  sortedUsers, results:  results)) {
484+       return  null ;
485+     }
486+     return  results;
487+   }
488+ 
489+   MentionAutocompleteResult ?  _testWildcard (MentionAutocompleteQuery  query, Wildcard  wildcard) {
490+     if  (query.testWildcard (wildcard)) {
491+       if  (wildcard.type ==  WildcardType .channel) {
492+         if  (_isChannelWildcardIncluded) return  null ;
493+         _isChannelWildcardIncluded =  true ;
494+       }
495+       return  WildcardMentionAutocompleteResult (wildcardName:  wildcard.name);
496+     }
497+     return  null ;
498+   }
499+ 
500+   MentionAutocompleteResult ?  _testUser (MentionAutocompleteQuery  query, User  user) {
501+     if  (query.testUser (user, store.autocompleteViewManager.autocompleteDataCache)) {
502+       return  UserMentionAutocompleteResult (userId:  user.userId);
503+     }
504+     return  null ;
505+   }
506+ 
486507  @override 
487508  void  dispose () {
488509    store.autocompleteViewManager.unregisterMentionAutocomplete (this );
@@ -493,6 +514,37 @@ class MentionAutocompleteView extends AutocompleteView<MentionAutocompleteQuery,
493514  }
494515}
495516
517+ class  Wildcard  {
518+   Wildcard ({
519+     required  this .name,
520+     required  this .value,
521+     required  this .fullDisplayName,
522+     required  this .type,
523+   });
524+ 
525+   /// The name of the wildcard to be shown as part of [fullDisplayName]  in autocomplete suggestions. 
526+   /// 
527+   /// Ex: "channel", "stream", "topic", ... 
528+ final  String  name;
529+ 
530+   /// The value to be put at the compose box after choosing an option from autocomplete. 
531+   /// 
532+   /// Same as the [name] , except for "stream" it is "channel" in FL >= 247 (server-9). 
533+ final  String  value; // TODO(sever-9): remove, instead use [name] 
534+ 
535+   /// The full name of the wildcard to be shown in autocomplete suggestions. 
536+   /// 
537+   /// Ex: "all (Notify channel)" or "everyone (Notify recipients)". 
538+ final  String  fullDisplayName;
539+ 
540+   final  WildcardType  type;
541+ }
542+ 
543+ enum  WildcardType  {
544+   channel,
545+   topic, // TODO(sever-8) 
546+ }
547+ 
496548abstract  class  AutocompleteQuery  {
497549  AutocompleteQuery (this .raw)
498550    :  _lowercaseWords =  raw.toLowerCase ().split (' ' );
@@ -529,15 +581,14 @@ class MentionAutocompleteQuery extends AutocompleteQuery {
529581  /// Whether the user wants a silent mention (@_query, vs. @query). 
530582final  bool  silent;
531583
532-   bool  testUser (User  user, AutocompleteDataCache  cache) {
533-     // TODO(#236) test email too, not just name 
584+   bool  testWildcard (Wildcard  wildcard) {
585+     return  wildcard.name.contains (raw.toLowerCase ());
586+   }
534587
588+   bool  testUser (User  user, AutocompleteDataCache  cache) {
535589    if  (! user.isActive) return  false ;
536590
537-     return  _testName (user, cache);
538-   }
539- 
540-   bool  _testName (User  user, AutocompleteDataCache  cache) {
591+     // TODO(#236) test email too, not just name 
541592    return  _testContainsQueryWords (cache.nameWordsForUser (user));
542593  }
543594
@@ -585,11 +636,15 @@ class UserMentionAutocompleteResult extends MentionAutocompleteResult {
585636  final  int  userId;
586637}
587638
588- // TODO(#233): // class UserGroupMentionAutocompleteResult extends MentionAutocompleteResult { 
639+ class  WildcardMentionAutocompleteResult  extends  MentionAutocompleteResult  {
640+   WildcardMentionAutocompleteResult ({required  this .wildcardName});
641+ 
642+   final  String  wildcardName;
643+ }
589644
590- // TODO(#234 ): // class WildcardMentionAutocompleteResult  extends MentionAutocompleteResult { 
645+ // TODO(#233 ): // class UserGroupMentionAutocompleteResult  extends MentionAutocompleteResult { 
591646
592- class  TopicAutocompleteView  extends  AutocompleteView <TopicAutocompleteQuery , TopicAutocompleteResult ,  String > {
647+ class  TopicAutocompleteView  extends  AutocompleteView <TopicAutocompleteQuery , TopicAutocompleteResult > {
593648  TopicAutocompleteView ._({required  super .store, required  this .streamId});
594649
595650  factory  TopicAutocompleteView .init ({required  PerAccountStore  store, required  int  streamId}) {
0 commit comments