@@ -178,6 +178,7 @@ class MentionAutocompleteView extends ChangeNotifier {
178178 @override
179179 void dispose () {
180180 store.autocompleteViewManager.unregisterMentionAutocomplete (this );
181+ _sortedUsers = null ;
181182 // We cancel in-progress computations by checking [hasListeners] between tasks.
182183 // After [super.dispose] is called, [hasListeners] returns false.
183184 // TODO test that logic (may involve detecting an unhandled Future rejection; how?)
@@ -201,6 +202,7 @@ class MentionAutocompleteView extends ChangeNotifier {
201202 /// This will redo the search from scratch for the current query, if any.
202203 void reassemble () {
203204 if (_query != null ) {
205+ _sortedUsers = null ;
204206 _startSearch (_query! );
205207 }
206208 }
@@ -230,22 +232,43 @@ class MentionAutocompleteView extends ChangeNotifier {
230232 notifyListeners ();
231233 }
232234
235+ List <User >? _sortedUsers;
236+
237+ List <User > sortByRelevance ({required List <User > users}) {
238+ return users; // TODO(#228) sort for most relevant first
239+ }
240+
241+ void _sortUsers () {
242+ final users = store.users.values.toList ();
243+ _sortedUsers = sortByRelevance (users: users);
244+ }
245+
233246 Future <List <MentionAutocompleteResult >?> _computeResults (MentionAutocompleteQuery query) async {
234247 final List <MentionAutocompleteResult > results = [];
235- final Iterable <User > users = store.users.values;
236248
237- final iterator = users.iterator;
249+ if (_sortedUsers == null ) {
250+ _sortUsers ();
251+ }
252+
253+ final sortedUsers = _sortedUsers! ;
254+ final iterator = sortedUsers.iterator;
238255 bool isDone = false ;
239256 while (! isDone) {
240257 // CPU perf: End this task; enqueue a new one for resuming this work
241258 await Future (() {});
242259
260+ if (_sortedUsers != sortedUsers) {
261+ // The list of users this loop has been working from has become stale.
262+ // Abort so _startSearch can retry with the new list.
263+ throw ConcurrentModificationError ();
264+ }
265+
243266 if (query != _query || ! hasListeners) { // false if [dispose] has been called.
244267 return null ;
245268 }
246269
247270 for (int i = 0 ; i < 1000 ; i++ ) {
248- if (! iterator.moveNext ()) { // Can throw ConcurrentModificationError
271+ if (! iterator.moveNext ()) {
249272 isDone = true ;
250273 break ;
251274 }
@@ -256,7 +279,7 @@ class MentionAutocompleteView extends ChangeNotifier {
256279 }
257280 }
258281 }
259- return results; // TODO(#228) sort for most relevant first
282+ return results;
260283 }
261284}
262285
0 commit comments