diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index 88b3cd518a..78dad49b64 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -48,7 +48,7 @@ import org.thoughtcrime.securesms.sskenvironment.ReadReceiptManager; import org.thoughtcrime.securesms.sskenvironment.TypingStatusRepository; import org.thoughtcrime.securesms.components.TypingStatusSender; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; -import org.thoughtcrime.securesms.crypto.ProfileKeyUtil; +import org.session.libsession.utilities.preferences.ProfileKeyUtil; import org.session.libsession.messaging.threads.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.GroupDatabase; diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java index 59e5d75731..27505c08e0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java @@ -6,6 +6,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; +import org.session.libsession.utilities.preferences.ProfileKeyUtil; import org.session.libsignal.metadata.SignalProtos; import org.session.libsignal.utilities.logging.Log; import org.session.libsession.messaging.threads.recipients.Recipient; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java index 383cfaa091..3b222404e0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java @@ -122,7 +122,7 @@ public class MmsSmsDatabase extends Database { } public Cursor getConversation(long threadId, long offset, long limit) { - String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " DESC"; + String order = MmsSmsColumns.NORMALIZED_DATE_SENT + " DESC"; String selection = MmsSmsColumns.THREAD_ID + " = " + threadId; String limitStr = limit > 0 || offset > 0 ? offset + ", " + limit : null; diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java index 5543739c28..08cc05da9f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java @@ -260,14 +260,14 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType { if (userPublicKey == address.getNumber()) { // Loki - Device link messages don't go through here - SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccessPair, mediaMessage); + SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccessPair, mediaMessage, true); if (result.getLokiAPIError() != null) { throw result.getLokiAPIError(); } else { return result.getSuccess().isUnidentified(); } } else { - SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccessPair, mediaMessage); + SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccessPair, mediaMessage, false); if (result.getLokiAPIError() != null) { throw result.getLokiAPIError(); } else { @@ -276,7 +276,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType { try { // send to ourselves to sync multi-device Optional syncAccess = UnidentifiedAccessUtil.getAccessForSync(context); - SendMessageResult selfSendResult = messageSender.sendMessage(messageId, localAddress, syncAccess, mediaSelfSendMessage); + SendMessageResult selfSendResult = messageSender.sendMessage(messageId, localAddress, syncAccess, mediaSelfSendMessage, true); if (selfSendResult.getLokiAPIError() != null) { throw selfSendResult.getLokiAPIError(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java index 3bd34c394d..d99ab36c55 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java @@ -17,7 +17,7 @@ import org.session.libsession.utilities.Util; import org.greenrobot.eventbus.EventBus; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.contactshare.ContactModelMapper; -import org.thoughtcrime.securesms.crypto.ProfileKeyUtil; +import org.session.libsession.utilities.preferences.ProfileKeyUtil; import org.session.libsession.messaging.threads.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.events.PartProgressEvent; diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java index de8953f44e..ef6e43b31d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java @@ -197,14 +197,14 @@ public class PushTextSendJob extends PushSendJob implements InjectableType { if (userPublicKey.equals(address.getNumber())) { // Loki - Device link messages don't go through here - SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccess, textSecureMessage); + SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccess, textSecureMessage, true); if (result.getLokiAPIError() != null) { throw result.getLokiAPIError(); } else { return result.getSuccess().isUnidentified(); } } else { - SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccess, textSecureMessage); + SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccess, textSecureMessage, false); if (result.getLokiAPIError() != null) { throw result.getLokiAPIError(); } else { @@ -213,7 +213,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType { try { // send to ourselves to sync multi-device Optional syncAccess = UnidentifiedAccessUtil.getAccessForSync(context); - SendMessageResult selfSendResult = messageSender.sendMessage(messageId, localAddress, syncAccess, textSecureSelfSendMessage); + SendMessageResult selfSendResult = messageSender.sendMessage(messageId, localAddress, syncAccess, textSecureSelfSendMessage, true); if (selfSendResult.getLokiAPIError() != null) { throw selfSendResult.getLokiAPIError(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java index d6d2757f52..fc216d68fb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java @@ -82,7 +82,7 @@ public class RequestGroupInfoJob extends BaseJob implements InjectableType { messageSender.sendMessage(0, new SignalServiceAddress(source), UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromExternal(context, source), false)), - message); + message, false); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupActivity.kt index 4ae71e0619..65bf5ef905 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupActivity.kt @@ -298,7 +298,7 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() { }.failUi { exception -> val message = if (exception is ClosedGroupsProtocolV2.Error) exception.description else "An error occurred" Toast.makeText(this@EditClosedGroupActivity, message, Toast.LENGTH_LONG).show() - loader.fadeOut() + loaderContainer.fadeOut() isLoading = false } } else { diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt index dd3c9a192c..29d058deed 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt @@ -17,25 +17,26 @@ import android.view.MenuItem import android.view.View import android.view.inputmethod.InputMethodManager import android.widget.Toast +import androidx.core.view.isVisible import kotlinx.android.synthetic.main.activity_settings.* import network.loki.messenger.BuildConfig import network.loki.messenger.R import nl.komponents.kovenant.Promise import nl.komponents.kovenant.all import nl.komponents.kovenant.deferred +import nl.komponents.kovenant.functional.bind +import nl.komponents.kovenant.task import nl.komponents.kovenant.ui.alwaysUi import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity import org.thoughtcrime.securesms.avatar.AvatarSelection -import org.thoughtcrime.securesms.crypto.ProfileKeyUtil +import org.session.libsession.utilities.preferences.ProfileKeyUtil import org.session.libsession.messaging.threads.Address import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.loki.dialogs.ChangeUiModeDialog import org.thoughtcrime.securesms.loki.dialogs.ClearAllDataDialog import org.thoughtcrime.securesms.loki.dialogs.SeedDialog import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities -import org.thoughtcrime.securesms.loki.utilities.fadeIn -import org.thoughtcrime.securesms.loki.utilities.fadeOut import org.thoughtcrime.securesms.loki.utilities.push import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.mms.GlideRequests @@ -48,6 +49,7 @@ import org.thoughtcrime.securesms.util.BitmapUtil import org.session.libsession.utilities.TextSecurePreferences import org.session.libsignal.service.api.util.StreamDetails import org.session.libsignal.service.loki.api.fileserver.FileServerAPI +import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol import java.io.ByteArrayInputStream import java.io.File import java.security.SecureRandom @@ -169,7 +171,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { } private fun updateProfile(isUpdatingProfilePicture: Boolean) { - loader.fadeIn() + loader.isVisible = true val promises = mutableListOf>() val displayName = displayNameToBeUploaded if (displayName != null) { @@ -196,7 +198,17 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { } promises.add(deferred.promise) } - all(promises).alwaysUi { + + all(promises).bind { + // updating the profile name or picture + if (profilePicture != null || displayName != null) { + task { + MultiDeviceProtocol.forceSyncConfigurationNowIfNeeded(this@SettingsActivity) + } + } else { + Promise.of(Unit) + } + }.alwaysUi { if (displayName != null) { btnGroupNameDisplay.text = displayName } @@ -209,7 +221,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { profilePictureView.update() } profilePictureToBeUploaded = null - loader.fadeOut() + loader.isVisible = false } } // endregion diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt index 8f12de0105..10f27aa89a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt @@ -95,8 +95,12 @@ object ClosedGroupsProtocolV2 { return deferred.promise } - @JvmStatic - fun explicitLeave(context: Context, groupPublicKey: String): Promise { + /** + * @param notifyUser Inserts an outgoing info message for the user's leave message, useful to set `false` if + * you are exiting asynchronously and deleting the thread from [HomeActivity][org.thoughtcrime.securesms.loki.activities.HomeActivity.deleteConversation] + */ + @JvmStatic @JvmOverloads + fun explicitLeave(context: Context, groupPublicKey: String, notifyUser: Boolean = true): Promise { val deferred = deferred() ThreadUtils.queue { val userPublicKey = TextSecurePreferences.getLocalNumber(context)!! @@ -120,7 +124,9 @@ object ClosedGroupsProtocolV2 { // Notify the user val infoType = GroupContext.Type.QUIT val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) - insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID, sentTime) + if (notifyUser) { + insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID, sentTime) + } // Remove the group private key and unsubscribe from PNs disableLocalGroupAndUnsubscribe(context, apiDB, groupPublicKey, groupDB, groupID, userPublicKey) deferred.resolve(Unit) @@ -144,9 +150,7 @@ object ClosedGroupsProtocolV2 { val admins = group.admins.map { it.serialize() } val adminsAsData = admins.map { Hex.fromStringCondensed(it) } val sentTime = System.currentTimeMillis() - val encryptionKeyPair = pendingKeyPair.getOrElse(groupPublicKey) { - Optional.fromNullable(apiDB.getLatestClosedGroupEncryptionKeyPair(groupPublicKey)) - }.orNull() + val encryptionKeyPair = pendingKeyPair[groupPublicKey]?.orNull() ?: Optional.fromNullable(apiDB.getLatestClosedGroupEncryptionKeyPair(groupPublicKey)).orNull() if (encryptionKeyPair == null) { Log.d("Loki", "Couldn't get encryption key pair for closed group.") throw Error.NoKeyPair @@ -359,7 +363,7 @@ object ClosedGroupsProtocolV2 { apiDB.addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey) // Notify the user (if we didn't make the group) if (userPublicKey != senderPublicKey) { - insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins) + insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, sentTimestamp) } else if (prevGroup == null) { // only notify if we created this group val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) @@ -418,7 +422,7 @@ object ClosedGroupsProtocolV2 { val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) insertOutgoingInfoMessage(context, groupID, contextType, name, members, admins, threadID, sentTimestamp) } else { - insertIncomingInfoMessage(context, senderPublicKey, groupID, contextType, signalType, name, members, admins) + insertIncomingInfoMessage(context, senderPublicKey, groupID, contextType, signalType, name, members, admins, sentTimestamp) } } @@ -450,7 +454,7 @@ object ClosedGroupsProtocolV2 { val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID, sentTimestamp) } else { - insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins) + insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, sentTimestamp) } if (userPublicKey in admins) { // send current encryption key to the latest added members @@ -489,7 +493,7 @@ object ClosedGroupsProtocolV2 { val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID, sentTimestamp) } else { - insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins) + insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, sentTimestamp) } } @@ -517,7 +521,7 @@ object ClosedGroupsProtocolV2 { val userLeft = userPublicKey == senderPublicKey // if the admin left, we left, or we are the only remaining member: remove the group - if (didAdminLeave || userLeft || updatedMemberList.size == 1) { + if (didAdminLeave || userLeft) { disableLocalGroupAndUnsubscribe(context, apiDB, groupPublicKey, groupDB, groupID, userPublicKey) } else { val isCurrentUserAdmin = admins.contains(userPublicKey) @@ -531,7 +535,7 @@ object ClosedGroupsProtocolV2 { val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) insertOutgoingInfoMessage(context, groupID, GroupContext.Type.QUIT, name, members, admins, threadID, sentTimestamp) } else { - insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.QUIT, SignalServiceGroup.Type.QUIT, name, members, admins) + insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.QUIT, SignalServiceGroup.Type.QUIT, name, members, admins, sentTimestamp) } } @@ -585,7 +589,7 @@ object ClosedGroupsProtocolV2 { val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) insertOutgoingInfoMessage(context, groupID, type0, name, members, admins, threadID, sentTimestamp) } else { - insertIncomingInfoMessage(context, senderPublicKey, groupID, type0, type1, name, members, admins) + insertIncomingInfoMessage(context, senderPublicKey, groupID, type0, type1, name, members, admins, sentTimestamp) } } @@ -652,7 +656,7 @@ object ClosedGroupsProtocolV2 { } private fun insertIncomingInfoMessage(context: Context, senderPublicKey: String, groupID: String, type0: GroupContext.Type, type1: SignalServiceGroup.Type, - name: String, members: Collection, admins: Collection) { + name: String, members: Collection, admins: Collection, sentTimestamp: Long) { val groupContextBuilder = GroupContext.newBuilder() .setId(ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(groupID))) .setType(type0) @@ -660,7 +664,7 @@ object ClosedGroupsProtocolV2 { .addAllMembers(members) .addAllAdmins(admins) val group = SignalServiceGroup(type1, GroupUtil.getDecodedGroupIDAsData(groupID), SignalServiceGroup.GroupType.SIGNAL, name, members.toList(), null, admins.toList()) - val m = IncomingTextMessage(Address.fromSerialized(senderPublicKey), 1, System.currentTimeMillis(), "", Optional.of(group), 0, true) + val m = IncomingTextMessage(Address.fromSerialized(senderPublicKey), 1, sentTimestamp, "", Optional.of(group), 0, true) val infoMessage = IncomingGroupMessage(m, groupContextBuilder.build(), "") val smsDB = DatabaseFactory.getSmsDatabase(context) smsDB.insertMessageInbox(infoMessage) diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt index 5fdd20210b..614aed7913 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt @@ -37,7 +37,7 @@ object MultiDeviceProtocol { try { messageSender.sendMessage(0, address, udAccess, Date().time, serializedMessage, false, configurationMessage.ttl.toInt(), - true, false, true, Optional.absent()) + true, false, false, Optional.absent()) TextSecurePreferences.setLastConfigurationSyncTime(context, now) } catch (e: Exception) { Log.d("Loki", "Failed to send configuration message due to error: $e.") @@ -56,7 +56,7 @@ object MultiDeviceProtocol { try { messageSender.sendMessage(0, address, udAccess, Date().time, serializedMessage, false, configurationMessage.ttl.toInt(), - true, false, true, Optional.absent()) + true, false, false, Optional.absent()) } catch (e: Exception) { Log.d("Loki", "Failed to send configuration message due to error: $e.") } @@ -92,6 +92,7 @@ object MultiDeviceProtocol { if (allOpenGroups.contains(openGroup)) continue OpenGroupUtilities.addGroup(context, openGroup, 1) } + // TODO: handle new configuration message fields or handle in new pipeline TextSecurePreferences.setConfigurationMessageSynced(context, true) } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/OpenGroupUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/OpenGroupUtilities.kt index 83d86f9f8b..45c792931a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/OpenGroupUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/OpenGroupUtilities.kt @@ -4,7 +4,7 @@ import android.content.Context import androidx.annotation.WorkerThread import org.greenrobot.eventbus.EventBus import org.thoughtcrime.securesms.ApplicationContext -import org.thoughtcrime.securesms.crypto.ProfileKeyUtil +import org.session.libsession.utilities.preferences.ProfileKeyUtil import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.groups.GroupManager import org.session.libsession.utilities.GroupUtil diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 36c74258d5..3f985ae909 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -250,22 +250,26 @@ - + android:layout_height="match_parent"> + - + - + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_conversation.xml b/app/src/main/res/layout/view_conversation.xml index ef630ee682..3546a3a987 100644 --- a/app/src/main/res/layout/view_conversation.xml +++ b/app/src/main/res/layout/view_conversation.xml @@ -3,6 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" + xmlns:tools="http://schemas.android.com/tools" android:background="@drawable/conversation_view_background" android:gravity="center_vertical" android:orientation="horizontal"> @@ -50,7 +51,7 @@ android:textSize="@dimen/medium_font_size" android:textStyle="bold" android:textColor="@color/text" - android:text="I'm a very long display name. What are you going to do about it?" /> + tools:text="I'm a very long display name. What are you going to do about it?" /> + tools:text="Sorry, gotta go fight crime again" /> - - , val openGroups: List): ControlMessage() { +class ConfigurationMessage(val closedGroups: List, val openGroups: List, val displayName: String, val profilePicture: String?, val profileKey: ByteArray): ControlMessage() { class ClosedGroup(val publicKey: String, val name: String, val encryptionKeyPair: ECKeyPair, val members: List, val admins: List) { val isValid: Boolean get() = members.isNotEmpty() && admins.isNotEmpty() @@ -57,7 +59,12 @@ class ConfigurationMessage(val closedGroups: List, val openGroups: fun getCurrent(): ConfigurationMessage { val closedGroups = mutableListOf() val openGroups = mutableListOf() - val storage = MessagingConfiguration.shared.storage + val sharedConfig = MessagingConfiguration.shared + val storage = sharedConfig.storage + val context = sharedConfig.context + val displayName = TextSecurePreferences.getProfileName(context)!! + val profilePicture = TextSecurePreferences.getProfilePictureURL(context) + val profileKey = ProfileKeyUtil.getProfileKey(context) val groups = storage.getAllGroups() for (groupRecord in groups) { if (groupRecord.isClosedGroup) { @@ -74,7 +81,8 @@ class ConfigurationMessage(val closedGroups: List, val openGroups: openGroups.add(openGroup.server) } } - return ConfigurationMessage(closedGroups, openGroups) + + return ConfigurationMessage(closedGroups, openGroups, displayName, profilePicture, profileKey) } fun fromProto(proto: SignalServiceProtos.Content): ConfigurationMessage? { @@ -82,7 +90,10 @@ class ConfigurationMessage(val closedGroups: List, val openGroups: val configurationProto = proto.configurationMessage val closedGroups = configurationProto.closedGroupsList.mapNotNull { ClosedGroup.fromProto(it) } val openGroups = configurationProto.openGroupsList - return ConfigurationMessage(closedGroups, openGroups) + val displayName = configurationProto.displayName + val profilePicture = configurationProto.profilePicture + val profileKey = configurationProto.profileKey + return ConfigurationMessage(closedGroups, openGroups, displayName, profilePicture, profileKey.toByteArray()) } } @@ -90,6 +101,9 @@ class ConfigurationMessage(val closedGroups: List, val openGroups: val configurationProto = SignalServiceProtos.ConfigurationMessage.newBuilder() configurationProto.addAllClosedGroups(closedGroups.mapNotNull { it.toProto() }) configurationProto.addAllOpenGroups(openGroups) + configurationProto.displayName = displayName + configurationProto.profilePicture = profilePicture + configurationProto.profileKey = ByteString.copyFrom(profileKey) val contentProto = SignalServiceProtos.Content.newBuilder() contentProto.configurationMessage = configurationProto.build() return contentProto.build() @@ -100,6 +114,9 @@ class ConfigurationMessage(val closedGroups: List, val openGroups: ConfigurationMessage( closedGroups: ${(closedGroups)} openGroups: ${(openGroups)} + displayName: $displayName + profilePicture: $profilePicture + profileKey: $profileKey ) """.trimIndent() } diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt index b37c2eafe7..530badd329 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt @@ -117,6 +117,7 @@ private fun MessageReceiver.handleConfigurationMessage(message: ConfigurationMes if (allOpenGroups.contains(openGroup)) continue storage.addOpenGroup(openGroup, 1) } + // TODO: in future handle the latest in config messages TextSecurePreferences.setConfigurationMessageSynced(context, true) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/ProfileKeyUtil.java b/libsession/src/main/java/org/session/libsession/utilities/preferences/ProfileKeyUtil.java similarity index 96% rename from app/src/main/java/org/thoughtcrime/securesms/crypto/ProfileKeyUtil.java rename to libsession/src/main/java/org/session/libsession/utilities/preferences/ProfileKeyUtil.java index d3260bb0c5..990164238c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/ProfileKeyUtil.java +++ b/libsession/src/main/java/org/session/libsession/utilities/preferences/ProfileKeyUtil.java @@ -1,4 +1,4 @@ -package org.thoughtcrime.securesms.crypto; +package org.session.libsession.utilities.preferences; import android.content.Context; diff --git a/libsignal/protobuf/Makefile b/libsignal/protobuf/Makefile index 9f3edc177a..7b3b733754 100644 --- a/libsignal/protobuf/Makefile +++ b/libsignal/protobuf/Makefile @@ -2,4 +2,3 @@ all: protoc25 --java_out=../src/main/java/ SignalService.proto WebSocketResources.proto protoc25 --java_out=../src/main/java/ UnidentifiedDelivery.proto - protoc25 --java_out=../src/main/java/ WhisperTextProtocol.proto diff --git a/libsignal/protobuf/SignalService.proto b/libsignal/protobuf/SignalService.proto index 4e0a646659..3d4cd889a7 100644 --- a/libsignal/protobuf/SignalService.proto +++ b/libsignal/protobuf/SignalService.proto @@ -223,8 +223,11 @@ message ConfigurationMessage { repeated bytes admins = 5; } - repeated ClosedGroup closedGroups = 1; - repeated string openGroups = 2; + repeated ClosedGroup closedGroups = 1; + repeated string openGroups = 2; + optional string displayName = 3; + optional string profilePicture = 4; + optional bytes profileKey = 5; } message ReceiptMessage { diff --git a/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java b/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java index e6f9adbe72..154ab3c025 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java +++ b/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java @@ -152,14 +152,15 @@ public class SignalServiceMessageSender { */ public SendMessageResult sendMessage(long messageID, SignalServiceAddress recipient, - Optional unidentifiedAccess, - SignalServiceDataMessage message) + Optional unidentifiedAccess, + SignalServiceDataMessage message, + boolean isSelfSend) throws IOException { byte[] content = createMessageContent(message, recipient); long timestamp = message.getTimestamp(); boolean isClosedGroup = message.group.isPresent() && message.group.get().getGroupType() == SignalServiceGroup.GroupType.SIGNAL; - SendMessageResult result = sendMessage(messageID, recipient, unidentifiedAccess, timestamp, content, false, message.getTTL(), true, isClosedGroup, message.hasVisibleContent(), message.getSyncTarget()); + SendMessageResult result = sendMessage(messageID, recipient, unidentifiedAccess, timestamp, content, false, message.getTTL(), true, isClosedGroup, message.hasVisibleContent() && !isSelfSend, message.getSyncTarget()); return result; } diff --git a/libsignal/src/main/java/org/session/libsignal/service/internal/push/SignalServiceProtos.java b/libsignal/src/main/java/org/session/libsignal/service/internal/push/SignalServiceProtos.java index 5694326b55..7577e904a1 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/internal/push/SignalServiceProtos.java +++ b/libsignal/src/main/java/org/session/libsignal/service/internal/push/SignalServiceProtos.java @@ -20116,6 +20116,46 @@ public final class SignalServiceProtos { */ com.google.protobuf.ByteString getOpenGroupsBytes(int index); + + // optional string displayName = 3; + /** + * optional string displayName = 3; + */ + boolean hasDisplayName(); + /** + * optional string displayName = 3; + */ + java.lang.String getDisplayName(); + /** + * optional string displayName = 3; + */ + com.google.protobuf.ByteString + getDisplayNameBytes(); + + // optional string profilePicture = 4; + /** + * optional string profilePicture = 4; + */ + boolean hasProfilePicture(); + /** + * optional string profilePicture = 4; + */ + java.lang.String getProfilePicture(); + /** + * optional string profilePicture = 4; + */ + com.google.protobuf.ByteString + getProfilePictureBytes(); + + // optional bytes profileKey = 5; + /** + * optional bytes profileKey = 5; + */ + boolean hasProfileKey(); + /** + * optional bytes profileKey = 5; + */ + com.google.protobuf.ByteString getProfileKey(); } /** * Protobuf type {@code signalservice.ConfigurationMessage} @@ -20184,6 +20224,21 @@ public final class SignalServiceProtos { openGroups_.add(input.readBytes()); break; } + case 26: { + bitField0_ |= 0x00000001; + displayName_ = input.readBytes(); + break; + } + case 34: { + bitField0_ |= 0x00000002; + profilePicture_ = input.readBytes(); + break; + } + case 42: { + bitField0_ |= 0x00000004; + profileKey_ = input.readBytes(); + break; + } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { @@ -21288,6 +21343,7 @@ public final class SignalServiceProtos { // @@protoc_insertion_point(class_scope:signalservice.ConfigurationMessage.ClosedGroup) } + private int bitField0_; // repeated .signalservice.ConfigurationMessage.ClosedGroup closedGroups = 1; public static final int CLOSEDGROUPS_FIELD_NUMBER = 1; private java.util.List closedGroups_; @@ -21354,9 +21410,114 @@ public final class SignalServiceProtos { return openGroups_.getByteString(index); } + // optional string displayName = 3; + public static final int DISPLAYNAME_FIELD_NUMBER = 3; + private java.lang.Object displayName_; + /** + * optional string displayName = 3; + */ + public boolean hasDisplayName() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional string displayName = 3; + */ + public java.lang.String getDisplayName() { + java.lang.Object ref = displayName_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + displayName_ = s; + } + return s; + } + } + /** + * optional string displayName = 3; + */ + public com.google.protobuf.ByteString + getDisplayNameBytes() { + java.lang.Object ref = displayName_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + displayName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + // optional string profilePicture = 4; + public static final int PROFILEPICTURE_FIELD_NUMBER = 4; + private java.lang.Object profilePicture_; + /** + * optional string profilePicture = 4; + */ + public boolean hasProfilePicture() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional string profilePicture = 4; + */ + public java.lang.String getProfilePicture() { + java.lang.Object ref = profilePicture_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + profilePicture_ = s; + } + return s; + } + } + /** + * optional string profilePicture = 4; + */ + public com.google.protobuf.ByteString + getProfilePictureBytes() { + java.lang.Object ref = profilePicture_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + profilePicture_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + // optional bytes profileKey = 5; + public static final int PROFILEKEY_FIELD_NUMBER = 5; + private com.google.protobuf.ByteString profileKey_; + /** + * optional bytes profileKey = 5; + */ + public boolean hasProfileKey() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * optional bytes profileKey = 5; + */ + public com.google.protobuf.ByteString getProfileKey() { + return profileKey_; + } + private void initFields() { closedGroups_ = java.util.Collections.emptyList(); openGroups_ = com.google.protobuf.LazyStringArrayList.EMPTY; + displayName_ = ""; + profilePicture_ = ""; + profileKey_ = com.google.protobuf.ByteString.EMPTY; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -21382,6 +21543,15 @@ public final class SignalServiceProtos { for (int i = 0; i < openGroups_.size(); i++) { output.writeBytes(2, openGroups_.getByteString(i)); } + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeBytes(3, getDisplayNameBytes()); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + output.writeBytes(4, getProfilePictureBytes()); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + output.writeBytes(5, profileKey_); + } getUnknownFields().writeTo(output); } @@ -21404,6 +21574,18 @@ public final class SignalServiceProtos { size += dataSize; size += 1 * getOpenGroupsList().size(); } + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(3, getDisplayNameBytes()); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(4, getProfilePictureBytes()); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(5, profileKey_); + } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; @@ -21529,6 +21711,12 @@ public final class SignalServiceProtos { } openGroups_ = com.google.protobuf.LazyStringArrayList.EMPTY; bitField0_ = (bitField0_ & ~0x00000002); + displayName_ = ""; + bitField0_ = (bitField0_ & ~0x00000004); + profilePicture_ = ""; + bitField0_ = (bitField0_ & ~0x00000008); + profileKey_ = com.google.protobuf.ByteString.EMPTY; + bitField0_ = (bitField0_ & ~0x00000010); return this; } @@ -21556,6 +21744,7 @@ public final class SignalServiceProtos { public org.session.libsignal.service.internal.push.SignalServiceProtos.ConfigurationMessage buildPartial() { org.session.libsignal.service.internal.push.SignalServiceProtos.ConfigurationMessage result = new org.session.libsignal.service.internal.push.SignalServiceProtos.ConfigurationMessage(this); int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; if (closedGroupsBuilder_ == null) { if (((bitField0_ & 0x00000001) == 0x00000001)) { closedGroups_ = java.util.Collections.unmodifiableList(closedGroups_); @@ -21571,6 +21760,19 @@ public final class SignalServiceProtos { bitField0_ = (bitField0_ & ~0x00000002); } result.openGroups_ = openGroups_; + if (((from_bitField0_ & 0x00000004) == 0x00000004)) { + to_bitField0_ |= 0x00000001; + } + result.displayName_ = displayName_; + if (((from_bitField0_ & 0x00000008) == 0x00000008)) { + to_bitField0_ |= 0x00000002; + } + result.profilePicture_ = profilePicture_; + if (((from_bitField0_ & 0x00000010) == 0x00000010)) { + to_bitField0_ |= 0x00000004; + } + result.profileKey_ = profileKey_; + result.bitField0_ = to_bitField0_; onBuilt(); return result; } @@ -21622,6 +21824,19 @@ public final class SignalServiceProtos { } onChanged(); } + if (other.hasDisplayName()) { + bitField0_ |= 0x00000004; + displayName_ = other.displayName_; + onChanged(); + } + if (other.hasProfilePicture()) { + bitField0_ |= 0x00000008; + profilePicture_ = other.profilePicture_; + onChanged(); + } + if (other.hasProfileKey()) { + setProfileKey(other.getProfileKey()); + } this.mergeUnknownFields(other.getUnknownFields()); return this; } @@ -21988,6 +22203,190 @@ public final class SignalServiceProtos { return this; } + // optional string displayName = 3; + private java.lang.Object displayName_ = ""; + /** + * optional string displayName = 3; + */ + public boolean hasDisplayName() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * optional string displayName = 3; + */ + public java.lang.String getDisplayName() { + java.lang.Object ref = displayName_; + if (!(ref instanceof java.lang.String)) { + java.lang.String s = ((com.google.protobuf.ByteString) ref) + .toStringUtf8(); + displayName_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string displayName = 3; + */ + public com.google.protobuf.ByteString + getDisplayNameBytes() { + java.lang.Object ref = displayName_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + displayName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string displayName = 3; + */ + public Builder setDisplayName( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; + displayName_ = value; + onChanged(); + return this; + } + /** + * optional string displayName = 3; + */ + public Builder clearDisplayName() { + bitField0_ = (bitField0_ & ~0x00000004); + displayName_ = getDefaultInstance().getDisplayName(); + onChanged(); + return this; + } + /** + * optional string displayName = 3; + */ + public Builder setDisplayNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; + displayName_ = value; + onChanged(); + return this; + } + + // optional string profilePicture = 4; + private java.lang.Object profilePicture_ = ""; + /** + * optional string profilePicture = 4; + */ + public boolean hasProfilePicture() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + /** + * optional string profilePicture = 4; + */ + public java.lang.String getProfilePicture() { + java.lang.Object ref = profilePicture_; + if (!(ref instanceof java.lang.String)) { + java.lang.String s = ((com.google.protobuf.ByteString) ref) + .toStringUtf8(); + profilePicture_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string profilePicture = 4; + */ + public com.google.protobuf.ByteString + getProfilePictureBytes() { + java.lang.Object ref = profilePicture_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + profilePicture_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string profilePicture = 4; + */ + public Builder setProfilePicture( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000008; + profilePicture_ = value; + onChanged(); + return this; + } + /** + * optional string profilePicture = 4; + */ + public Builder clearProfilePicture() { + bitField0_ = (bitField0_ & ~0x00000008); + profilePicture_ = getDefaultInstance().getProfilePicture(); + onChanged(); + return this; + } + /** + * optional string profilePicture = 4; + */ + public Builder setProfilePictureBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000008; + profilePicture_ = value; + onChanged(); + return this; + } + + // optional bytes profileKey = 5; + private com.google.protobuf.ByteString profileKey_ = com.google.protobuf.ByteString.EMPTY; + /** + * optional bytes profileKey = 5; + */ + public boolean hasProfileKey() { + return ((bitField0_ & 0x00000010) == 0x00000010); + } + /** + * optional bytes profileKey = 5; + */ + public com.google.protobuf.ByteString getProfileKey() { + return profileKey_; + } + /** + * optional bytes profileKey = 5; + */ + public Builder setProfileKey(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000010; + profileKey_ = value; + onChanged(); + return this; + } + /** + * optional bytes profileKey = 5; + */ + public Builder clearProfileKey() { + bitField0_ = (bitField0_ & ~0x00000010); + profileKey_ = getDefaultInstance().getProfileKey(); + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:signalservice.ConfigurationMessage) } @@ -30943,45 +31342,46 @@ public final class SignalServiceProtos { "\003\022\017\n\013NAME_CHANGE\020\004\022\021\n\rMEMBERS_ADDED\020\005\022\023\n" + "\017MEMBERS_REMOVED\020\006\022\017\n\013MEMBER_LEFT\020\007\022\037\n\033E" + "NCRYPTION_KEY_PAIR_REQUEST\020\010\"$\n\005Flags\022\033\n" + - "\027EXPIRATION_TIMER_UPDATE\020\002\"\366\001\n\024Configura" + + "\027EXPIRATION_TIMER_UPDATE\020\002\"\267\002\n\024Configura" + "tionMessage\022E\n\014closedGroups\030\001 \003(\0132/.sign" + "alservice.ConfigurationMessage.ClosedGro" + - "up\022\022\n\nopenGroups\030\002 \003(\t\032\202\001\n\013ClosedGroup\022\021" + - "\n\tpublicKey\030\001 \001(\014\022\014\n\004name\030\002 \001(\t\0221\n\021encry", - "ptionKeyPair\030\003 \001(\0132\026.signalservice.KeyPa" + - "ir\022\017\n\007members\030\004 \003(\014\022\016\n\006admins\030\005 \003(\014\"u\n\016R" + - "eceiptMessage\0220\n\004type\030\001 \001(\0162\".signalserv" + - "ice.ReceiptMessage.Type\022\021\n\ttimestamp\030\002 \003" + - "(\004\"\036\n\004Type\022\014\n\010DELIVERY\020\000\022\010\n\004READ\020\001\"\354\001\n\021A" + - "ttachmentPointer\022\n\n\002id\030\001 \001(\006\022\023\n\013contentT" + - "ype\030\002 \001(\t\022\013\n\003key\030\003 \001(\014\022\014\n\004size\030\004 \001(\r\022\021\n\t" + - "thumbnail\030\005 \001(\014\022\016\n\006digest\030\006 \001(\014\022\020\n\010fileN" + - "ame\030\007 \001(\t\022\r\n\005flags\030\010 \001(\r\022\r\n\005width\030\t \001(\r\022" + - "\016\n\006height\030\n \001(\r\022\017\n\007caption\030\013 \001(\t\022\013\n\003url\030", - "e \001(\t\"\032\n\005Flags\022\021\n\rVOICE_MESSAGE\020\001\"\243\002\n\014Gr" + - "oupContext\022\n\n\002id\030\001 \001(\014\022.\n\004type\030\002 \001(\0162 .s" + - "ignalservice.GroupContext.Type\022\014\n\004name\030\003" + - " \001(\t\022\017\n\007members\030\004 \003(\t\0220\n\006avatar\030\005 \001(\0132 ." + - "signalservice.AttachmentPointer\022\016\n\006admin" + - "s\030\006 \003(\t\022\023\n\nnewMembers\030\346\007 \003(\t\022\027\n\016removedM" + - "embers\030\347\007 \003(\t\"H\n\004Type\022\013\n\007UNKNOWN\020\000\022\n\n\006UP" + - "DATE\020\001\022\013\n\007DELIVER\020\002\022\010\n\004QUIT\020\003\022\020\n\014REQUEST" + - "_INFO\020\004\"\356\001\n\016ContactDetails\022\016\n\006number\030\001 \001" + - "(\t\022\014\n\004name\030\002 \001(\t\0224\n\006avatar\030\003 \001(\0132$.signa", - "lservice.ContactDetails.Avatar\022\r\n\005color\030" + - "\004 \001(\t\022\022\n\nprofileKey\030\006 \001(\014\022\017\n\007blocked\030\007 \001" + - "(\010\022\023\n\013expireTimer\030\010 \001(\r\022\020\n\010nickname\030e \001(" + - "\t\032-\n\006Avatar\022\023\n\013contentType\030\001 \001(\t\022\016\n\006leng" + - "th\030\002 \001(\r\"\367\001\n\014GroupDetails\022\n\n\002id\030\001 \001(\014\022\014\n" + - "\004name\030\002 \001(\t\022\017\n\007members\030\003 \003(\t\0222\n\006avatar\030\004" + - " \001(\0132\".signalservice.GroupDetails.Avatar" + - "\022\024\n\006active\030\005 \001(\010:\004true\022\023\n\013expireTimer\030\006 " + - "\001(\r\022\r\n\005color\030\007 \001(\t\022\017\n\007blocked\030\010 \001(\010\022\016\n\006a" + - "dmins\030\t \003(\t\032-\n\006Avatar\022\023\n\013contentType\030\001 \001", - "(\t\022\016\n\006length\030\002 \001(\r\"\"\n\016PublicChatInfo\022\020\n\010" + - "serverID\030\001 \001(\004BB\n+org.session.libsignal." + - "service.internal.pushB\023SignalServiceProt" + - "os" + "up\022\022\n\nopenGroups\030\002 \003(\t\022\023\n\013displayName\030\003 " + + "\001(\t\022\026\n\016profilePicture\030\004 \001(\t\022\022\n\nprofileKe", + "y\030\005 \001(\014\032\202\001\n\013ClosedGroup\022\021\n\tpublicKey\030\001 \001" + + "(\014\022\014\n\004name\030\002 \001(\t\0221\n\021encryptionKeyPair\030\003 " + + "\001(\0132\026.signalservice.KeyPair\022\017\n\007members\030\004" + + " \003(\014\022\016\n\006admins\030\005 \003(\014\"u\n\016ReceiptMessage\0220" + + "\n\004type\030\001 \001(\0162\".signalservice.ReceiptMess" + + "age.Type\022\021\n\ttimestamp\030\002 \003(\004\"\036\n\004Type\022\014\n\010D" + + "ELIVERY\020\000\022\010\n\004READ\020\001\"\354\001\n\021AttachmentPointe" + + "r\022\n\n\002id\030\001 \001(\006\022\023\n\013contentType\030\002 \001(\t\022\013\n\003ke" + + "y\030\003 \001(\014\022\014\n\004size\030\004 \001(\r\022\021\n\tthumbnail\030\005 \001(\014" + + "\022\016\n\006digest\030\006 \001(\014\022\020\n\010fileName\030\007 \001(\t\022\r\n\005fl", + "ags\030\010 \001(\r\022\r\n\005width\030\t \001(\r\022\016\n\006height\030\n \001(\r" + + "\022\017\n\007caption\030\013 \001(\t\022\013\n\003url\030e \001(\t\"\032\n\005Flags\022" + + "\021\n\rVOICE_MESSAGE\020\001\"\243\002\n\014GroupContext\022\n\n\002i" + + "d\030\001 \001(\014\022.\n\004type\030\002 \001(\0162 .signalservice.Gr" + + "oupContext.Type\022\014\n\004name\030\003 \001(\t\022\017\n\007members" + + "\030\004 \003(\t\0220\n\006avatar\030\005 \001(\0132 .signalservice.A" + + "ttachmentPointer\022\016\n\006admins\030\006 \003(\t\022\023\n\nnewM" + + "embers\030\346\007 \003(\t\022\027\n\016removedMembers\030\347\007 \003(\t\"H" + + "\n\004Type\022\013\n\007UNKNOWN\020\000\022\n\n\006UPDATE\020\001\022\013\n\007DELIV" + + "ER\020\002\022\010\n\004QUIT\020\003\022\020\n\014REQUEST_INFO\020\004\"\356\001\n\016Con", + "tactDetails\022\016\n\006number\030\001 \001(\t\022\014\n\004name\030\002 \001(" + + "\t\0224\n\006avatar\030\003 \001(\0132$.signalservice.Contac" + + "tDetails.Avatar\022\r\n\005color\030\004 \001(\t\022\022\n\nprofil" + + "eKey\030\006 \001(\014\022\017\n\007blocked\030\007 \001(\010\022\023\n\013expireTim" + + "er\030\010 \001(\r\022\020\n\010nickname\030e \001(\t\032-\n\006Avatar\022\023\n\013" + + "contentType\030\001 \001(\t\022\016\n\006length\030\002 \001(\r\"\367\001\n\014Gr" + + "oupDetails\022\n\n\002id\030\001 \001(\014\022\014\n\004name\030\002 \001(\t\022\017\n\007" + + "members\030\003 \003(\t\0222\n\006avatar\030\004 \001(\0132\".signalse" + + "rvice.GroupDetails.Avatar\022\024\n\006active\030\005 \001(" + + "\010:\004true\022\023\n\013expireTimer\030\006 \001(\r\022\r\n\005color\030\007 ", + "\001(\t\022\017\n\007blocked\030\010 \001(\010\022\016\n\006admins\030\t \003(\t\032-\n\006" + + "Avatar\022\023\n\013contentType\030\001 \001(\t\022\016\n\006length\030\002 " + + "\001(\r\"\"\n\016PublicChatInfo\022\020\n\010serverID\030\001 \001(\004B" + + "B\n+org.session.libsignal.service.interna" + + "l.pushB\023SignalServiceProtos" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -31101,7 +31501,7 @@ public final class SignalServiceProtos { internal_static_signalservice_ConfigurationMessage_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_signalservice_ConfigurationMessage_descriptor, - new java.lang.String[] { "ClosedGroups", "OpenGroups", }); + new java.lang.String[] { "ClosedGroups", "OpenGroups", "DisplayName", "ProfilePicture", "ProfileKey", }); internal_static_signalservice_ConfigurationMessage_ClosedGroup_descriptor = internal_static_signalservice_ConfigurationMessage_descriptor.getNestedTypes().get(0); internal_static_signalservice_ConfigurationMessage_ClosedGroup_fieldAccessorTable = new