@@ -183,6 +183,7 @@ class MentionAutocompleteView extends ChangeNotifier {
183
183
@override
184
184
void dispose () {
185
185
store.autocompleteViewManager.unregisterMentionAutocomplete (this );
186
+ _sortedUsers = null ;
186
187
// We cancel in-progress computations by checking [hasListeners] between tasks.
187
188
// After [super.dispose] is called, [hasListeners] returns false.
188
189
// TODO test that logic (may involve detecting an unhandled Future rejection; how?)
@@ -206,6 +207,7 @@ class MentionAutocompleteView extends ChangeNotifier {
206
207
/// Called in particular when we get a [RealmUserEvent] .
207
208
void refreshStaleUserResults () {
208
209
if (_query != null ) {
210
+ _sortedUsers = null ;
209
211
_startSearch (_query! );
210
212
}
211
213
}
@@ -244,11 +246,116 @@ class MentionAutocompleteView extends ChangeNotifier {
244
246
notifyListeners ();
245
247
}
246
248
249
+ List <User >? _sortedUsers;
250
+
251
+ int compareByDms (User userA, User userB) {
252
+ final aRecencyIndex = store.recentDmConversationsView.getRecencyIndex (userA.userId);
253
+ final bRecencyIndex = store.recentDmConversationsView.getRecencyIndex (userB.userId);
254
+
255
+ if (aRecencyIndex > bRecencyIndex) {
256
+ return - 1 ;
257
+ } else if (bRecencyIndex > aRecencyIndex) {
258
+ return 1 ;
259
+ }
260
+
261
+ final aIsPartner = store.recentDmConversationsView.isPartner (userA.userId);
262
+ final bIsPartner = store.recentDmConversationsView.isPartner (userB.userId);
263
+
264
+ // This code will never run except in the rare case that one has no
265
+ // recent DM message history with a user, but does have some older
266
+ // message history.
267
+ if (aIsPartner && ! bIsPartner) {
268
+ return - 1 ;
269
+ } else if (bIsPartner && ! aIsPartner) {
270
+ return 1 ;
271
+ }
272
+
273
+ if (! userA.isBot && userB.isBot) {
274
+ return - 1 ;
275
+ } else if (userA.isBot && ! userB.isBot) {
276
+ return 1 ;
277
+ }
278
+
279
+ if (userA.fullName.toLowerCase ().compareTo (
280
+ userB.fullName.toLowerCase ()) < 0 ) {
281
+ return - 1 ;
282
+ }
283
+ return 1 ;
284
+ }
285
+
286
+ int compareByRelevance ({
287
+ required User userA,
288
+ required User userB,
289
+ int Function (User , User )? compareByCurrentConversation,
290
+ }) {
291
+ // TODO(#234): give preference to "all", "everyone" or "stream".
292
+
293
+ // TODO(#618): give preference to subscribed users first.
294
+
295
+ if (compareByCurrentConversation != null ) {
296
+ final preference = compareByCurrentConversation (userA, userB);
297
+ if (preference != 0 ) {
298
+ return preference;
299
+ }
300
+ }
301
+
302
+ return compareByDms (userA, userB);
303
+ }
304
+
305
+ List <User > sortByRelevance ({
306
+ required List <User > users,
307
+ required int ? currentStreamId,
308
+ required String ? currentTopic,
309
+ }) {
310
+ // Sorting for DMs narrow
311
+ if (currentStreamId == null ) {
312
+ users.sort ((userA, userB) => compareByRelevance (
313
+ userA: userA,
314
+ userB: userB));
315
+ } else { // Sorting for stream/topic narrow
316
+ users.sort ((userA, userB) => compareByRelevance (
317
+ userA: userA,
318
+ userB: userB,
319
+ compareByCurrentConversation: (userA, userB) => store.recentSenders.compareByRecency (
320
+ userA: userA,
321
+ userB: userB,
322
+ streamId: currentStreamId,
323
+ topic: currentTopic)));
324
+ }
325
+ return users;
326
+ }
327
+
328
+ void _sortUsers () {
329
+ final users = store.users.values.toList ();
330
+ switch (narrow) {
331
+ case StreamNarrow ():
332
+ _sortedUsers = sortByRelevance (
333
+ users: users,
334
+ currentStreamId: (narrow as StreamNarrow ).streamId,
335
+ currentTopic: null );
336
+ case TopicNarrow ():
337
+ _sortedUsers = sortByRelevance (
338
+ users: users,
339
+ currentStreamId: (narrow as TopicNarrow ).streamId,
340
+ currentTopic: (narrow as TopicNarrow ).topic);
341
+ case DmNarrow ():
342
+ _sortedUsers = sortByRelevance (
343
+ users: users,
344
+ currentStreamId: null ,
345
+ currentTopic: null );
346
+ case AllMessagesNarrow ():
347
+ _sortedUsers = []; // TODO: sort (maybe in future)
348
+ }
349
+ }
350
+
247
351
Future <List <MentionAutocompleteResult >?> _computeResults (MentionAutocompleteQuery query) async {
248
352
final List <MentionAutocompleteResult > results = [];
249
- final Iterable <User > users = store.users.values;
250
353
251
- final iterator = users.iterator;
354
+ if (_sortedUsers == null ) {
355
+ _sortUsers ();
356
+ }
357
+
358
+ final iterator = _sortedUsers! .iterator;
252
359
bool isDone = false ;
253
360
while (! isDone) {
254
361
// CPU perf: End this task; enqueue a new one for resuming this work
@@ -270,7 +377,7 @@ class MentionAutocompleteView extends ChangeNotifier {
270
377
}
271
378
}
272
379
}
273
- return results; // TODO(#228) sort for most relevant first
380
+ return results;
274
381
}
275
382
}
276
383
0 commit comments