Skip to content

Commit 72f0b00

Browse files
committed
Intuitive search ordering of filtered data
Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com>
1 parent 0357c20 commit 72f0b00

1 file changed

Lines changed: 76 additions & 15 deletions

File tree

app/src/main/java/com/nextcloud/talk/conversationlist/viewmodels/ConversationsListViewModel.kt

Lines changed: 76 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
package com.nextcloud.talk.conversationlist.viewmodels
88

9+
import android.annotation.SuppressLint
910
import android.content.Context
1011
import android.util.Log
1112
import 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

Comments
 (0)