66 */
77package com.nextcloud.talk.conversationlist.viewmodels
88
9+ import android.annotation.SuppressLint
910import android.content.Context
1011import android.util.Log
1112import androidx.lifecycle.LiveData
@@ -318,6 +319,7 @@ class ConversationsListViewModel @Inject constructor(
318319 }
319320 }
320321
322+ @SuppressLint(" DefaultLocale" )
321323 @Suppress(" LongMethod" )
322324 fun getSearchQuery (context : Context , filter : String ) {
323325 // Rotation / display-off guard: if the composition restarts (config change) the
@@ -348,31 +350,66 @@ class ConversationsListViewModel @Inject constructor(
348350
349351 if (localConvs.isNotEmpty()) {
350352 entries.add(ConversationListEntry .Header (conversationsTitle))
351- localConvs.forEach { entries.add(ConversationListEntry .ConversationEntry (it)) }
353+
354+ val pattern = """ \b${Regex .escape(filter)} \b""" .toRegex(RegexOption .IGNORE_CASE )
355+
356+ processOrderAndAdd(
357+ localConvs,
358+ firstPredicate = { it.name.trim().equals(filter, ignoreCase = true ) },
359+ secondPredicate = { it.name.contains(pattern) },
360+ addAction = {
361+ entries.add(ConversationListEntry .ConversationEntry (it))
362+ }
363+ )
352364 }
353365 if (openConvs.isNotEmpty()) {
354366 entries.add(ConversationListEntry .Header (openConversationsTitle))
355- openConvs.forEach { conv ->
356- entries.add(
357- ConversationListEntry .ConversationEntry (
358- ConversationModel .mapToConversationModel(conv, currentUser)
367+
368+ val pattern = """ \b${Regex .escape(filter)} \b""" .toRegex(RegexOption .IGNORE_CASE )
369+
370+ processOrderAndAdd(
371+ openConvs,
372+ firstPredicate = { it.name.trim().equals(filter, ignoreCase = true ) },
373+ secondPredicate = { it.name.contains(pattern) },
374+ addAction = { conv ->
375+ entries.add(
376+ ConversationListEntry .ConversationEntry (
377+ ConversationModel .mapToConversationModel(conv, currentUser)
378+ )
359379 )
360- )
361- }
380+ }
381+ )
362382 }
363383 if (contacts.isNotEmpty()) {
364384 entries.add(ConversationListEntry .Header (usersTitle))
365- contacts.forEach { autocompleteUser ->
366- val participant = Participant ()
367- participant.actorId = autocompleteUser.id
368- participant.actorType = actorTypeConverter.getFromString(autocompleteUser.source)
369- participant.displayName = autocompleteUser.label
370- entries.add(ConversationListEntry .ContactEntry (participant))
371- }
385+
386+ val pattern = """ \s*${Regex .escape(filter)} \s*""" .toRegex(RegexOption .IGNORE_CASE )
387+
388+ processOrderAndAdd(
389+ contacts,
390+ firstPredicate = { it.label?.trim().equals(filter, ignoreCase = true ) },
391+ secondPredicate = { it.label?.contains(pattern) ? : false },
392+ addAction = { autocompleteUser ->
393+ val participant = Participant ()
394+ participant.actorId = autocompleteUser.id
395+ participant.actorType = actorTypeConverter.getFromString(autocompleteUser.source)
396+ participant.displayName = autocompleteUser.label
397+ entries.add(ConversationListEntry .ContactEntry (participant))
398+ }
399+ )
372400 }
373401 if (messages.isNotEmpty()) {
374402 entries.add(ConversationListEntry .Header (messagesTitle))
375- messages.forEach { msg -> entries.add(ConversationListEntry .MessageResultEntry (msg)) }
403+
404+ val pattern = """ \b${Regex .escape(filter)} \b""" .toRegex(RegexOption .IGNORE_CASE )
405+
406+ processOrderAndAdd(
407+ messages,
408+ firstPredicate = {
409+ it.messageExcerpt.contains(pattern)
410+ },
411+ addAction = { msg -> entries.add(ConversationListEntry .MessageResultEntry (msg)) }
412+ )
376413 }
377414 if (hasMore) entries.add(ConversationListEntry .LoadMore )
378415
@@ -384,6 +421,30 @@ class ConversationsListViewModel @Inject constructor(
384421 }
385422 }
386423
424+ // This function orders any arbitrary list according to
425+ // [meets predicate 1][meets predicate 2]?[the rest]
426+ // and applying a unit function upon the result of these reorderings
427+ private fun <T > processOrderAndAdd (
428+ list : List <T >,
429+ firstPredicate : (T ) -> Boolean ,
430+ secondPredicate : ((T ) -> Boolean )? = null,
431+ addAction : (T ) -> Unit
432+ ) {
433+ val result = mutableListOf<T >()
434+
435+ val (firstPredicate, remainingFirst) = list.partition(firstPredicate)
436+ result.addAll(firstPredicate)
437+
438+ if (secondPredicate != null ) {
439+ val (secondPredicate, remainingSecond) = remainingFirst.partition(secondPredicate)
440+ result.addAll(secondPredicate + remainingSecond)
441+ } else {
442+ result.addAll(remainingFirst)
443+ }
444+
445+ result.forEach(addAction)
446+ }
447+
387448 private fun getMessagesFlow (search : String ): Flow <MessageSearchResults > =
388449 flow {
389450 emit(searchHelper.startMessageSearch(search))
0 commit comments