@@ -148,6 +148,10 @@ class AutocompleteViewManager {
148
148
autocompleteDataCache.invalidateUser (event.userId);
149
149
}
150
150
151
+ void handleMessageEvent (MessageEvent event) {
152
+ _refreshStaleUserResults ();
153
+ }
154
+
151
155
/// Called when the app is reassembled during debugging, e.g. for hot reload.
152
156
///
153
157
/// Calls [MentionAutocompleteView.reassemble] for all that are registered.
@@ -193,6 +197,7 @@ class MentionAutocompleteView extends ChangeNotifier {
193
197
@override
194
198
void dispose () {
195
199
store.autocompleteViewManager.unregisterMentionAutocomplete (this );
200
+ _sortedUsers = null ;
196
201
// We cancel in-progress computations by checking [hasListeners] between tasks.
197
202
// After [super.dispose] is called, [hasListeners] returns false.
198
203
// TODO test that logic (may involve detecting an unhandled Future rejection; how?)
@@ -213,9 +218,11 @@ class MentionAutocompleteView extends ChangeNotifier {
213
218
214
219
/// Recompute user results for the current query, if any.
215
220
///
216
- /// Called in particular when we get a [RealmUserEvent] .
221
+ /// Called in particular when we get a [RealmUserEvent] , a [MessageEvent] , or
222
+ /// [MessageListView.fetchOlder] is called.
217
223
void refreshStaleUserResults () {
218
224
if (_query != null ) {
225
+ _sortedUsers = null ;
219
226
_startSearch (_query! );
220
227
}
221
228
}
@@ -225,6 +232,7 @@ class MentionAutocompleteView extends ChangeNotifier {
225
232
/// This will redo the search from scratch for the current query, if any.
226
233
void reassemble () {
227
234
if (_query != null ) {
235
+ _sortedUsers = null ;
228
236
_startSearch (_query! );
229
237
}
230
238
}
@@ -251,22 +259,43 @@ class MentionAutocompleteView extends ChangeNotifier {
251
259
notifyListeners ();
252
260
}
253
261
262
+ List <User >? _sortedUsers;
263
+
264
+ List <User > sortByRelevance ({required List <User > users}) {
265
+ return users; // TODO(#228) sort for most relevant first
266
+ }
267
+
268
+ void _sortUsers () {
269
+ final users = store.users.values.toList ();
270
+ _sortedUsers = sortByRelevance (users: users);
271
+ }
272
+
254
273
Future <List <MentionAutocompleteResult >?> _computeResults (MentionAutocompleteQuery query) async {
255
274
final List <MentionAutocompleteResult > results = [];
256
- final Iterable <User > users = store.users.values;
257
275
258
- final iterator = users.iterator;
276
+ if (_sortedUsers == null ) {
277
+ _sortUsers ();
278
+ }
279
+
280
+ final sortedUsers = _sortedUsers! ;
281
+ final iterator = sortedUsers.iterator;
259
282
bool isDone = false ;
260
283
while (! isDone) {
261
284
// CPU perf: End this task; enqueue a new one for resuming this work
262
285
await Future (() {});
263
286
287
+ if (_sortedUsers != sortedUsers) {
288
+ // The list of users this loop has been working from has become stale.
289
+ // Abort so _startSearch can retry with the new list.
290
+ throw ConcurrentModificationError ();
291
+ }
292
+
264
293
if (query != _query || ! hasListeners) { // false if [dispose] has been called.
265
294
return null ;
266
295
}
267
296
268
297
for (int i = 0 ; i < 1000 ; i++ ) {
269
- if (! iterator.moveNext ()) { // Can throw ConcurrentModificationError
298
+ if (! iterator.moveNext ()) {
270
299
isDone = true ;
271
300
break ;
272
301
}
@@ -277,7 +306,7 @@ class MentionAutocompleteView extends ChangeNotifier {
277
306
}
278
307
}
279
308
}
280
- return results; // TODO(#228) sort for most relevant first
309
+ return results;
281
310
}
282
311
}
283
312
0 commit comments