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.sskenvironment.TypingStatusRepository;
import org.thoughtcrime.securesms.components.TypingStatusSender; import org.thoughtcrime.securesms.components.TypingStatusSender;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; 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.session.libsession.messaging.threads.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase;

View file

@ -6,6 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread; import androidx.annotation.WorkerThread;
import org.session.libsession.utilities.preferences.ProfileKeyUtil;
import org.session.libsignal.metadata.SignalProtos; import org.session.libsignal.metadata.SignalProtos;
import org.session.libsignal.utilities.logging.Log; import org.session.libsignal.utilities.logging.Log;
import org.session.libsession.messaging.threads.recipients.Recipient; 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) { 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 selection = MmsSmsColumns.THREAD_ID + " = " + threadId;
String limitStr = limit > 0 || offset > 0 ? offset + ", " + limit : null; 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()) { if (userPublicKey == address.getNumber()) {
// Loki - Device link messages don't go through here // 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) { if (result.getLokiAPIError() != null) {
throw result.getLokiAPIError(); throw result.getLokiAPIError();
} else { } else {
return result.getSuccess().isUnidentified(); return result.getSuccess().isUnidentified();
} }
} else { } else {
SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccessPair, mediaMessage); SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccessPair, mediaMessage, false);
if (result.getLokiAPIError() != null) { if (result.getLokiAPIError() != null) {
throw result.getLokiAPIError(); throw result.getLokiAPIError();
} else { } else {
@ -276,7 +276,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
try { try {
// send to ourselves to sync multi-device // send to ourselves to sync multi-device
Optional<UnidentifiedAccess> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context); 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) { if (selfSendResult.getLokiAPIError() != null) {
throw selfSendResult.getLokiAPIError(); throw selfSendResult.getLokiAPIError();
} }

View file

@ -17,7 +17,7 @@ import org.session.libsession.utilities.Util;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.contactshare.ContactModelMapper; 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.session.libsession.messaging.threads.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.events.PartProgressEvent; import org.thoughtcrime.securesms.events.PartProgressEvent;

View file

@ -197,14 +197,14 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
if (userPublicKey.equals(address.getNumber())) { if (userPublicKey.equals(address.getNumber())) {
// Loki - Device link messages don't go through here // 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) { if (result.getLokiAPIError() != null) {
throw result.getLokiAPIError(); throw result.getLokiAPIError();
} else { } else {
return result.getSuccess().isUnidentified(); return result.getSuccess().isUnidentified();
} }
} else { } else {
SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccess, textSecureMessage); SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccess, textSecureMessage, false);
if (result.getLokiAPIError() != null) { if (result.getLokiAPIError() != null) {
throw result.getLokiAPIError(); throw result.getLokiAPIError();
} else { } else {
@ -213,7 +213,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
try { try {
// send to ourselves to sync multi-device // send to ourselves to sync multi-device
Optional<UnidentifiedAccess> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context); 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) { if (selfSendResult.getLokiAPIError() != null) {
throw selfSendResult.getLokiAPIError(); throw selfSendResult.getLokiAPIError();
} }

View file

@ -82,7 +82,7 @@ public class RequestGroupInfoJob extends BaseJob implements InjectableType {
messageSender.sendMessage(0, new SignalServiceAddress(source), messageSender.sendMessage(0, new SignalServiceAddress(source),
UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromExternal(context, source), false)), UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromExternal(context, source), false)),
message); message, false);
} }
@Override @Override

View file

@ -298,7 +298,7 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
}.failUi { exception -> }.failUi { exception ->
val message = if (exception is ClosedGroupsProtocolV2.Error) exception.description else "An error occurred" val message = if (exception is ClosedGroupsProtocolV2.Error) exception.description else "An error occurred"
Toast.makeText(this@EditClosedGroupActivity, message, Toast.LENGTH_LONG).show() Toast.makeText(this@EditClosedGroupActivity, message, Toast.LENGTH_LONG).show()
loader.fadeOut() loaderContainer.fadeOut()
isLoading = false isLoading = false
} }
} else { } else {

View file

@ -17,25 +17,26 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.Toast import android.widget.Toast
import androidx.core.view.isVisible
import kotlinx.android.synthetic.main.activity_settings.* import kotlinx.android.synthetic.main.activity_settings.*
import network.loki.messenger.BuildConfig import network.loki.messenger.BuildConfig
import network.loki.messenger.R import network.loki.messenger.R
import nl.komponents.kovenant.Promise import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.all import nl.komponents.kovenant.all
import nl.komponents.kovenant.deferred import nl.komponents.kovenant.deferred
import nl.komponents.kovenant.functional.bind
import nl.komponents.kovenant.task
import nl.komponents.kovenant.ui.alwaysUi import nl.komponents.kovenant.ui.alwaysUi
import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.avatar.AvatarSelection 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.session.libsession.messaging.threads.Address
import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.loki.dialogs.ChangeUiModeDialog import org.thoughtcrime.securesms.loki.dialogs.ChangeUiModeDialog
import org.thoughtcrime.securesms.loki.dialogs.ClearAllDataDialog import org.thoughtcrime.securesms.loki.dialogs.ClearAllDataDialog
import org.thoughtcrime.securesms.loki.dialogs.SeedDialog import org.thoughtcrime.securesms.loki.dialogs.SeedDialog
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities 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.loki.utilities.push
import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.mms.GlideApp
import org.thoughtcrime.securesms.mms.GlideRequests 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.libsession.utilities.TextSecurePreferences
import org.session.libsignal.service.api.util.StreamDetails import org.session.libsignal.service.api.util.StreamDetails
import org.session.libsignal.service.loki.api.fileserver.FileServerAPI import org.session.libsignal.service.loki.api.fileserver.FileServerAPI
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.File import java.io.File
import java.security.SecureRandom import java.security.SecureRandom
@ -169,7 +171,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
} }
private fun updateProfile(isUpdatingProfilePicture: Boolean) { private fun updateProfile(isUpdatingProfilePicture: Boolean) {
loader.fadeIn() loader.isVisible = true
val promises = mutableListOf<Promise<*, Exception>>() val promises = mutableListOf<Promise<*, Exception>>()
val displayName = displayNameToBeUploaded val displayName = displayNameToBeUploaded
if (displayName != null) { if (displayName != null) {
@ -196,7 +198,17 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
} }
promises.add(deferred.promise) 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) { if (displayName != null) {
btnGroupNameDisplay.text = displayName btnGroupNameDisplay.text = displayName
} }
@ -209,7 +221,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
profilePictureView.update() profilePictureView.update()
} }
profilePictureToBeUploaded = null profilePictureToBeUploaded = null
loader.fadeOut() loader.isVisible = false
} }
} }
// endregion // endregion

View file

@ -95,8 +95,12 @@ object ClosedGroupsProtocolV2 {
return deferred.promise 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>() val deferred = deferred<Unit, Exception>()
ThreadUtils.queue { ThreadUtils.queue {
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!! val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
@ -120,7 +124,9 @@ object ClosedGroupsProtocolV2 {
// Notify the user // Notify the user
val infoType = GroupContext.Type.QUIT val infoType = GroupContext.Type.QUIT
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) 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 // Remove the group private key and unsubscribe from PNs
disableLocalGroupAndUnsubscribe(context, apiDB, groupPublicKey, groupDB, groupID, userPublicKey) disableLocalGroupAndUnsubscribe(context, apiDB, groupPublicKey, groupDB, groupID, userPublicKey)
deferred.resolve(Unit) deferred.resolve(Unit)
@ -144,9 +150,7 @@ object ClosedGroupsProtocolV2 {
val admins = group.admins.map { it.serialize() } val admins = group.admins.map { it.serialize() }
val adminsAsData = admins.map { Hex.fromStringCondensed(it) } val adminsAsData = admins.map { Hex.fromStringCondensed(it) }
val sentTime = System.currentTimeMillis() val sentTime = System.currentTimeMillis()
val encryptionKeyPair = pendingKeyPair.getOrElse(groupPublicKey) { val encryptionKeyPair = pendingKeyPair[groupPublicKey]?.orNull() ?: Optional.fromNullable(apiDB.getLatestClosedGroupEncryptionKeyPair(groupPublicKey)).orNull()
Optional.fromNullable(apiDB.getLatestClosedGroupEncryptionKeyPair(groupPublicKey))
}.orNull()
if (encryptionKeyPair == null) { if (encryptionKeyPair == null) {
Log.d("Loki", "Couldn't get encryption key pair for closed group.") Log.d("Loki", "Couldn't get encryption key pair for closed group.")
throw Error.NoKeyPair throw Error.NoKeyPair
@ -359,7 +363,7 @@ object ClosedGroupsProtocolV2 {
apiDB.addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey) apiDB.addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey)
// Notify the user (if we didn't make the group) // Notify the user (if we didn't make the group)
if (userPublicKey != senderPublicKey) { 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) { } else if (prevGroup == null) {
// only notify if we created this group // only notify if we created this group
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
@ -418,7 +422,7 @@ object ClosedGroupsProtocolV2 {
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
insertOutgoingInfoMessage(context, groupID, contextType, name, members, admins, threadID, sentTimestamp) insertOutgoingInfoMessage(context, groupID, contextType, name, members, admins, threadID, sentTimestamp)
} else { } 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) val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID, sentTimestamp) insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID, sentTimestamp)
} else { } 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) { if (userPublicKey in admins) {
// send current encryption key to the latest added members // send current encryption key to the latest added members
@ -489,7 +493,7 @@ object ClosedGroupsProtocolV2 {
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID, sentTimestamp) insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID, sentTimestamp)
} else { } 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 val userLeft = userPublicKey == senderPublicKey
// if the admin left, we left, or we are the only remaining member: remove the group // 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) disableLocalGroupAndUnsubscribe(context, apiDB, groupPublicKey, groupDB, groupID, userPublicKey)
} else { } else {
val isCurrentUserAdmin = admins.contains(userPublicKey) val isCurrentUserAdmin = admins.contains(userPublicKey)
@ -531,7 +535,7 @@ object ClosedGroupsProtocolV2 {
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
insertOutgoingInfoMessage(context, groupID, GroupContext.Type.QUIT, name, members, admins, threadID, sentTimestamp) insertOutgoingInfoMessage(context, groupID, GroupContext.Type.QUIT, name, members, admins, threadID, sentTimestamp)
} else { } 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) val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
insertOutgoingInfoMessage(context, groupID, type0, name, members, admins, threadID, sentTimestamp) insertOutgoingInfoMessage(context, groupID, type0, name, members, admins, threadID, sentTimestamp)
} else { } 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, 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() val groupContextBuilder = GroupContext.newBuilder()
.setId(ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(groupID))) .setId(ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(groupID)))
.setType(type0) .setType(type0)
@ -660,7 +664,7 @@ object ClosedGroupsProtocolV2 {
.addAllMembers(members) .addAllMembers(members)
.addAllAdmins(admins) .addAllAdmins(admins)
val group = SignalServiceGroup(type1, GroupUtil.getDecodedGroupIDAsData(groupID), SignalServiceGroup.GroupType.SIGNAL, name, members.toList(), null, admins.toList()) 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 infoMessage = IncomingGroupMessage(m, groupContextBuilder.build(), "")
val smsDB = DatabaseFactory.getSmsDatabase(context) val smsDB = DatabaseFactory.getSmsDatabase(context)
smsDB.insertMessageInbox(infoMessage) smsDB.insertMessageInbox(infoMessage)

View file

@ -37,7 +37,7 @@ object MultiDeviceProtocol {
try { try {
messageSender.sendMessage(0, address, udAccess, messageSender.sendMessage(0, address, udAccess,
Date().time, serializedMessage, false, configurationMessage.ttl.toInt(), Date().time, serializedMessage, false, configurationMessage.ttl.toInt(),
true, false, true, Optional.absent()) true, false, false, Optional.absent())
TextSecurePreferences.setLastConfigurationSyncTime(context, now) TextSecurePreferences.setLastConfigurationSyncTime(context, now)
} catch (e: Exception) { } catch (e: Exception) {
Log.d("Loki", "Failed to send configuration message due to error: $e.") Log.d("Loki", "Failed to send configuration message due to error: $e.")
@ -56,7 +56,7 @@ object MultiDeviceProtocol {
try { try {
messageSender.sendMessage(0, address, udAccess, messageSender.sendMessage(0, address, udAccess,
Date().time, serializedMessage, false, configurationMessage.ttl.toInt(), Date().time, serializedMessage, false, configurationMessage.ttl.toInt(),
true, false, true, Optional.absent()) true, false, false, Optional.absent())
} catch (e: Exception) { } catch (e: Exception) {
Log.d("Loki", "Failed to send configuration message due to error: $e.") Log.d("Loki", "Failed to send configuration message due to error: $e.")
} }
@ -92,6 +92,7 @@ object MultiDeviceProtocol {
if (allOpenGroups.contains(openGroup)) continue if (allOpenGroups.contains(openGroup)) continue
OpenGroupUtilities.addGroup(context, openGroup, 1) OpenGroupUtilities.addGroup(context, openGroup, 1)
} }
// TODO: handle new configuration message fields or handle in new pipeline
TextSecurePreferences.setConfigurationMessageSynced(context, true) TextSecurePreferences.setConfigurationMessageSynced(context, true)
} }
} }

View file

@ -4,7 +4,7 @@ import android.content.Context
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import org.thoughtcrime.securesms.ApplicationContext 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.database.DatabaseFactory
import org.thoughtcrime.securesms.groups.GroupManager import org.thoughtcrime.securesms.groups.GroupManager
import org.session.libsession.utilities.GroupUtil import org.session.libsession.utilities.GroupUtil

View file

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

View file

@ -3,6 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:background="@drawable/conversation_view_background" android:background="@drawable/conversation_view_background"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal">
@ -50,7 +51,7 @@
android:textSize="@dimen/medium_font_size" android:textSize="@dimen/medium_font_size"
android:textStyle="bold" android:textStyle="bold"
android:textColor="@color/text" 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 <TextView
android:id="@+id/timestampTextView" android:id="@+id/timestampTextView"
@ -82,7 +83,8 @@
android:layout_marginEnd="6dp" /> android:layout_marginEnd="6dp" />
<RelativeLayout <RelativeLayout
android:layout_width="wrap_content" android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<TextView <TextView
@ -93,7 +95,7 @@
android:ellipsize="end" android:ellipsize="end"
android:textSize="@dimen/medium_font_size" android:textSize="@dimen/medium_font_size"
android:textColor="@color/text" 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 <org.thoughtcrime.securesms.components.TypingIndicatorView
android:id="@+id/typingIndicatorView" android:id="@+id/typingIndicatorView"
@ -104,11 +106,6 @@
</RelativeLayout> </RelativeLayout>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<ImageView <ImageView
android:id="@+id/statusIndicatorImageView" android:id="@+id/statusIndicatorImageView"
android:layout_width="@dimen/conversation_view_status_indicator_size" 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.MessagingConfiguration
import org.session.libsession.messaging.threads.Address import org.session.libsession.messaging.threads.Address
import org.session.libsession.utilities.GroupUtil 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.DjbECPrivateKey
import org.session.libsignal.libsignal.ecc.DjbECPublicKey import org.session.libsignal.libsignal.ecc.DjbECPublicKey
import org.session.libsignal.libsignal.ecc.ECKeyPair 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.service.loki.utilities.toHexString
import org.session.libsignal.utilities.Hex 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>) { 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() val isValid: Boolean get() = members.isNotEmpty() && admins.isNotEmpty()
@ -57,7 +59,12 @@ class ConfigurationMessage(val closedGroups: List<ClosedGroup>, val openGroups:
fun getCurrent(): ConfigurationMessage { fun getCurrent(): ConfigurationMessage {
val closedGroups = mutableListOf<ClosedGroup>() val closedGroups = mutableListOf<ClosedGroup>()
val openGroups = mutableListOf<String>() 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() val groups = storage.getAllGroups()
for (groupRecord in groups) { for (groupRecord in groups) {
if (groupRecord.isClosedGroup) { if (groupRecord.isClosedGroup) {
@ -74,7 +81,8 @@ class ConfigurationMessage(val closedGroups: List<ClosedGroup>, val openGroups:
openGroups.add(openGroup.server) openGroups.add(openGroup.server)
} }
} }
return ConfigurationMessage(closedGroups, openGroups)
return ConfigurationMessage(closedGroups, openGroups, displayName, profilePicture, profileKey)
} }
fun fromProto(proto: SignalServiceProtos.Content): ConfigurationMessage? { fun fromProto(proto: SignalServiceProtos.Content): ConfigurationMessage? {
@ -82,7 +90,10 @@ class ConfigurationMessage(val closedGroups: List<ClosedGroup>, val openGroups:
val configurationProto = proto.configurationMessage val configurationProto = proto.configurationMessage
val closedGroups = configurationProto.closedGroupsList.mapNotNull { ClosedGroup.fromProto(it) } val closedGroups = configurationProto.closedGroupsList.mapNotNull { ClosedGroup.fromProto(it) }
val openGroups = configurationProto.openGroupsList 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() val configurationProto = SignalServiceProtos.ConfigurationMessage.newBuilder()
configurationProto.addAllClosedGroups(closedGroups.mapNotNull { it.toProto() }) configurationProto.addAllClosedGroups(closedGroups.mapNotNull { it.toProto() })
configurationProto.addAllOpenGroups(openGroups) configurationProto.addAllOpenGroups(openGroups)
configurationProto.displayName = displayName
configurationProto.profilePicture = profilePicture
configurationProto.profileKey = ByteString.copyFrom(profileKey)
val contentProto = SignalServiceProtos.Content.newBuilder() val contentProto = SignalServiceProtos.Content.newBuilder()
contentProto.configurationMessage = configurationProto.build() contentProto.configurationMessage = configurationProto.build()
return contentProto.build() return contentProto.build()
@ -100,6 +114,9 @@ class ConfigurationMessage(val closedGroups: List<ClosedGroup>, val openGroups:
ConfigurationMessage( ConfigurationMessage(
closedGroups: ${(closedGroups)} closedGroups: ${(closedGroups)}
openGroups: ${(openGroups)} openGroups: ${(openGroups)}
displayName: $displayName
profilePicture: $profilePicture
profileKey: $profileKey
) )
""".trimIndent() """.trimIndent()
} }

View file

@ -117,6 +117,7 @@ private fun MessageReceiver.handleConfigurationMessage(message: ConfigurationMes
if (allOpenGroups.contains(openGroup)) continue if (allOpenGroups.contains(openGroup)) continue
storage.addOpenGroup(openGroup, 1) storage.addOpenGroup(openGroup, 1)
} }
// TODO: in future handle the latest in config messages
TextSecurePreferences.setConfigurationMessageSynced(context, true) 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; import android.content.Context;

View file

@ -2,4 +2,3 @@
all: all:
protoc25 --java_out=../src/main/java/ SignalService.proto WebSocketResources.proto protoc25 --java_out=../src/main/java/ SignalService.proto WebSocketResources.proto
protoc25 --java_out=../src/main/java/ UnidentifiedDelivery.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 bytes admins = 5;
} }
repeated ClosedGroup closedGroups = 1; repeated ClosedGroup closedGroups = 1;
repeated string openGroups = 2; repeated string openGroups = 2;
optional string displayName = 3;
optional string profilePicture = 4;
optional bytes profileKey = 5;
} }
message ReceiptMessage { message ReceiptMessage {

View file

@ -152,14 +152,15 @@ public class SignalServiceMessageSender {
*/ */
public SendMessageResult sendMessage(long messageID, public SendMessageResult sendMessage(long messageID,
SignalServiceAddress recipient, SignalServiceAddress recipient,
Optional<UnidentifiedAccess> unidentifiedAccess, Optional<UnidentifiedAccess> unidentifiedAccess,
SignalServiceDataMessage message) SignalServiceDataMessage message,
boolean isSelfSend)
throws IOException throws IOException
{ {
byte[] content = createMessageContent(message, recipient); byte[] content = createMessageContent(message, recipient);
long timestamp = message.getTimestamp(); long timestamp = message.getTimestamp();
boolean isClosedGroup = message.group.isPresent() && message.group.get().getGroupType() == SignalServiceGroup.GroupType.SIGNAL; 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; return result;
} }

View file

@ -20116,6 +20116,46 @@ public final class SignalServiceProtos {
*/ */
com.google.protobuf.ByteString com.google.protobuf.ByteString
getOpenGroupsBytes(int index); 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} * Protobuf type {@code signalservice.ConfigurationMessage}
@ -20184,6 +20224,21 @@ public final class SignalServiceProtos {
openGroups_.add(input.readBytes()); openGroups_.add(input.readBytes());
break; 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) { } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@ -21288,6 +21343,7 @@ public final class SignalServiceProtos {
// @@protoc_insertion_point(class_scope:signalservice.ConfigurationMessage.ClosedGroup) // @@protoc_insertion_point(class_scope:signalservice.ConfigurationMessage.ClosedGroup)
} }
private int bitField0_;
// repeated .signalservice.ConfigurationMessage.ClosedGroup closedGroups = 1; // repeated .signalservice.ConfigurationMessage.ClosedGroup closedGroups = 1;
public static final int CLOSEDGROUPS_FIELD_NUMBER = 1; public static final int CLOSEDGROUPS_FIELD_NUMBER = 1;
private java.util.List<org.session.libsignal.service.internal.push.SignalServiceProtos.ConfigurationMessage.ClosedGroup> closedGroups_; 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); 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() { private void initFields() {
closedGroups_ = java.util.Collections.emptyList(); closedGroups_ = java.util.Collections.emptyList();
openGroups_ = com.google.protobuf.LazyStringArrayList.EMPTY; openGroups_ = com.google.protobuf.LazyStringArrayList.EMPTY;
displayName_ = "";
profilePicture_ = "";
profileKey_ = com.google.protobuf.ByteString.EMPTY;
} }
private byte memoizedIsInitialized = -1; private byte memoizedIsInitialized = -1;
public final boolean isInitialized() { public final boolean isInitialized() {
@ -21382,6 +21543,15 @@ public final class SignalServiceProtos {
for (int i = 0; i < openGroups_.size(); i++) { for (int i = 0; i < openGroups_.size(); i++) {
output.writeBytes(2, openGroups_.getByteString(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); getUnknownFields().writeTo(output);
} }
@ -21404,6 +21574,18 @@ public final class SignalServiceProtos {
size += dataSize; size += dataSize;
size += 1 * getOpenGroupsList().size(); 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(); size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size; memoizedSerializedSize = size;
return size; return size;
@ -21529,6 +21711,12 @@ public final class SignalServiceProtos {
} }
openGroups_ = com.google.protobuf.LazyStringArrayList.EMPTY; openGroups_ = com.google.protobuf.LazyStringArrayList.EMPTY;
bitField0_ = (bitField0_ & ~0x00000002); bitField0_ = (bitField0_ & ~0x00000002);
displayName_ = "";
bitField0_ = (bitField0_ & ~0x00000004);
profilePicture_ = "";
bitField0_ = (bitField0_ & ~0x00000008);
profileKey_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000010);
return this; return this;
} }
@ -21556,6 +21744,7 @@ public final class SignalServiceProtos {
public org.session.libsignal.service.internal.push.SignalServiceProtos.ConfigurationMessage buildPartial() { 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); org.session.libsignal.service.internal.push.SignalServiceProtos.ConfigurationMessage result = new org.session.libsignal.service.internal.push.SignalServiceProtos.ConfigurationMessage(this);
int from_bitField0_ = bitField0_; int from_bitField0_ = bitField0_;
int to_bitField0_ = 0;
if (closedGroupsBuilder_ == null) { if (closedGroupsBuilder_ == null) {
if (((bitField0_ & 0x00000001) == 0x00000001)) { if (((bitField0_ & 0x00000001) == 0x00000001)) {
closedGroups_ = java.util.Collections.unmodifiableList(closedGroups_); closedGroups_ = java.util.Collections.unmodifiableList(closedGroups_);
@ -21571,6 +21760,19 @@ public final class SignalServiceProtos {
bitField0_ = (bitField0_ & ~0x00000002); bitField0_ = (bitField0_ & ~0x00000002);
} }
result.openGroups_ = openGroups_; 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(); onBuilt();
return result; return result;
} }
@ -21622,6 +21824,19 @@ public final class SignalServiceProtos {
} }
onChanged(); 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()); this.mergeUnknownFields(other.getUnknownFields());
return this; return this;
} }
@ -21988,6 +22203,190 @@ public final class SignalServiceProtos {
return this; 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) // @@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" + "\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" + "\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" + "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" + "tionMessage\022E\n\014closedGroups\030\001 \003(\0132/.sign" +
"alservice.ConfigurationMessage.ClosedGro" + "alservice.ConfigurationMessage.ClosedGro" +
"up\022\022\n\nopenGroups\030\002 \003(\t\032\202\001\n\013ClosedGroup\022\021" + "up\022\022\n\nopenGroups\030\002 \003(\t\022\023\n\013displayName\030\003 " +
"\n\tpublicKey\030\001 \001(\014\022\014\n\004name\030\002 \001(\t\0221\n\021encry", "\001(\t\022\026\n\016profilePicture\030\004 \001(\t\022\022\n\nprofileKe",
"ptionKeyPair\030\003 \001(\0132\026.signalservice.KeyPa" + "y\030\005 \001(\014\032\202\001\n\013ClosedGroup\022\021\n\tpublicKey\030\001 \001" +
"ir\022\017\n\007members\030\004 \003(\014\022\016\n\006admins\030\005 \003(\014\"u\n\016R" + "(\014\022\014\n\004name\030\002 \001(\t\0221\n\021encryptionKeyPair\030\003 " +
"eceiptMessage\0220\n\004type\030\001 \001(\0162\".signalserv" + "\001(\0132\026.signalservice.KeyPair\022\017\n\007members\030\004" +
"ice.ReceiptMessage.Type\022\021\n\ttimestamp\030\002 \003" + " \003(\014\022\016\n\006admins\030\005 \003(\014\"u\n\016ReceiptMessage\0220" +
"(\004\"\036\n\004Type\022\014\n\010DELIVERY\020\000\022\010\n\004READ\020\001\"\354\001\n\021A" + "\n\004type\030\001 \001(\0162\".signalservice.ReceiptMess" +
"ttachmentPointer\022\n\n\002id\030\001 \001(\006\022\023\n\013contentT" + "age.Type\022\021\n\ttimestamp\030\002 \003(\004\"\036\n\004Type\022\014\n\010D" +
"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" + "ELIVERY\020\000\022\010\n\004READ\020\001\"\354\001\n\021AttachmentPointe" +
"thumbnail\030\005 \001(\014\022\016\n\006digest\030\006 \001(\014\022\020\n\010fileN" + "r\022\n\n\002id\030\001 \001(\006\022\023\n\013contentType\030\002 \001(\t\022\013\n\003ke" +
"ame\030\007 \001(\t\022\r\n\005flags\030\010 \001(\r\022\r\n\005width\030\t \001(\r\022" + "y\030\003 \001(\014\022\014\n\004size\030\004 \001(\r\022\021\n\tthumbnail\030\005 \001(\014" +
"\016\n\006height\030\n \001(\r\022\017\n\007caption\030\013 \001(\t\022\013\n\003url\030", "\022\016\n\006digest\030\006 \001(\014\022\020\n\010fileName\030\007 \001(\t\022\r\n\005fl",
"e \001(\t\"\032\n\005Flags\022\021\n\rVOICE_MESSAGE\020\001\"\243\002\n\014Gr" + "ags\030\010 \001(\r\022\r\n\005width\030\t \001(\r\022\016\n\006height\030\n \001(\r" +
"oupContext\022\n\n\002id\030\001 \001(\014\022.\n\004type\030\002 \001(\0162 .s" + "\022\017\n\007caption\030\013 \001(\t\022\013\n\003url\030e \001(\t\"\032\n\005Flags\022" +
"ignalservice.GroupContext.Type\022\014\n\004name\030\003" + "\021\n\rVOICE_MESSAGE\020\001\"\243\002\n\014GroupContext\022\n\n\002i" +
" \001(\t\022\017\n\007members\030\004 \003(\t\0220\n\006avatar\030\005 \001(\0132 ." + "d\030\001 \001(\014\022.\n\004type\030\002 \001(\0162 .signalservice.Gr" +
"signalservice.AttachmentPointer\022\016\n\006admin" + "oupContext.Type\022\014\n\004name\030\003 \001(\t\022\017\n\007members" +
"s\030\006 \003(\t\022\023\n\nnewMembers\030\346\007 \003(\t\022\027\n\016removedM" + "\030\004 \003(\t\0220\n\006avatar\030\005 \001(\0132 .signalservice.A" +
"embers\030\347\007 \003(\t\"H\n\004Type\022\013\n\007UNKNOWN\020\000\022\n\n\006UP" + "ttachmentPointer\022\016\n\006admins\030\006 \003(\t\022\023\n\nnewM" +
"DATE\020\001\022\013\n\007DELIVER\020\002\022\010\n\004QUIT\020\003\022\020\n\014REQUEST" + "embers\030\346\007 \003(\t\022\027\n\016removedMembers\030\347\007 \003(\t\"H" +
"_INFO\020\004\"\356\001\n\016ContactDetails\022\016\n\006number\030\001 \001" + "\n\004Type\022\013\n\007UNKNOWN\020\000\022\n\n\006UPDATE\020\001\022\013\n\007DELIV" +
"(\t\022\014\n\004name\030\002 \001(\t\0224\n\006avatar\030\003 \001(\0132$.signa", "ER\020\002\022\010\n\004QUIT\020\003\022\020\n\014REQUEST_INFO\020\004\"\356\001\n\016Con",
"lservice.ContactDetails.Avatar\022\r\n\005color\030" + "tactDetails\022\016\n\006number\030\001 \001(\t\022\014\n\004name\030\002 \001(" +
"\004 \001(\t\022\022\n\nprofileKey\030\006 \001(\014\022\017\n\007blocked\030\007 \001" + "\t\0224\n\006avatar\030\003 \001(\0132$.signalservice.Contac" +
"(\010\022\023\n\013expireTimer\030\010 \001(\r\022\020\n\010nickname\030e \001(" + "tDetails.Avatar\022\r\n\005color\030\004 \001(\t\022\022\n\nprofil" +
"\t\032-\n\006Avatar\022\023\n\013contentType\030\001 \001(\t\022\016\n\006leng" + "eKey\030\006 \001(\014\022\017\n\007blocked\030\007 \001(\010\022\023\n\013expireTim" +
"th\030\002 \001(\r\"\367\001\n\014GroupDetails\022\n\n\002id\030\001 \001(\014\022\014\n" + "er\030\010 \001(\r\022\020\n\010nickname\030e \001(\t\032-\n\006Avatar\022\023\n\013" +
"\004name\030\002 \001(\t\022\017\n\007members\030\003 \003(\t\0222\n\006avatar\030\004" + "contentType\030\001 \001(\t\022\016\n\006length\030\002 \001(\r\"\367\001\n\014Gr" +
" \001(\0132\".signalservice.GroupDetails.Avatar" + "oupDetails\022\n\n\002id\030\001 \001(\014\022\014\n\004name\030\002 \001(\t\022\017\n\007" +
"\022\024\n\006active\030\005 \001(\010:\004true\022\023\n\013expireTimer\030\006 " + "members\030\003 \003(\t\0222\n\006avatar\030\004 \001(\0132\".signalse" +
"\001(\r\022\r\n\005color\030\007 \001(\t\022\017\n\007blocked\030\010 \001(\010\022\016\n\006a" + "rvice.GroupDetails.Avatar\022\024\n\006active\030\005 \001(" +
"dmins\030\t \003(\t\032-\n\006Avatar\022\023\n\013contentType\030\001 \001", "\010:\004true\022\023\n\013expireTimer\030\006 \001(\r\022\r\n\005color\030\007 ",
"(\t\022\016\n\006length\030\002 \001(\r\"\"\n\016PublicChatInfo\022\020\n\010" + "\001(\t\022\017\n\007blocked\030\010 \001(\010\022\016\n\006admins\030\t \003(\t\032-\n\006" +
"serverID\030\001 \001(\004BB\n+org.session.libsignal." + "Avatar\022\023\n\013contentType\030\001 \001(\t\022\016\n\006length\030\002 " +
"service.internal.pushB\023SignalServiceProt" + "\001(\r\"\"\n\016PublicChatInfo\022\020\n\010serverID\030\001 \001(\004B" +
"os" "B\n+org.session.libsignal.service.interna" +
"l.pushB\023SignalServiceProtos"
}; };
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@ -31101,7 +31501,7 @@ public final class SignalServiceProtos {
internal_static_signalservice_ConfigurationMessage_fieldAccessorTable = new internal_static_signalservice_ConfigurationMessage_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable( com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_signalservice_ConfigurationMessage_descriptor, 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_ClosedGroup_descriptor =
internal_static_signalservice_ConfigurationMessage_descriptor.getNestedTypes().get(0); internal_static_signalservice_ConfigurationMessage_descriptor.getNestedTypes().get(0);
internal_static_signalservice_ConfigurationMessage_ClosedGroup_fieldAccessorTable = new internal_static_signalservice_ConfigurationMessage_ClosedGroup_fieldAccessorTable = new