Merge branch 'dev' of https://github.com/loki-project/session-android into refactor_clean_0

This commit is contained in:
Ryan ZHAO 2021-02-24 16:39:04 +11:00
commit d5343d5462
21 changed files with 546 additions and 106 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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<UnidentifiedAccess> 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();
}

View file

@ -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;

View file

@ -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<UnidentifiedAccess> 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();
}

View file

@ -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

View file

@ -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 {

View file

@ -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<Promise<*, Exception>>()
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

View file

@ -95,8 +95,12 @@ object ClosedGroupsProtocolV2 {
return deferred.promise
}
@JvmStatic
fun explicitLeave(context: Context, groupPublicKey: String): Promise<Unit, Exception> {
/**
* @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<Unit, Exception> {
val deferred = deferred<Unit, Exception>()
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<String>, admins: Collection<String>) {
name: String, members: Collection<String>, admins: Collection<String>, 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)

View file

@ -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)
}
}

View file

@ -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

View file

@ -250,22 +250,26 @@
</ScrollView>
<RelativeLayout
android:id="@+id/loader"
<FrameLayout
android:animateLayoutChanges="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#A4000000"
android:visibility="gone"
android:alpha="0">
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/loader"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#A4000000"
android:visibility="gone">
<com.github.ybq.android.spinkit.SpinKitView
style="@style/SpinKitView.Large.ThreeBounce"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_centerInParent="true"
app:SpinKit_Color="@android:color/white" />
<com.github.ybq.android.spinkit.SpinKitView
style="@style/SpinKitView.Large.ThreeBounce"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_centerInParent="true"
app:SpinKit_Color="@android:color/white" />
</RelativeLayout>
</RelativeLayout>
</FrameLayout>
</RelativeLayout>

View file

@ -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?" />
<TextView
android:id="@+id/timestampTextView"
@ -82,7 +83,8 @@
android:layout_marginEnd="6dp" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content">
<TextView
@ -93,7 +95,7 @@
android:ellipsize="end"
android:textSize="@dimen/medium_font_size"
android:textColor="@color/text"
android:text="Sorry, gotta go fight crime again" />
tools:text="Sorry, gotta go fight crime again" />
<org.thoughtcrime.securesms.components.TypingIndicatorView
android:id="@+id/typingIndicatorView"
@ -104,11 +106,6 @@
</RelativeLayout>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<ImageView
android:id="@+id/statusIndicatorImageView"
android:layout_width="@dimen/conversation_view_status_indicator_size"

View file

@ -4,6 +4,8 @@ import com.google.protobuf.ByteString
import org.session.libsession.messaging.MessagingConfiguration
import org.session.libsession.messaging.threads.Address
import org.session.libsession.utilities.GroupUtil
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.preferences.ProfileKeyUtil
import org.session.libsignal.libsignal.ecc.DjbECPrivateKey
import org.session.libsignal.libsignal.ecc.DjbECPublicKey
import org.session.libsignal.libsignal.ecc.ECKeyPair
@ -12,7 +14,7 @@ import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded
import org.session.libsignal.service.loki.utilities.toHexString
import org.session.libsignal.utilities.Hex
class ConfigurationMessage(val closedGroups: List<ClosedGroup>, val openGroups: List<String>): ControlMessage() {
class ConfigurationMessage(val closedGroups: List<ClosedGroup>, val openGroups: List<String>, val displayName: String, val profilePicture: String?, val profileKey: ByteArray): ControlMessage() {
class ClosedGroup(val publicKey: String, val name: String, val encryptionKeyPair: ECKeyPair, val members: List<String>, val admins: List<String>) {
val isValid: Boolean get() = members.isNotEmpty() && admins.isNotEmpty()
@ -57,7 +59,12 @@ class ConfigurationMessage(val closedGroups: List<ClosedGroup>, val openGroups:
fun getCurrent(): ConfigurationMessage {
val closedGroups = mutableListOf<ClosedGroup>()
val openGroups = mutableListOf<String>()
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<ClosedGroup>, 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<ClosedGroup>, 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<ClosedGroup>, 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<ClosedGroup>, val openGroups:
ConfigurationMessage(
closedGroups: ${(closedGroups)}
openGroups: ${(openGroups)}
displayName: $displayName
profilePicture: $profilePicture
profileKey: $profileKey
)
""".trimIndent()
}

View file

@ -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)
}

View file

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.crypto;
package org.session.libsession.utilities.preferences;
import android.content.Context;

View file

@ -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

View file

@ -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 {

View file

@ -152,14 +152,15 @@ public class SignalServiceMessageSender {
*/
public SendMessageResult sendMessage(long messageID,
SignalServiceAddress recipient,
Optional<UnidentifiedAccess> unidentifiedAccess,
SignalServiceDataMessage message)
Optional<UnidentifiedAccess> 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;
}

View file

@ -20116,6 +20116,46 @@ public final class SignalServiceProtos {
*/
com.google.protobuf.ByteString
getOpenGroupsBytes(int index);
// optional string displayName = 3;
/**
* <code>optional string displayName = 3;</code>
*/
boolean hasDisplayName();
/**
* <code>optional string displayName = 3;</code>
*/
java.lang.String getDisplayName();
/**
* <code>optional string displayName = 3;</code>
*/
com.google.protobuf.ByteString
getDisplayNameBytes();
// optional string profilePicture = 4;
/**
* <code>optional string profilePicture = 4;</code>
*/
boolean hasProfilePicture();
/**
* <code>optional string profilePicture = 4;</code>
*/
java.lang.String getProfilePicture();
/**
* <code>optional string profilePicture = 4;</code>
*/
com.google.protobuf.ByteString
getProfilePictureBytes();
// optional bytes profileKey = 5;
/**
* <code>optional bytes profileKey = 5;</code>
*/
boolean hasProfileKey();
/**
* <code>optional bytes profileKey = 5;</code>
*/
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<org.session.libsignal.service.internal.push.SignalServiceProtos.ConfigurationMessage.ClosedGroup> 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_;
/**
* <code>optional string displayName = 3;</code>
*/
public boolean hasDisplayName() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
/**
* <code>optional string displayName = 3;</code>
*/
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;
}
}
/**
* <code>optional string displayName = 3;</code>
*/
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_;
/**
* <code>optional string profilePicture = 4;</code>
*/
public boolean hasProfilePicture() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
/**
* <code>optional string profilePicture = 4;</code>
*/
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;
}
}
/**
* <code>optional string profilePicture = 4;</code>
*/
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_;
/**
* <code>optional bytes profileKey = 5;</code>
*/
public boolean hasProfileKey() {
return ((bitField0_ & 0x00000004) == 0x00000004);
}
/**
* <code>optional bytes profileKey = 5;</code>
*/
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_ = "";
/**
* <code>optional string displayName = 3;</code>
*/
public boolean hasDisplayName() {
return ((bitField0_ & 0x00000004) == 0x00000004);
}
/**
* <code>optional string displayName = 3;</code>
*/
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;
}
}
/**
* <code>optional string displayName = 3;</code>
*/
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;
}
}
/**
* <code>optional string displayName = 3;</code>
*/
public Builder setDisplayName(
java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000004;
displayName_ = value;
onChanged();
return this;
}
/**
* <code>optional string displayName = 3;</code>
*/
public Builder clearDisplayName() {
bitField0_ = (bitField0_ & ~0x00000004);
displayName_ = getDefaultInstance().getDisplayName();
onChanged();
return this;
}
/**
* <code>optional string displayName = 3;</code>
*/
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_ = "";
/**
* <code>optional string profilePicture = 4;</code>
*/
public boolean hasProfilePicture() {
return ((bitField0_ & 0x00000008) == 0x00000008);
}
/**
* <code>optional string profilePicture = 4;</code>
*/
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;
}
}
/**
* <code>optional string profilePicture = 4;</code>
*/
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;
}
}
/**
* <code>optional string profilePicture = 4;</code>
*/
public Builder setProfilePicture(
java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000008;
profilePicture_ = value;
onChanged();
return this;
}
/**
* <code>optional string profilePicture = 4;</code>
*/
public Builder clearProfilePicture() {
bitField0_ = (bitField0_ & ~0x00000008);
profilePicture_ = getDefaultInstance().getProfilePicture();
onChanged();
return this;
}
/**
* <code>optional string profilePicture = 4;</code>
*/
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;
/**
* <code>optional bytes profileKey = 5;</code>
*/
public boolean hasProfileKey() {
return ((bitField0_ & 0x00000010) == 0x00000010);
}
/**
* <code>optional bytes profileKey = 5;</code>
*/
public com.google.protobuf.ByteString getProfileKey() {
return profileKey_;
}
/**
* <code>optional bytes profileKey = 5;</code>
*/
public Builder setProfileKey(com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000010;
profileKey_ = value;
onChanged();
return this;
}
/**
* <code>optional bytes profileKey = 5;</code>
*/
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