diff --git a/app/build.gradle.kts b/app/build.gradle.kts index defad7b175..dfa060a161 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -26,8 +26,8 @@ configurations.configureEach { exclude(module = "commons-logging") } -val canonicalVersionCode = 429 -val canonicalVersionName = "1.29.0" +val canonicalVersionCode = 430 +val canonicalVersionName = "1.29.1" val postFixSize = 10 val abiPostFix = mapOf( diff --git a/app/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt b/app/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt index 3954404ac3..277efe3054 100644 --- a/app/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt +++ b/app/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt @@ -409,8 +409,10 @@ class ReceivedMessageHandler @Inject constructor( runThreadUpdate = runThreadUpdate ) ?: return null - // If we have previously "hidden" the sender, we should flip the flag back to visible - if (senderAddress is Address.Standard && senderAddress.address != userPublicKey) { + // If we have previously "hidden" the sender, we should flip the flag back to visible, + // and this should only be done only for 1:1 messages + if (senderAddress is Address.Standard && senderAddress.address != userPublicKey + && context.threadAddress is Address.Standard) { val existingContact = configFactory.withUserConfigs { it.contacts.get(senderAddress.accountId.hexString) } diff --git a/app/src/main/java/org/session/libsession/utilities/Address.kt b/app/src/main/java/org/session/libsession/utilities/Address.kt index 108bbfeec2..f94c823de4 100644 --- a/app/src/main/java/org/session/libsession/utilities/Address.kt +++ b/app/src/main/java/org/session/libsession/utilities/Address.kt @@ -175,7 +175,7 @@ sealed interface Address : Parcelable, Comparable
{ /** * A marker interface for addresses that represent a group-like entity. */ - sealed interface GroupLike : Address + sealed interface GroupLike : Conversable sealed interface WithAccountId { val accountId: AccountId diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactAccessor.java b/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactAccessor.java deleted file mode 100644 index bd3c7c1cc6..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactAccessor.java +++ /dev/null @@ -1,137 +0,0 @@ -/** - * Copyright (C) 2011 Whisper Systems - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.thoughtcrime.securesms.contacts; - -import android.content.Context; -import android.net.Uri; -import android.os.Parcel; -import android.os.Parcelable; - -import org.session.libsession.utilities.GroupRecord; -import org.session.libsession.utilities.TextSecurePreferences; -import org.thoughtcrime.securesms.database.GroupDatabase; -import org.thoughtcrime.securesms.dependencies.DatabaseComponent; - -import java.util.LinkedList; -import java.util.List; - -import javax.inject.Inject; -import javax.inject.Singleton; - -import network.loki.messenger.R; - -/** - * This class was originally a layer of indirection between - * ContactAccessorNewApi and ContactAccesorOldApi, which corresponded - * to the API changes between 1.x and 2.x. - * - * Now that we no longer support 1.x, this class mostly serves as a place - * to encapsulate Contact-related logic. It's still a singleton, mostly - * just because that's how it's currently called from everywhere. - * - * @author Moxie Marlinspike - */ - -@Singleton -public class ContactAccessor { - private final GroupDatabase groupDatabase; - - @Inject - public ContactAccessor(GroupDatabase groupDatabase) { - this.groupDatabase = groupDatabase; - } - - - public List getNumbersForThreadSearchFilter(Context context, String constraint) { - LinkedList numberList = new LinkedList<>(); - - GroupRecord record; - try (GroupDatabase.Reader reader = groupDatabase.getGroupsFilteredByTitle(constraint)) { - while ((record = reader.getNext()) != null) { - numberList.add(record.getEncodedId()); - } - } - - return numberList; - } - - public static class NumberData implements Parcelable { - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - public NumberData createFromParcel(Parcel in) { - return new NumberData(in); - } - - public NumberData[] newArray(int size) { - return new NumberData[size]; - } - }; - - public final String number; - public final String type; - - - public NumberData(Parcel in) { - number = in.readString(); - type = in.readString(); - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(number); - dest.writeString(type); - } - } - - public static class ContactData implements Parcelable { - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - public ContactData createFromParcel(Parcel in) { - return new ContactData(in); - } - - public ContactData[] newArray(int size) { - return new ContactData[size]; - } - }; - - public final long id; - public final String name; - public final List numbers; - - public ContactData(Parcel in) { - id = in.readLong(); - name = in.readString(); - numbers = new LinkedList(); - in.readTypedList(numbers, NumberData.CREATOR); - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(id); - dest.writeString(name); - dest.writeTypedList(numbers); - } - } - -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt index 89c980c0c5..5a87cc3cef 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt @@ -225,6 +225,10 @@ class ConversationViewModel @AssistedInject constructor( it.currentUserRole in EnumSet.of(GroupMemberRole.ADMIN, GroupMemberRole.HIDDEN_ADMIN) } + val canModerate: StateFlow = recipientFlow.mapStateFlow(viewModelScope) { + it.currentUserRole.canModerate + } + private val _searchOpened = MutableStateFlow(false) val appBarData: StateFlow = combine( @@ -750,7 +754,7 @@ class ConversationViewModel @AssistedInject constructor( } // If the user is an admin or is interacting with their own message And are allowed to delete for everyone - (isAdmin.value || allSentByCurrentUser) && canDeleteForEveryone -> { + (canModerate.value || allSentByCurrentUser) && canDeleteForEveryone -> { _dialogsState.update { it.copy( deleteEveryone = DeleteForEveryoneDialogData( diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java index 0ab54cbdca..f7b51cef35 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java @@ -146,8 +146,6 @@ public void postKey(SQLiteConnection connection) { ); this.jsonProvider = jsonProvider; - - Log.d(TAG, "SQLCipherOpenHelper created with database secret: " + databaseSecret.asString()); } @Override 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 9e18662ea9..c200357545 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -172,7 +172,7 @@ class HomeActivity : ScreenLockActionBarActivity(), is GlobalSearchAdapter.Model.GroupConversation -> ConversationActivityV2 .createIntent( this, - address = Address.fromSerialized(model.groupId) as Address.Conversable + address = model.address ) else -> { @@ -466,7 +466,7 @@ class HomeActivity : ScreenLockActionBarActivity(), .map { GlobalSearchAdapter.Model.Contact( contact = it.value, - isSelf = it.value.address.address == publicKey, + isSelf = it.value.isSelf, showProBadge = it.value.proStatus.shouldShowProBadge() ) } @@ -479,8 +479,9 @@ class HomeActivity : ScreenLockActionBarActivity(), isSelf = it.isSelf, showProBadge = it.proStatus.shouldShowProBadge() ) } + - threads.map { - GlobalSearchAdapter.Model.GroupConversation(it, showProBadge = recipientRepository.getRecipientSync(it.encodedId.toAddress()).proStatus.shouldShowProBadge()) + threads.mapNotNull { + if(it.address is Address.GroupLike) GlobalSearchAdapter.Model.GroupConversation(it) + else null } private val GlobalSearchResult.messageResults: List get() { 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 5a5b09c708..4808702b2a 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 @@ -14,8 +14,11 @@ import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.utilities.Address import org.session.libsession.utilities.GroupRecord import org.session.libsession.utilities.recipients.Recipient +import org.session.libsession.utilities.recipients.RecipientData import org.session.libsession.utilities.recipients.displayName +import org.session.libsession.utilities.recipients.shouldShowProBadge import org.session.libsignal.utilities.AccountId +import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.search.model.MessageResult import org.thoughtcrime.securesms.ui.GetString import org.thoughtcrime.securesms.util.DateUtils @@ -147,6 +150,8 @@ class GlobalSearchAdapter( onContactLongPressed(model) true } + } else { + binding.root.setOnLongClickListener(null) } } } @@ -167,26 +172,39 @@ class GlobalSearchAdapter( this(contact.address as Address.Conversable, contact.displayName(false), isSelf, showProBadge) } data class GroupConversation( - val isLegacy: Boolean, - val groupId: String, + val address: Address.GroupLike, val title: String, val legacyMembersString: String?, val showProBadge: Boolean ) : Model { - constructor(groupRecord: GroupRecord, showProBadge: Boolean): + constructor(recipient: Recipient): this( - isLegacy = groupRecord.isLegacyGroup, - groupId = groupRecord.encodedId, - title = groupRecord.title, - legacyMembersString = if (groupRecord.isLegacyGroup) { - val recipients = groupRecord.members.map { - MessagingModuleConfiguration.shared.recipientRepository.getRecipientSync(it) + address = recipient.address as Address.GroupLike, + title = recipient.displayName(), + legacyMembersString = when (recipient.address) { + is Address.LegacyGroup -> { + val data = (recipient.data as? RecipientData.LegacyGroup) + if(data == null) null + else { + if(data.secondMember != null) "${data.firstMember.displayName()}, ${data.secondMember.displayName()}".plus( + if(data.members.size > 2) ", ..." else "" + ) + else data.firstMember.displayName().plus( + if(data.members.size > 1) ", ..." else "" + ) + } + } + + is Address.Group -> { + val data = (recipient.data as? RecipientData.Group) + data?.partial?.members?.joinToString(", ") { it.name } + } + + else -> { + null } - recipients.joinToString(transform = { it.searchName }) - } else { - null }, - showProBadge = showProBadge + showProBadge = recipient.proStatus.shouldShowProBadge() ) } data class Message(val messageResult: MessageResult, val unread: Int, val isSelf: Boolean, val showProBadge: 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 72239f1bd0..d356be5fe4 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 @@ -11,6 +11,7 @@ import androidx.recyclerview.widget.DiffUtil import network.loki.messenger.R import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.utilities.Address +import org.session.libsession.utilities.isLegacyGroup import org.session.libsession.utilities.recipients.Recipient import org.session.libsession.utilities.recipients.displayName import org.session.libsession.utilities.truncateIdForDisplay @@ -111,10 +112,9 @@ private fun ComposeView.setupTitleWithBadge(title: String, showProBadge: Boolean fun ContentView.bindModel(query: String?, model: GroupConversation) { binding.searchResultProfilePicture.isVisible = true - binding.searchResultSubtitle.isVisible = model.isLegacy binding.searchResultTimestamp.isVisible = false val threadRecipient = MessagingModuleConfiguration.shared.recipientRepository.getRecipientSync( - Address.fromSerialized(model.groupId) + model.address ) binding.searchResultProfilePicture.setThemedContent { @@ -130,7 +130,10 @@ fun ContentView.bindModel(query: String?, model: GroupConversation) { ) if (model.legacyMembersString != null) { + binding.searchResultSubtitle.isVisible = true binding.searchResultSubtitle.text = getHighlight(query, model.legacyMembersString) + } else { + binding.searchResultSubtitle.isVisible = false } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchResult.kt b/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchResult.kt index 3f74aa6528..04b28c0ea4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchResult.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchResult.kt @@ -8,7 +8,7 @@ import org.thoughtcrime.securesms.search.model.SearchResult data class GlobalSearchResult( val query: String, val contacts: List = emptyList(), - val threads: List = emptyList(), + val threads: List = emptyList(), val messages: List = emptyList(), val showNoteToSelf: Boolean = false ) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/search/SearchRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/search/SearchRepository.kt index 83a8059914..16bde5de03 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/search/SearchRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/search/SearchRepository.kt @@ -3,24 +3,20 @@ package org.thoughtcrime.securesms.search import android.content.Context import android.database.Cursor import dagger.hilt.android.qualifiers.ApplicationContext +import network.loki.messenger.libsession_util.util.GroupInfo import org.session.libsession.utilities.Address import org.session.libsession.utilities.Address.Companion.fromSerialized import org.session.libsession.utilities.Address.Companion.toAddress import org.session.libsession.utilities.ConfigFactoryProtocol -import org.session.libsession.utilities.GroupRecord -import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.concurrent.SignalExecutors import org.session.libsession.utilities.recipients.Recipient import org.session.libsession.utilities.recipients.RecipientData -import org.session.libsession.utilities.toGroupString +import org.session.libsession.utilities.recipients.displayName import org.session.libsignal.utilities.AccountId -import org.thoughtcrime.securesms.contacts.ContactAccessor import org.thoughtcrime.securesms.database.CursorList -import org.thoughtcrime.securesms.database.GroupDatabase import org.thoughtcrime.securesms.database.MmsSmsColumns import org.thoughtcrime.securesms.database.RecipientRepository import org.thoughtcrime.securesms.database.SearchDatabase -import org.thoughtcrime.securesms.database.ThreadDatabase import org.thoughtcrime.securesms.repository.ConversationRepository import org.thoughtcrime.securesms.search.model.MessageResult import org.thoughtcrime.securesms.search.model.SearchResult @@ -33,13 +29,9 @@ import javax.inject.Singleton class SearchRepository @Inject constructor( @param:ApplicationContext private val context: Context, private val searchDatabase: SearchDatabase, - private val threadDatabase: ThreadDatabase, - private val groupDatabase: GroupDatabase, - private val contactAccessor: ContactAccessor, private val recipientRepository: RecipientRepository, private val conversationRepository: ConversationRepository, private val configFactory: ConfigFactoryProtocol, - private val prefs: TextSecurePreferences, ) { private val executor = SignalExecutors.SERIAL @@ -128,12 +120,41 @@ class SearchRepository @Inject constructor( private fun queryConversations( query: String, - ): List { - val numbers = contactAccessor.getNumbersForThreadSearchFilter(context, query) - val addresses = numbers.map { fromSerialized(it) } + ) : List { + if(query.isEmpty()) return emptyList() - return threadDatabase.getThreads(addresses) - .map { groupDatabase.getGroup(it.recipient.address.toGroupString()).get() } + return configFactory.withUserConfigs { configs -> + configs.userGroups.all() + }.asSequence() + .mapNotNull { group -> + when (group) { + is GroupInfo.ClosedGroupInfo -> { + if(group.invited) null // do not show groups V2 we have not yet accepted + else recipientRepository.getRecipientSync( + Address.Group(AccountId(group.groupAccountId)) + ) + } + + is GroupInfo.LegacyGroupInfo -> { + recipientRepository.getRecipientSync( + Address.LegacyGroup(group.accountId) + ) + } + + is GroupInfo.CommunityGroupInfo -> { + recipientRepository.getRecipientSync( + Address.Community( + serverUrl = group.community.baseUrl, + room = group.community.room + ) + ) + } + } + } + .filter { group -> + group.displayName().contains(query, ignoreCase = true) + } + .toList() } private fun queryMessages(query: String): CursorList { diff --git a/app/src/main/java/org/thoughtcrime/securesms/search/model/SearchResult.kt b/app/src/main/java/org/thoughtcrime/securesms/search/model/SearchResult.kt index d1dfc64124..d501cd0d8c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/search/model/SearchResult.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/search/model/SearchResult.kt @@ -11,7 +11,7 @@ import org.thoughtcrime.securesms.database.CursorList class SearchResult( val query: String = "", val contacts: List = emptyList(), - val conversations: List = emptyList(), + val conversations: List = emptyList(), val messages: CursorList = CursorList.emptyList() ) { fun size(): Int {