From c358111363533e42c9169c0a36623e9c7c9f8d94 Mon Sep 17 00:00:00 2001 From: SessionHero01 <180888785+SessionHero01@users.noreply.github.com> Date: Thu, 20 Mar 2025 09:33:35 +1100 Subject: [PATCH] Fixes flashing on search result list --- .../securesms/home/HomeActivity.kt | 14 ++++--- .../home/search/GlobalSearchAdapter.kt | 40 +++++++++++++++---- .../home/search/GlobalSearchAdapterUtils.kt | 26 +++++------- .../securesms/search/model/MessageResult.java | 13 ++++++ 4 files changed, 64 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt index 112717a384..b06a051b4b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -45,6 +45,7 @@ import org.session.libsession.utilities.StringSubstitutionConstants.GROUP_NAME_K import org.session.libsession.utilities.StringSubstitutionConstants.NAME_KEY import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.recipients.Recipient +import org.session.libsignal.utilities.AccountId import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.ScreenLockActionBarActivity @@ -67,6 +68,7 @@ import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter import org.thoughtcrime.securesms.home.search.GlobalSearchInputLayout import org.thoughtcrime.securesms.home.search.GlobalSearchResult import org.thoughtcrime.securesms.home.search.GlobalSearchViewModel +import org.thoughtcrime.securesms.home.search.getSearchName import org.thoughtcrime.securesms.messagerequests.MessageRequestsActivity import org.thoughtcrime.securesms.permissions.Permissions import org.thoughtcrime.securesms.preferences.SettingsActivity @@ -135,11 +137,11 @@ class HomeActivity : ScreenLockActionBarActivity(), is GlobalSearchAdapter.Model.Contact -> push { putExtra( ConversationActivityV2.ADDRESS, - model.contact.accountID.let(Address::fromSerialized) + model.contact.hexString.let(Address::fromSerialized) ) } - is GlobalSearchAdapter.Model.GroupConversation -> model.groupRecord.encodedId + is GlobalSearchAdapter.Model.GroupConversation -> model.groupId .let { Recipient.from(this, Address.fromSerialized(it), false) } .let(threadDb::getThreadIdIfExistsFor) .takeIf { it >= 0 } @@ -352,13 +354,15 @@ class HomeActivity : ScreenLockActionBarActivity(), .flatMap { (key, contacts) -> listOf( GlobalSearchAdapter.Model.SubHeader(key) - ) + contacts.sortedBy { it.name ?: it.value.accountID }.map { it.value }.map { GlobalSearchAdapter.Model.Contact(it, it.nickname ?: it.name, it.accountID == publicKey) } + ) + contacts.sortedBy { it.name ?: it.value.accountID }.map { it.value }.map { GlobalSearchAdapter.Model.Contact(it, it.accountID == publicKey) } } } private val GlobalSearchResult.contactAndGroupList: List get() = - contacts.map { GlobalSearchAdapter.Model.Contact(it, it.nickname ?: it.name, it.accountID == publicKey) } + - threads.map(GlobalSearchAdapter.Model::GroupConversation) + contacts.map { GlobalSearchAdapter.Model.Contact(it, it.accountID == publicKey) } + + threads.map { + GlobalSearchAdapter.Model.GroupConversation(this@HomeActivity, it) + } private val GlobalSearchResult.messageResults: List get() { val unreadThreadMap = messages diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapter.kt index bc9d597641..6281a03b10 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapter.kt @@ -1,5 +1,6 @@ package org.thoughtcrime.securesms.home.search +import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -10,11 +11,13 @@ import network.loki.messenger.R import network.loki.messenger.databinding.ViewGlobalSearchHeaderBinding import network.loki.messenger.databinding.ViewGlobalSearchResultBinding import network.loki.messenger.databinding.ViewGlobalSearchSubheaderBinding +import org.session.libsession.messaging.contacts.Contact import org.session.libsession.utilities.GroupRecord +import org.session.libsession.utilities.recipients.Recipient +import org.session.libsignal.utilities.AccountId import org.thoughtcrime.securesms.search.model.MessageResult import org.thoughtcrime.securesms.ui.GetString import java.security.InvalidParameterException -import org.session.libsession.messaging.contacts.Contact as ContactModel class GlobalSearchAdapter(private val modelCallback: (Model)->Unit): RecyclerView.Adapter() { @@ -125,18 +128,39 @@ class GlobalSearchAdapter(private val modelCallback: (Model)->Unit): RecyclerVie } } - sealed class Model { - data class Header(val title: GetString): Model() { + sealed interface Model { + data class Header(val title: GetString): Model { constructor(@StringRes title: Int): this(GetString(title)) constructor(title: String): this(GetString(title)) } - data class SubHeader(val title: GetString): Model() { + data class SubHeader(val title: GetString): Model { constructor(@StringRes title: Int): this(GetString(title)) constructor(title: String): this(GetString(title)) } - data class SavedMessages(val currentUserPublicKey: String): Model() - data class Contact(val contact: ContactModel, val name: String?, val isSelf: Boolean) : Model() - data class GroupConversation(val groupRecord: GroupRecord) : Model() - data class Message(val messageResult: MessageResult, val unread: Int, val isSelf: Boolean) : Model() + data class SavedMessages(val currentUserPublicKey: String): Model + data class Contact(val contact: AccountId, val name: String, val isSelf: Boolean) : Model { + constructor(contact: org.session.libsession.messaging.contacts.Contact, isSelf: Boolean): + this(AccountId(contact.accountID), contact.getSearchName(), isSelf) + } + data class GroupConversation( + val isLegacy: Boolean, + val groupId: String, + val title: String, + val legacyMembersString: String?, + ) : Model { + constructor(context: Context, groupRecord: GroupRecord): + this( + isLegacy = groupRecord.isLegacyGroup, + groupId = groupRecord.encodedId, + title = groupRecord.title, + legacyMembersString = if (groupRecord.isLegacyGroup) { + val recipients = groupRecord.members.map { Recipient.from(context, it, false) } + recipients.joinToString(transform = Recipient::getSearchName) + } else { + null + } + ) + } + data class Message(val messageResult: MessageResult, val unread: Int, val isSelf: Boolean) : Model } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapterUtils.kt b/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapterUtils.kt index b4377e6a37..48d4d11c5b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapterUtils.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapterUtils.kt @@ -48,7 +48,7 @@ fun ContentView.bindQuery(query: String, model: GlobalSearchAdapter.Model) { is ContactModel -> { binding.searchResultTitle.text = getHighlight( query, - model.contact.getSearchName() + model.name ) } is Message -> { @@ -69,13 +69,10 @@ fun ContentView.bindQuery(query: String, model: GlobalSearchAdapter.Model) { is GroupConversation -> { binding.searchResultTitle.text = getHighlight( query, - model.groupRecord.title + model.title ) - val membersString = model.groupRecord.members.joinToString { address -> - Recipient.from(binding.root.context, address, false).getSearchName() - } - binding.searchResultSubtitle.text = getHighlight(query, membersString) + binding.searchResultSubtitle.text = getHighlight(query, model.legacyMembersString.orEmpty()) } is Header, // do nothing for header is SubHeader, // do nothing for subheader @@ -89,18 +86,15 @@ private fun getHighlight(query: String?, toSearch: String): Spannable? { fun ContentView.bindModel(query: String?, model: GroupConversation) { binding.searchResultProfilePicture.isVisible = true - binding.searchResultSubtitle.isVisible = model.groupRecord.isLegacyGroup + binding.searchResultSubtitle.isVisible = model.isLegacy binding.searchResultTimestamp.isVisible = false - val threadRecipient = Recipient.from(binding.root.context, Address.fromSerialized(model.groupRecord.encodedId), false) + val threadRecipient = Recipient.from(binding.root.context, Address.fromSerialized(model.groupId), false) binding.searchResultProfilePicture.update(threadRecipient) - val nameString = model.groupRecord.title + val nameString = model.title binding.searchResultTitle.text = getHighlight(query, nameString) - val groupRecipients = model.groupRecord.members.map { Recipient.from(binding.root.context, it, false) } - - val membersString = groupRecipients.joinToString(transform = Recipient::getSearchName) - if (model.groupRecord.isLegacyGroup) { - binding.searchResultSubtitle.text = getHighlight(query, membersString) + if (model.legacyMembersString != null) { + binding.searchResultSubtitle.text = getHighlight(query, model.legacyMembersString) } } @@ -109,10 +103,10 @@ fun ContentView.bindModel(query: String?, model: ContactModel) = binding.run { searchResultSubtitle.isVisible = false searchResultTimestamp.isVisible = false searchResultSubtitle.text = null - val recipient = Recipient.from(root.context, Address.fromSerialized(model.contact.accountID), false) + val recipient = Recipient.from(root.context, Address.fromSerialized(model.contact.hexString), false) searchResultProfilePicture.update(recipient) val nameString = if (model.isSelf) root.context.getString(R.string.noteToSelf) - else model.contact.getSearchName() + else model.name searchResultTitle.text = getHighlight(query, nameString) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/search/model/MessageResult.java b/app/src/main/java/org/thoughtcrime/securesms/search/model/MessageResult.java index 58e3f1a69a..804e47893e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/search/model/MessageResult.java +++ b/app/src/main/java/org/thoughtcrime/securesms/search/model/MessageResult.java @@ -4,6 +4,8 @@ import androidx.annotation.NonNull; import org.session.libsession.utilities.recipients.Recipient; +import java.util.Objects; + /** * Represents a search result for a message. */ @@ -27,4 +29,15 @@ public class MessageResult { this.threadId = threadId; this.sentTimestampMs = sentTimestampMs; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof MessageResult that)) return false; + return threadId == that.threadId && sentTimestampMs == that.sentTimestampMs && Objects.equals(conversationRecipient, that.conversationRecipient) && Objects.equals(messageRecipient, that.messageRecipient) && Objects.equals(bodySnippet, that.bodySnippet); + } + + @Override + public int hashCode() { + return Objects.hash(conversationRecipient, messageRecipient, bodySnippet, threadId, sentTimestampMs); + } }