@@ -178,6 +178,7 @@ class MentionAutocompleteView extends ChangeNotifier {
178
178
@override
179
179
void dispose () {
180
180
store.autocompleteViewManager.unregisterMentionAutocomplete (this );
181
+ _sortedUsers = null ;
181
182
// We cancel in-progress computations by checking [hasListeners] between tasks.
182
183
// After [super.dispose] is called, [hasListeners] returns false.
183
184
// TODO test that logic (may involve detecting an unhandled Future rejection; how?)
@@ -201,6 +202,7 @@ class MentionAutocompleteView extends ChangeNotifier {
201
202
/// This will redo the search from scratch for the current query, if any.
202
203
void reassemble () {
203
204
if (_query != null ) {
205
+ _sortedUsers = null ;
204
206
_startSearch (_query! );
205
207
}
206
208
}
@@ -230,22 +232,43 @@ class MentionAutocompleteView extends ChangeNotifier {
230
232
notifyListeners ();
231
233
}
232
234
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
+
233
246
Future <List <MentionAutocompleteResult >?> _computeResults (MentionAutocompleteQuery query) async {
234
247
final List <MentionAutocompleteResult > results = [];
235
- final Iterable <User > users = store.users.values;
236
248
237
- final iterator = users.iterator;
249
+ if (_sortedUsers == null ) {
250
+ _sortUsers ();
251
+ }
252
+
253
+ final sortedUsers = _sortedUsers! ;
254
+ final iterator = sortedUsers.iterator;
238
255
bool isDone = false ;
239
256
while (! isDone) {
240
257
// CPU perf: End this task; enqueue a new one for resuming this work
241
258
await Future (() {});
242
259
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
+
243
266
if (query != _query || ! hasListeners) { // false if [dispose] has been called.
244
267
return null ;
245
268
}
246
269
247
270
for (int i = 0 ; i < 1000 ; i++ ) {
248
- if (! iterator.moveNext ()) { // Can throw ConcurrentModificationError
271
+ if (! iterator.moveNext ()) {
249
272
isDone = true ;
250
273
break ;
251
274
}
@@ -256,7 +279,7 @@ class MentionAutocompleteView extends ChangeNotifier {
256
279
}
257
280
}
258
281
}
259
- return results; // TODO(#228) sort for most relevant first
282
+ return results;
260
283
}
261
284
}
262
285
0 commit comments