mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-23 12:38:33 +00:00
Update backup proto with subscriber and recipient changes.
This commit is contained in:
@@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.backup.v2.proto.ChatItem
|
|||||||
import org.thoughtcrime.securesms.backup.v2.proto.ChatUpdateMessage
|
import org.thoughtcrime.securesms.backup.v2.proto.ChatUpdateMessage
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.Contact
|
import org.thoughtcrime.securesms.backup.v2.proto.Contact
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.DistributionList
|
import org.thoughtcrime.securesms.backup.v2.proto.DistributionList
|
||||||
|
import org.thoughtcrime.securesms.backup.v2.proto.DistributionListItem
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.ExpirationTimerChatUpdate
|
import org.thoughtcrime.securesms.backup.v2.proto.ExpirationTimerChatUpdate
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.FilePointer
|
import org.thoughtcrime.securesms.backup.v2.proto.FilePointer
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||||
@@ -85,9 +86,11 @@ class ImportExportTest {
|
|||||||
givenName = "Peter",
|
givenName = "Peter",
|
||||||
familyName = "Parker",
|
familyName = "Parker",
|
||||||
avatarUrlPath = "https://example.com/",
|
avatarUrlPath = "https://example.com/",
|
||||||
subscriberId = SubscriberId.generate().bytes.toByteString(),
|
donationSubscriberData = AccountData.SubscriberData(
|
||||||
subscriberCurrencyCode = "USD",
|
subscriberId = SubscriberId.generate().bytes.toByteString(),
|
||||||
subscriptionManuallyCancelled = true,
|
currencyCode = "USD",
|
||||||
|
manuallyCancelled = true
|
||||||
|
),
|
||||||
accountSettings = AccountData.AccountSettings(
|
accountSettings = AccountData.AccountSettings(
|
||||||
readReceipts = true,
|
readReceipts = true,
|
||||||
sealedSenderIndicators = true,
|
sealedSenderIndicators = true,
|
||||||
@@ -116,9 +119,8 @@ class ImportExportTest {
|
|||||||
username = "cool.01",
|
username = "cool.01",
|
||||||
e164 = 141255501234,
|
e164 = 141255501234,
|
||||||
blocked = false,
|
blocked = false,
|
||||||
hidden = false,
|
visibility = Contact.Visibility.VISIBLE,
|
||||||
registered = Contact.Registered.REGISTERED,
|
registered = Contact.Registered(),
|
||||||
unregisteredTimestamp = 0L,
|
|
||||||
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
||||||
profileSharing = true,
|
profileSharing = true,
|
||||||
profileGivenName = "Alexa",
|
profileGivenName = "Alexa",
|
||||||
@@ -171,9 +173,8 @@ class ImportExportTest {
|
|||||||
username = "rec$i.01",
|
username = "rec$i.01",
|
||||||
e164 = 14125550000 + i,
|
e164 = 14125550000 + i,
|
||||||
blocked = false,
|
blocked = false,
|
||||||
hidden = false,
|
visibility = Contact.Visibility.VISIBLE,
|
||||||
registered = Contact.Registered.REGISTERED,
|
registered = Contact.Registered(),
|
||||||
unregisteredTimestamp = 0L,
|
|
||||||
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
||||||
profileSharing = true,
|
profileSharing = true,
|
||||||
profileGivenName = "Test",
|
profileGivenName = "Test",
|
||||||
@@ -237,9 +238,8 @@ class ImportExportTest {
|
|||||||
username = if (random.trueWithProbability(0.2f)) "rec$i.01" else null,
|
username = if (random.trueWithProbability(0.2f)) "rec$i.01" else null,
|
||||||
e164 = 14125550000 + i,
|
e164 = 14125550000 + i,
|
||||||
blocked = random.trueWithProbability(0.1f),
|
blocked = random.trueWithProbability(0.1f),
|
||||||
hidden = random.trueWithProbability(0.1f),
|
visibility = if (random.trueWithProbability(0.1f)) Contact.Visibility.HIDDEN else Contact.Visibility.VISIBLE,
|
||||||
registered = Contact.Registered.REGISTERED,
|
registered = Contact.Registered(),
|
||||||
unregisteredTimestamp = 0L,
|
|
||||||
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
||||||
profileSharing = random.trueWithProbability(0.9f),
|
profileSharing = random.trueWithProbability(0.9f),
|
||||||
profileGivenName = "Test",
|
profileGivenName = "Test",
|
||||||
@@ -390,9 +390,8 @@ class ImportExportTest {
|
|||||||
username = "cool.01",
|
username = "cool.01",
|
||||||
e164 = 141255501234,
|
e164 = 141255501234,
|
||||||
blocked = true,
|
blocked = true,
|
||||||
hidden = true,
|
visibility = Contact.Visibility.VISIBLE,
|
||||||
registered = Contact.Registered.REGISTERED,
|
registered = Contact.Registered(),
|
||||||
unregisteredTimestamp = 0L,
|
|
||||||
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
||||||
profileSharing = true,
|
profileSharing = true,
|
||||||
profileGivenName = "Alexa",
|
profileGivenName = "Alexa",
|
||||||
@@ -408,9 +407,8 @@ class ImportExportTest {
|
|||||||
username = null,
|
username = null,
|
||||||
e164 = 141255501235,
|
e164 = 141255501235,
|
||||||
blocked = true,
|
blocked = true,
|
||||||
hidden = true,
|
visibility = Contact.Visibility.HIDDEN,
|
||||||
registered = Contact.Registered.NOT_REGISTERED,
|
notRegistered = Contact.NotRegistered(unregisteredTimestamp = 1234568927398L),
|
||||||
unregisteredTimestamp = 1234568927398L,
|
|
||||||
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
||||||
profileSharing = false,
|
profileSharing = false,
|
||||||
profileGivenName = "Peter",
|
profileGivenName = "Peter",
|
||||||
@@ -470,9 +468,8 @@ class ImportExportTest {
|
|||||||
username = "cool.01",
|
username = "cool.01",
|
||||||
e164 = 141255501234,
|
e164 = 141255501234,
|
||||||
blocked = true,
|
blocked = true,
|
||||||
hidden = true,
|
visibility = Contact.Visibility.HIDDEN,
|
||||||
registered = Contact.Registered.REGISTERED,
|
registered = Contact.Registered(),
|
||||||
unregisteredTimestamp = 0L,
|
|
||||||
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
||||||
profileSharing = true,
|
profileSharing = true,
|
||||||
profileGivenName = "Alexa",
|
profileGivenName = "Alexa",
|
||||||
@@ -488,9 +485,8 @@ class ImportExportTest {
|
|||||||
username = null,
|
username = null,
|
||||||
e164 = 141255501235,
|
e164 = 141255501235,
|
||||||
blocked = true,
|
blocked = true,
|
||||||
hidden = true,
|
visibility = Contact.Visibility.HIDDEN,
|
||||||
registered = Contact.Registered.REGISTERED,
|
registered = Contact.Registered(),
|
||||||
unregisteredTimestamp = 0L,
|
|
||||||
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
||||||
profileSharing = true,
|
profileSharing = true,
|
||||||
profileGivenName = "Peter",
|
profileGivenName = "Peter",
|
||||||
@@ -506,9 +502,8 @@ class ImportExportTest {
|
|||||||
username = null,
|
username = null,
|
||||||
e164 = 141255501236,
|
e164 = 141255501236,
|
||||||
blocked = true,
|
blocked = true,
|
||||||
hidden = true,
|
visibility = Contact.Visibility.HIDDEN,
|
||||||
registered = Contact.Registered.REGISTERED,
|
registered = Contact.Registered(),
|
||||||
unregisteredTimestamp = 0L,
|
|
||||||
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
||||||
profileSharing = true,
|
profileSharing = true,
|
||||||
profileGivenName = "Father",
|
profileGivenName = "Father",
|
||||||
@@ -518,13 +513,14 @@ class ImportExportTest {
|
|||||||
),
|
),
|
||||||
Recipient(
|
Recipient(
|
||||||
id = 6,
|
id = 6,
|
||||||
distributionList = DistributionList(
|
distributionList = DistributionListItem(
|
||||||
name = "Kim Family",
|
|
||||||
distributionId = DistributionId.create().asUuid().toByteArray().toByteString(),
|
distributionId = DistributionId.create().asUuid().toByteArray().toByteString(),
|
||||||
allowReplies = true,
|
distributionList = DistributionList(
|
||||||
deletionTimestamp = 0L,
|
name = "Kim Family",
|
||||||
privacyMode = DistributionList.PrivacyMode.ONLY_WITH,
|
allowReplies = true,
|
||||||
memberRecipientIds = listOf(3, 4, 5)
|
privacyMode = DistributionList.PrivacyMode.ONLY_WITH,
|
||||||
|
memberRecipientIds = listOf(3, 4, 5)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -540,9 +536,8 @@ class ImportExportTest {
|
|||||||
username = "cool.01",
|
username = "cool.01",
|
||||||
e164 = 141255501234,
|
e164 = 141255501234,
|
||||||
blocked = true,
|
blocked = true,
|
||||||
hidden = true,
|
visibility = Contact.Visibility.HIDDEN,
|
||||||
registered = Contact.Registered.REGISTERED,
|
registered = Contact.Registered(),
|
||||||
unregisteredTimestamp = 0L,
|
|
||||||
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
||||||
profileSharing = true,
|
profileSharing = true,
|
||||||
profileGivenName = "Alexa",
|
profileGivenName = "Alexa",
|
||||||
@@ -555,13 +550,9 @@ class ImportExportTest {
|
|||||||
alexa,
|
alexa,
|
||||||
Recipient(
|
Recipient(
|
||||||
id = 6,
|
id = 6,
|
||||||
distributionList = DistributionList(
|
distributionList = DistributionListItem(
|
||||||
name = "Deleted list",
|
|
||||||
distributionId = DistributionId.create().asUuid().toByteArray().toByteString(),
|
distributionId = DistributionId.create().asUuid().toByteArray().toByteString(),
|
||||||
allowReplies = true,
|
deletionTimestamp = 12345L
|
||||||
deletionTimestamp = 12345L,
|
|
||||||
privacyMode = DistributionList.PrivacyMode.ONLY_WITH,
|
|
||||||
memberRecipientIds = listOf(3)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -587,9 +578,8 @@ class ImportExportTest {
|
|||||||
username = "cool.01",
|
username = "cool.01",
|
||||||
e164 = 141255501234,
|
e164 = 141255501234,
|
||||||
blocked = false,
|
blocked = false,
|
||||||
hidden = false,
|
visibility = Contact.Visibility.VISIBLE,
|
||||||
registered = Contact.Registered.REGISTERED,
|
registered = Contact.Registered(),
|
||||||
unregisteredTimestamp = 0L,
|
|
||||||
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
||||||
profileSharing = true,
|
profileSharing = true,
|
||||||
profileGivenName = "Alexa",
|
profileGivenName = "Alexa",
|
||||||
@@ -614,8 +604,7 @@ class ImportExportTest {
|
|||||||
expirationTimerMs = 1.days.inWholeMilliseconds,
|
expirationTimerMs = 1.days.inWholeMilliseconds,
|
||||||
muteUntilMs = System.currentTimeMillis(),
|
muteUntilMs = System.currentTimeMillis(),
|
||||||
markedUnread = true,
|
markedUnread = true,
|
||||||
dontNotifyForMentionsIfMuted = true,
|
dontNotifyForMentionsIfMuted = true
|
||||||
wallpaper = null
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -689,9 +678,8 @@ class ImportExportTest {
|
|||||||
username = "cool.01",
|
username = "cool.01",
|
||||||
e164 = 141255501234,
|
e164 = 141255501234,
|
||||||
blocked = false,
|
blocked = false,
|
||||||
hidden = false,
|
visibility = Contact.Visibility.VISIBLE,
|
||||||
registered = Contact.Registered.REGISTERED,
|
registered = Contact.Registered(),
|
||||||
unregisteredTimestamp = 0L,
|
|
||||||
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
profileKey = TestRecipientUtils.generateProfileKey().toByteString(),
|
||||||
profileSharing = true,
|
profileSharing = true,
|
||||||
profileGivenName = "Alexa",
|
profileGivenName = "Alexa",
|
||||||
@@ -716,8 +704,7 @@ class ImportExportTest {
|
|||||||
expirationTimerMs = 1.days.inWholeMilliseconds,
|
expirationTimerMs = 1.days.inWholeMilliseconds,
|
||||||
muteUntilMs = System.currentTimeMillis(),
|
muteUntilMs = System.currentTimeMillis(),
|
||||||
markedUnread = true,
|
markedUnread = true,
|
||||||
dontNotifyForMentionsIfMuted = true,
|
dontNotifyForMentionsIfMuted = true
|
||||||
wallpaper = null
|
|
||||||
),
|
),
|
||||||
*individualCalls.toArray()
|
*individualCalls.toArray()
|
||||||
)
|
)
|
||||||
@@ -1361,8 +1348,7 @@ class ImportExportTest {
|
|||||||
expirationTimerMs = 0,
|
expirationTimerMs = 0,
|
||||||
muteUntilMs = 0,
|
muteUntilMs = 0,
|
||||||
markedUnread = false,
|
markedUnread = false,
|
||||||
dontNotifyForMentionsIfMuted = false,
|
dontNotifyForMentionsIfMuted = false
|
||||||
wallpaper = null
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ fun CallTable.restoreCallLogFromBackup(call: AdHocCall, backupState: BackupState
|
|||||||
CallTable.TYPE to CallTable.Type.serialize(CallTable.Type.AD_HOC_CALL),
|
CallTable.TYPE to CallTable.Type.serialize(CallTable.Type.AD_HOC_CALL),
|
||||||
CallTable.DIRECTION to CallTable.Direction.serialize(CallTable.Direction.OUTGOING),
|
CallTable.DIRECTION to CallTable.Direction.serialize(CallTable.Direction.OUTGOING),
|
||||||
CallTable.EVENT to CallTable.Event.serialize(event),
|
CallTable.EVENT to CallTable.Event.serialize(event),
|
||||||
CallTable.TIMESTAMP to call.startedCallTimestamp
|
CallTable.TIMESTAMP to call.callTimestamp
|
||||||
)
|
)
|
||||||
|
|
||||||
writableDatabase.insert(CallTable.TABLE_NAME, SQLiteDatabase.CONFLICT_IGNORE, values)
|
writableDatabase.insert(CallTable.TABLE_NAME, SQLiteDatabase.CONFLICT_IGNORE, values)
|
||||||
@@ -64,7 +64,7 @@ class CallLogIterator(private val cursor: Cursor) : Iterator<AdHocCall?>, Closea
|
|||||||
callId = callId,
|
callId = callId,
|
||||||
recipientId = cursor.requireLong(CallTable.PEER),
|
recipientId = cursor.requireLong(CallTable.PEER),
|
||||||
state = AdHocCall.State.GENERIC,
|
state = AdHocCall.State.GENERIC,
|
||||||
startedCallTimestamp = cursor.requireLong(CallTable.TIMESTAMP)
|
callTimestamp = cursor.requireLong(CallTable.TIMESTAMP)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -538,6 +538,7 @@ class ChatItemImportInserter(
|
|||||||
SimpleChatUpdate.Type.BAD_DECRYPT -> MessageTypes.BAD_DECRYPT_TYPE or typeWithoutBase
|
SimpleChatUpdate.Type.BAD_DECRYPT -> MessageTypes.BAD_DECRYPT_TYPE or typeWithoutBase
|
||||||
SimpleChatUpdate.Type.PAYMENTS_ACTIVATED -> MessageTypes.SPECIAL_TYPE_PAYMENTS_ACTIVATED or typeWithoutBase
|
SimpleChatUpdate.Type.PAYMENTS_ACTIVATED -> MessageTypes.SPECIAL_TYPE_PAYMENTS_ACTIVATED or typeWithoutBase
|
||||||
SimpleChatUpdate.Type.PAYMENT_ACTIVATION_REQUEST -> MessageTypes.SPECIAL_TYPE_PAYMENTS_ACTIVATE_REQUEST or typeWithoutBase
|
SimpleChatUpdate.Type.PAYMENT_ACTIVATION_REQUEST -> MessageTypes.SPECIAL_TYPE_PAYMENTS_ACTIVATE_REQUEST or typeWithoutBase
|
||||||
|
SimpleChatUpdate.Type.UNSUPPORTED_PROTOCOL_MESSAGE -> MessageTypes.UNSUPPORTED_MESSAGE_TYPE or typeWithoutBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateMessage.expirationTimerChange != null -> {
|
updateMessage.expirationTimerChange != null -> {
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import org.signal.core.util.requireNonNullString
|
|||||||
import org.signal.core.util.requireObject
|
import org.signal.core.util.requireObject
|
||||||
import org.signal.core.util.select
|
import org.signal.core.util.select
|
||||||
import org.thoughtcrime.securesms.backup.v2.BackupState
|
import org.thoughtcrime.securesms.backup.v2.BackupState
|
||||||
|
import org.thoughtcrime.securesms.backup.v2.proto.DistributionList
|
||||||
|
import org.thoughtcrime.securesms.backup.v2.proto.DistributionListItem
|
||||||
import org.thoughtcrime.securesms.database.DistributionListTables
|
import org.thoughtcrime.securesms.database.DistributionListTables
|
||||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||||
import org.thoughtcrime.securesms.database.model.DistributionListId
|
import org.thoughtcrime.securesms.database.model.DistributionListId
|
||||||
@@ -60,19 +62,28 @@ fun DistributionListTables.getAllForBackup(): List<BackupRecipient> {
|
|||||||
.map { recipient ->
|
.map { recipient ->
|
||||||
BackupRecipient(
|
BackupRecipient(
|
||||||
id = recipient.id.toLong(),
|
id = recipient.id.toLong(),
|
||||||
distributionList = BackupDistributionList(
|
distributionList = if (recipient.record.deletedAtTimestamp != 0L) {
|
||||||
name = recipient.record.name,
|
DistributionListItem(
|
||||||
distributionId = recipient.record.distributionId.asUuid().toByteArray().toByteString(),
|
distributionId = recipient.record.distributionId.asUuid().toByteArray().toByteString(),
|
||||||
allowReplies = recipient.record.allowsReplies,
|
deletionTimestamp = recipient.record.deletedAtTimestamp
|
||||||
deletionTimestamp = recipient.record.deletedAtTimestamp,
|
)
|
||||||
privacyMode = recipient.record.privacyMode.toBackupPrivacyMode(),
|
} else {
|
||||||
memberRecipientIds = recipient.record.members.map { it.toLong() }
|
DistributionListItem(
|
||||||
)
|
distributionId = recipient.record.distributionId.asUuid().toByteArray().toByteString(),
|
||||||
|
distributionList = DistributionList(
|
||||||
|
name = recipient.record.name,
|
||||||
|
allowReplies = recipient.record.allowsReplies,
|
||||||
|
privacyMode = recipient.record.privacyMode.toBackupPrivacyMode(),
|
||||||
|
memberRecipientIds = recipient.record.members.map { it.toLong() }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun DistributionListTables.restoreFromBackup(dlist: BackupDistributionList, backupState: BackupState): RecipientId {
|
fun DistributionListTables.restoreFromBackup(dlistItem: DistributionListItem, backupState: BackupState): RecipientId? {
|
||||||
|
val dlist = dlistItem.distributionList ?: return null
|
||||||
val members: List<RecipientId> = dlist.memberRecipientIds
|
val members: List<RecipientId> = dlist.memberRecipientIds
|
||||||
.mapNotNull { backupState.backupToLocalRecipientId[it] }
|
.mapNotNull { backupState.backupToLocalRecipientId[it] }
|
||||||
|
|
||||||
@@ -83,9 +94,9 @@ fun DistributionListTables.restoreFromBackup(dlist: BackupDistributionList, back
|
|||||||
val dlistId = this.createList(
|
val dlistId = this.createList(
|
||||||
name = dlist.name,
|
name = dlist.name,
|
||||||
members = members,
|
members = members,
|
||||||
distributionId = DistributionId.from(UuidUtil.fromByteString(dlist.distributionId)),
|
distributionId = DistributionId.from(UuidUtil.fromByteString(dlistItem.distributionId)),
|
||||||
allowsReplies = dlist.allowReplies,
|
allowsReplies = dlist.allowReplies,
|
||||||
deletionTimestamp = dlist.deletionTimestamp,
|
deletionTimestamp = dlistItem.deletionTimestamp ?: 0,
|
||||||
storageId = null,
|
storageId = null,
|
||||||
privacyMode = dlist.privacyMode.toLocalPrivacyMode()
|
privacyMode = dlist.privacyMode.toLocalPrivacyMode()
|
||||||
)!!
|
)!!
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.backup.v2.database
|
|||||||
|
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
|
import androidx.core.content.contentValuesOf
|
||||||
import okio.ByteString.Companion.toByteString
|
import okio.ByteString.Companion.toByteString
|
||||||
import org.signal.core.util.Base64
|
import org.signal.core.util.Base64
|
||||||
import org.signal.core.util.SqlUtil
|
import org.signal.core.util.SqlUtil
|
||||||
@@ -175,23 +176,30 @@ fun RecipientTable.restoreContactFromBackup(contact: Contact): RecipientId {
|
|||||||
)
|
)
|
||||||
|
|
||||||
val profileKey = contact.profileKey?.toByteArray()
|
val profileKey = contact.profileKey?.toByteArray()
|
||||||
|
val values = contentValuesOf(
|
||||||
|
RecipientTable.BLOCKED to contact.blocked,
|
||||||
|
RecipientTable.HIDDEN to (contact.visibility == Contact.Visibility.HIDDEN),
|
||||||
|
RecipientTable.TYPE to RecipientTable.RecipientType.INDIVIDUAL.id,
|
||||||
|
RecipientTable.PROFILE_FAMILY_NAME to contact.profileFamilyName.nullIfBlank(),
|
||||||
|
RecipientTable.PROFILE_GIVEN_NAME to contact.profileGivenName.nullIfBlank(),
|
||||||
|
RecipientTable.PROFILE_JOINED_NAME to ProfileName.fromParts(contact.profileGivenName.nullIfBlank(), contact.profileFamilyName.nullIfBlank()).toString().nullIfBlank(),
|
||||||
|
RecipientTable.PROFILE_KEY to if (profileKey == null) null else Base64.encodeWithPadding(profileKey),
|
||||||
|
RecipientTable.PROFILE_SHARING to contact.profileSharing.toInt(),
|
||||||
|
RecipientTable.USERNAME to contact.username,
|
||||||
|
RecipientTable.EXTRAS to contact.toLocalExtras().encode()
|
||||||
|
)
|
||||||
|
|
||||||
|
if (contact.registered != null) {
|
||||||
|
values.put(RecipientTable.UNREGISTERED_TIMESTAMP, 0L)
|
||||||
|
values.put(RecipientTable.REGISTERED, RecipientTable.RegisteredState.REGISTERED.id)
|
||||||
|
} else if (contact.notRegistered != null) {
|
||||||
|
values.put(RecipientTable.UNREGISTERED_TIMESTAMP, contact.notRegistered.unregisteredTimestamp)
|
||||||
|
values.put(RecipientTable.REGISTERED, RecipientTable.RegisteredState.NOT_REGISTERED.id)
|
||||||
|
}
|
||||||
|
|
||||||
writableDatabase
|
writableDatabase
|
||||||
.update(RecipientTable.TABLE_NAME)
|
.update(RecipientTable.TABLE_NAME)
|
||||||
.values(
|
.values(values)
|
||||||
RecipientTable.BLOCKED to contact.blocked,
|
|
||||||
RecipientTable.HIDDEN to contact.hidden,
|
|
||||||
RecipientTable.TYPE to RecipientTable.RecipientType.INDIVIDUAL.id,
|
|
||||||
RecipientTable.PROFILE_FAMILY_NAME to contact.profileFamilyName.nullIfBlank(),
|
|
||||||
RecipientTable.PROFILE_GIVEN_NAME to contact.profileGivenName.nullIfBlank(),
|
|
||||||
RecipientTable.PROFILE_JOINED_NAME to ProfileName.fromParts(contact.profileGivenName.nullIfBlank(), contact.profileFamilyName.nullIfBlank()).toString().nullIfBlank(),
|
|
||||||
RecipientTable.PROFILE_KEY to if (profileKey == null) null else Base64.encodeWithPadding(profileKey),
|
|
||||||
RecipientTable.PROFILE_SHARING to contact.profileSharing.toInt(),
|
|
||||||
RecipientTable.REGISTERED to contact.registered.toLocalRegisteredState().id,
|
|
||||||
RecipientTable.USERNAME to contact.username,
|
|
||||||
RecipientTable.UNREGISTERED_TIMESTAMP to contact.unregisteredTimestamp,
|
|
||||||
RecipientTable.EXTRAS to contact.toLocalExtras().encode()
|
|
||||||
)
|
|
||||||
.where("${RecipientTable.ID} = ?", id)
|
.where("${RecipientTable.ID} = ?", id)
|
||||||
.run()
|
.run()
|
||||||
|
|
||||||
@@ -418,23 +426,28 @@ class BackupContactIterator(private val cursor: Cursor, private val selfId: Long
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val contactBuilder = Contact.Builder()
|
||||||
|
.aci(aci?.rawUuid?.toByteArray()?.toByteString())
|
||||||
|
.pni(pni?.rawUuid?.toByteArray()?.toByteString())
|
||||||
|
.username(cursor.requireString(RecipientTable.USERNAME))
|
||||||
|
.e164(cursor.requireString(RecipientTable.E164)?.e164ToLong())
|
||||||
|
.blocked(cursor.requireBoolean(RecipientTable.BLOCKED))
|
||||||
|
.visibility(if (cursor.requireBoolean(RecipientTable.HIDDEN)) Contact.Visibility.HIDDEN else Contact.Visibility.VISIBLE)
|
||||||
|
.profileKey(if (profileKey != null) Base64.decode(profileKey).toByteString() else null)
|
||||||
|
.profileSharing(cursor.requireBoolean(RecipientTable.PROFILE_SHARING))
|
||||||
|
.profileGivenName(cursor.requireString(RecipientTable.PROFILE_GIVEN_NAME).nullIfBlank())
|
||||||
|
.profileFamilyName(cursor.requireString(RecipientTable.PROFILE_FAMILY_NAME).nullIfBlank())
|
||||||
|
.hideStory(extras?.hideStory() ?: false)
|
||||||
|
|
||||||
|
if (registeredState == RecipientTable.RegisteredState.REGISTERED) {
|
||||||
|
contactBuilder.registered = Contact.Registered()
|
||||||
|
} else {
|
||||||
|
contactBuilder.notRegistered = Contact.NotRegistered(unregisteredTimestamp = cursor.requireLong(RecipientTable.UNREGISTERED_TIMESTAMP))
|
||||||
|
}
|
||||||
|
|
||||||
return BackupRecipient(
|
return BackupRecipient(
|
||||||
id = id,
|
id = id,
|
||||||
contact = Contact(
|
contact = contactBuilder.build()
|
||||||
aci = aci?.rawUuid?.toByteArray()?.toByteString(),
|
|
||||||
pni = pni?.rawUuid?.toByteArray()?.toByteString(),
|
|
||||||
username = cursor.requireString(RecipientTable.USERNAME),
|
|
||||||
e164 = cursor.requireString(RecipientTable.E164)?.e164ToLong(),
|
|
||||||
blocked = cursor.requireBoolean(RecipientTable.BLOCKED),
|
|
||||||
hidden = cursor.requireBoolean(RecipientTable.HIDDEN),
|
|
||||||
registered = registeredState.toContactRegisteredState(),
|
|
||||||
unregisteredTimestamp = cursor.requireLong(RecipientTable.UNREGISTERED_TIMESTAMP),
|
|
||||||
profileKey = if (profileKey != null) Base64.decode(profileKey).toByteString() else null,
|
|
||||||
profileSharing = cursor.requireBoolean(RecipientTable.PROFILE_SHARING),
|
|
||||||
profileGivenName = cursor.requireString(RecipientTable.PROFILE_GIVEN_NAME).nullIfBlank(),
|
|
||||||
profileFamilyName = cursor.requireString(RecipientTable.PROFILE_FAMILY_NAME).nullIfBlank(),
|
|
||||||
hideStory = extras?.hideStory() ?: false
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,22 +502,6 @@ private fun String.e164ToLong(): Long? {
|
|||||||
return fixed.toLongOrNull()
|
return fixed.toLongOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun RecipientTable.RegisteredState.toContactRegisteredState(): Contact.Registered {
|
|
||||||
return when (this) {
|
|
||||||
RecipientTable.RegisteredState.REGISTERED -> Contact.Registered.REGISTERED
|
|
||||||
RecipientTable.RegisteredState.NOT_REGISTERED -> Contact.Registered.NOT_REGISTERED
|
|
||||||
RecipientTable.RegisteredState.UNKNOWN -> Contact.Registered.UNKNOWN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Contact.Registered.toLocalRegisteredState(): RecipientTable.RegisteredState {
|
|
||||||
return when (this) {
|
|
||||||
Contact.Registered.REGISTERED -> RecipientTable.RegisteredState.REGISTERED
|
|
||||||
Contact.Registered.NOT_REGISTERED -> RecipientTable.RegisteredState.NOT_REGISTERED
|
|
||||||
Contact.Registered.UNKNOWN -> RecipientTable.RegisteredState.UNKNOWN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun GroupTable.ShowAsStoryState.toGroupStorySendMode(): Group.StorySendMode {
|
private fun GroupTable.ShowAsStoryState.toGroupStorySendMode(): Group.StorySendMode {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
GroupTable.ShowAsStoryState.ALWAYS -> Group.StorySendMode.ENABLED
|
GroupTable.ShowAsStoryState.ALWAYS -> Group.StorySendMode.ENABLED
|
||||||
|
|||||||
@@ -49,10 +49,7 @@ object AccountDataProcessor {
|
|||||||
givenName = self.profileName.givenName,
|
givenName = self.profileName.givenName,
|
||||||
familyName = self.profileName.familyName,
|
familyName = self.profileName.familyName,
|
||||||
avatarUrlPath = self.profileAvatar ?: "",
|
avatarUrlPath = self.profileAvatar ?: "",
|
||||||
subscriptionManuallyCancelled = InAppPaymentsRepository.isUserManuallyCancelled(InAppPaymentSubscriberRecord.Type.DONATION),
|
|
||||||
username = self.username.getOrNull(),
|
username = self.username.getOrNull(),
|
||||||
subscriberId = subscriber?.subscriberId?.bytes?.toByteString() ?: defaultAccountRecord.subscriberId,
|
|
||||||
subscriberCurrencyCode = subscriber?.currency?.currencyCode ?: defaultAccountRecord.subscriberCurrencyCode,
|
|
||||||
accountSettings = AccountData.AccountSettings(
|
accountSettings = AccountData.AccountSettings(
|
||||||
storyViewReceiptsEnabled = SignalStore.storyValues().viewedReceiptsEnabled,
|
storyViewReceiptsEnabled = SignalStore.storyValues().viewedReceiptsEnabled,
|
||||||
typingIndicators = TextSecurePreferences.isTypingIndicatorsEnabled(context),
|
typingIndicators = TextSecurePreferences.isTypingIndicatorsEnabled(context),
|
||||||
@@ -71,6 +68,11 @@ object AccountDataProcessor {
|
|||||||
displayBadgesOnProfile = SignalStore.donationsValues().getDisplayBadgesOnProfile(),
|
displayBadgesOnProfile = SignalStore.donationsValues().getDisplayBadgesOnProfile(),
|
||||||
hasSeenGroupStoryEducationSheet = SignalStore.storyValues().userHasSeenGroupStoryEducationSheet,
|
hasSeenGroupStoryEducationSheet = SignalStore.storyValues().userHasSeenGroupStoryEducationSheet,
|
||||||
hasCompletedUsernameOnboarding = SignalStore.uiHints().hasCompletedUsernameOnboarding()
|
hasCompletedUsernameOnboarding = SignalStore.uiHints().hasCompletedUsernameOnboarding()
|
||||||
|
),
|
||||||
|
donationSubscriberData = AccountData.SubscriberData(
|
||||||
|
subscriberId = subscriber?.subscriberId?.bytes?.toByteString() ?: defaultAccountRecord.subscriberId,
|
||||||
|
currencyCode = subscriber?.currency?.currencyCode ?: defaultAccountRecord.subscriberCurrencyCode,
|
||||||
|
manuallyCancelled = InAppPaymentsRepository.isUserManuallyCancelled(InAppPaymentSubscriberRecord.Type.DONATION)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -103,23 +105,25 @@ object AccountDataProcessor {
|
|||||||
SignalStore.storyValues().userHasSeenGroupStoryEducationSheet = settings.hasSeenGroupStoryEducationSheet
|
SignalStore.storyValues().userHasSeenGroupStoryEducationSheet = settings.hasSeenGroupStoryEducationSheet
|
||||||
SignalStore.storyValues().viewedReceiptsEnabled = settings.storyViewReceiptsEnabled ?: settings.readReceipts
|
SignalStore.storyValues().viewedReceiptsEnabled = settings.storyViewReceiptsEnabled ?: settings.readReceipts
|
||||||
|
|
||||||
if (accountData.subscriberId.size > 0) {
|
if (accountData.donationSubscriberData != null) {
|
||||||
val remoteSubscriberId = SubscriberId.fromBytes(accountData.subscriberId.toByteArray())
|
if (accountData.donationSubscriberData.subscriberId.size > 0) {
|
||||||
val localSubscriber = InAppPaymentsRepository.getSubscriber(InAppPaymentSubscriberRecord.Type.DONATION)
|
val remoteSubscriberId = SubscriberId.fromBytes(accountData.donationSubscriberData.subscriberId.toByteArray())
|
||||||
|
val localSubscriber = InAppPaymentsRepository.getSubscriber(InAppPaymentSubscriberRecord.Type.DONATION)
|
||||||
|
|
||||||
val subscriber = InAppPaymentSubscriberRecord(
|
val subscriber = InAppPaymentSubscriberRecord(
|
||||||
remoteSubscriberId,
|
remoteSubscriberId,
|
||||||
Currency.getInstance(accountData.subscriberCurrencyCode),
|
Currency.getInstance(accountData.donationSubscriberData.currencyCode),
|
||||||
InAppPaymentSubscriberRecord.Type.DONATION,
|
InAppPaymentSubscriberRecord.Type.DONATION,
|
||||||
localSubscriber?.requiresCancel ?: false,
|
localSubscriber?.requiresCancel ?: accountData.donationSubscriberData.manuallyCancelled,
|
||||||
InAppPaymentsRepository.getLatestPaymentMethodType(InAppPaymentSubscriberRecord.Type.DONATION)
|
InAppPaymentsRepository.getLatestPaymentMethodType(InAppPaymentSubscriberRecord.Type.DONATION)
|
||||||
)
|
)
|
||||||
|
|
||||||
InAppPaymentsRepository.setSubscriber(subscriber)
|
InAppPaymentsRepository.setSubscriber(subscriber)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accountData.subscriptionManuallyCancelled) {
|
if (accountData.donationSubscriberData.manuallyCancelled) {
|
||||||
SignalStore.donationsValues().updateLocalStateForManualCancellation(InAppPaymentSubscriberRecord.Type.DONATION)
|
SignalStore.donationsValues().updateLocalStateForManualCancellation(InAppPaymentSubscriberRecord.Type.DONATION)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accountData.avatarUrlPath.isNotEmpty()) {
|
if (accountData.avatarUrlPath.isNotEmpty()) {
|
||||||
|
|||||||
@@ -74,6 +74,13 @@ message AccountData {
|
|||||||
bool hasSeenGroupStoryEducationSheet = 15;
|
bool hasSeenGroupStoryEducationSheet = 15;
|
||||||
bool hasCompletedUsernameOnboarding = 16;
|
bool hasCompletedUsernameOnboarding = 16;
|
||||||
PhoneNumberSharingMode phoneNumberSharingMode = 17;
|
PhoneNumberSharingMode phoneNumberSharingMode = 17;
|
||||||
|
ChatStyle defaultChatStyle = 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SubscriberData {
|
||||||
|
bytes subscriberId = 1;
|
||||||
|
string currencyCode = 2;
|
||||||
|
bool manuallyCancelled = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes profileKey = 1;
|
bytes profileKey = 1;
|
||||||
@@ -82,10 +89,9 @@ message AccountData {
|
|||||||
string givenName = 4;
|
string givenName = 4;
|
||||||
string familyName = 5;
|
string familyName = 5;
|
||||||
string avatarUrlPath = 6;
|
string avatarUrlPath = 6;
|
||||||
bytes subscriberId = 7;
|
SubscriberData donationSubscriberData = 7;
|
||||||
string subscriberCurrencyCode = 8;
|
SubscriberData backupsSubscriberData = 8;
|
||||||
bool subscriptionManuallyCancelled = 9;
|
AccountSettings accountSettings = 9;
|
||||||
AccountSettings accountSettings = 10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Recipient {
|
message Recipient {
|
||||||
@@ -93,7 +99,7 @@ message Recipient {
|
|||||||
oneof destination {
|
oneof destination {
|
||||||
Contact contact = 2;
|
Contact contact = 2;
|
||||||
Group group = 3;
|
Group group = 3;
|
||||||
DistributionList distributionList = 4;
|
DistributionListItem distributionList = 4;
|
||||||
Self self = 5;
|
Self self = 5;
|
||||||
ReleaseNotes releaseNotes = 6;
|
ReleaseNotes releaseNotes = 6;
|
||||||
CallLink callLink = 7;
|
CallLink callLink = 7;
|
||||||
@@ -101,10 +107,15 @@ message Recipient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message Contact {
|
message Contact {
|
||||||
enum Registered {
|
message Registered { }
|
||||||
UNKNOWN = 0;
|
message NotRegistered {
|
||||||
REGISTERED = 1;
|
uint64 unregisteredTimestamp = 1;
|
||||||
NOT_REGISTERED = 2;
|
}
|
||||||
|
|
||||||
|
enum Visibility {
|
||||||
|
VISIBLE = 0;
|
||||||
|
HIDDEN = 1;
|
||||||
|
HIDDEN_MESSAGE_REQUEST = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional bytes aci = 1; // should be 16 bytes
|
optional bytes aci = 1; // should be 16 bytes
|
||||||
@@ -112,9 +123,13 @@ message Contact {
|
|||||||
optional string username = 3;
|
optional string username = 3;
|
||||||
optional uint64 e164 = 4;
|
optional uint64 e164 = 4;
|
||||||
bool blocked = 5;
|
bool blocked = 5;
|
||||||
bool hidden = 6;
|
Visibility visibility = 6;
|
||||||
Registered registered = 7;
|
|
||||||
uint64 unregisteredTimestamp = 8;
|
oneof registration {
|
||||||
|
Registered registered = 7;
|
||||||
|
NotRegistered notRegistered = 8;
|
||||||
|
}
|
||||||
|
|
||||||
optional bytes profileKey = 9;
|
optional bytes profileKey = 9;
|
||||||
bool profileSharing = 10;
|
bool profileSharing = 10;
|
||||||
optional string profileGivenName = 11;
|
optional string profileGivenName = 11;
|
||||||
@@ -225,7 +240,7 @@ message Chat {
|
|||||||
uint64 muteUntilMs = 6;
|
uint64 muteUntilMs = 6;
|
||||||
bool markedUnread = 7;
|
bool markedUnread = 7;
|
||||||
bool dontNotifyForMentionsIfMuted = 8;
|
bool dontNotifyForMentionsIfMuted = 8;
|
||||||
FilePointer wallpaper = 9;
|
ChatStyle style = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -260,10 +275,16 @@ message AdHocCall {
|
|||||||
// Refers to a `CallLink` recipient.
|
// Refers to a `CallLink` recipient.
|
||||||
uint64 recipientId = 2;
|
uint64 recipientId = 2;
|
||||||
State state = 3;
|
State state = 3;
|
||||||
optional bytes startedCallAci = 4;
|
uint64 callTimestamp = 4;
|
||||||
uint64 startedCallTimestamp = 5;
|
}
|
||||||
// The time the call ended. 0 indicates an unknown time.
|
|
||||||
uint64 endedCallTimestamp = 6;
|
message DistributionListItem {
|
||||||
|
bytes distributionId = 1; // distribution list ids are uuids
|
||||||
|
|
||||||
|
oneof item {
|
||||||
|
uint64 deletionTimestamp = 2;
|
||||||
|
DistributionList distributionList = 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message DistributionList {
|
message DistributionList {
|
||||||
@@ -275,11 +296,9 @@ message DistributionList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string name = 1;
|
string name = 1;
|
||||||
bytes distributionId = 2; // distribution list ids are uuids
|
bool allowReplies = 2;
|
||||||
bool allowReplies = 3;
|
PrivacyMode privacyMode = 3;
|
||||||
uint64 deletionTimestamp = 4;
|
repeated uint64 memberRecipientIds = 4; // generated recipient id
|
||||||
PrivacyMode privacyMode = 5;
|
|
||||||
repeated uint64 memberRecipientIds = 6; // generated recipient id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Identity {
|
message Identity {
|
||||||
@@ -370,9 +389,6 @@ message ContactMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message PaymentNotification {
|
message PaymentNotification {
|
||||||
|
|
||||||
// Transaction details should largely be best effort. If fields are missing or
|
|
||||||
// invalid, we should try to render things to the best of our abilities.
|
|
||||||
message TransactionDetails {
|
message TransactionDetails {
|
||||||
message MobileCoinTxoIdentification { // Used to map to payments on the ledger
|
message MobileCoinTxoIdentification { // Used to map to payments on the ledger
|
||||||
repeated bytes publicKey = 1; // for received transactions
|
repeated bytes publicKey = 1; // for received transactions
|
||||||
@@ -398,13 +414,13 @@ message PaymentNotification {
|
|||||||
|
|
||||||
// This identification is used to map the payment table to the ledger
|
// This identification is used to map the payment table to the ledger
|
||||||
// and is likely required otherwise we may have issues reconciling with
|
// and is likely required otherwise we may have issues reconciling with
|
||||||
// the ledger. If this
|
// the ledger
|
||||||
MobileCoinTxoIdentification mobileCoinIdentification = 2;
|
MobileCoinTxoIdentification mobileCoinIdentification = 2;
|
||||||
optional uint64 timestamp = 3;
|
optional uint64 timestamp = 3;
|
||||||
optional uint64 blockIndex = 4;
|
optional uint64 blockIndex = 4;
|
||||||
optional uint64 blockTimestamp = 5;
|
optional uint64 blockTimestamp = 5;
|
||||||
optional bytes transaction = 6; // mobile coin blobs, these are best effort, if they are invalid or fail to parse, treat as if missing, but do not block
|
optional bytes transaction = 6; // mobile coin blobs
|
||||||
optional bytes receipt = 7; // mobile coin blobs, these are best effort, if they are invalid or fail to parse, treat as if missing, but do not block
|
optional bytes receipt = 7; // mobile coin blobs
|
||||||
}
|
}
|
||||||
|
|
||||||
oneof payment {
|
oneof payment {
|
||||||
@@ -481,7 +497,7 @@ message ContactAttachment {
|
|||||||
repeated Phone number = 3;
|
repeated Phone number = 3;
|
||||||
repeated Email email = 4;
|
repeated Email email = 4;
|
||||||
repeated PostalAddress address = 5;
|
repeated PostalAddress address = 5;
|
||||||
optional string avatarUrlPath = 6;
|
optional FilePointer avatar = 6;
|
||||||
optional string organization = 7;
|
optional string organization = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -729,6 +745,7 @@ message SimpleChatUpdate {
|
|||||||
BAD_DECRYPT = 9;
|
BAD_DECRYPT = 9;
|
||||||
PAYMENTS_ACTIVATED = 10;
|
PAYMENTS_ACTIVATED = 10;
|
||||||
PAYMENT_ACTIVATION_REQUEST = 11;
|
PAYMENT_ACTIVATION_REQUEST = 11;
|
||||||
|
UNSUPPORTED_PROTOCOL_MESSAGE = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type type = 1;
|
Type type = 1;
|
||||||
@@ -1019,3 +1036,79 @@ message StickerPackSticker {
|
|||||||
string emoji = 1;
|
string emoji = 1;
|
||||||
uint32 id = 2;
|
uint32 id = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message ChatStyle {
|
||||||
|
message Gradient {
|
||||||
|
uint32 angle = 1; // degrees
|
||||||
|
repeated uint32 colors = 2;
|
||||||
|
repeated float positions = 3; // percent from 0 to 1
|
||||||
|
}
|
||||||
|
|
||||||
|
message AutomaticBubbleColor {
|
||||||
|
}
|
||||||
|
|
||||||
|
enum WallpaperPreset {
|
||||||
|
UNKNOWN_WALLPAPER_PRESET = 0;
|
||||||
|
SOLID_BLUSH = 1;
|
||||||
|
SOLID_COPPER = 2;
|
||||||
|
SOLID_DUST = 3;
|
||||||
|
SOLID_CELADON = 4;
|
||||||
|
SOLID_RAINFOREST = 5;
|
||||||
|
SOLID_PACIFIC = 6;
|
||||||
|
SOLID_FROST = 7;
|
||||||
|
SOLID_NAVY = 8;
|
||||||
|
SOLID_LILAC = 9;
|
||||||
|
SOLID_PINK = 10;
|
||||||
|
SOLID_EGGPLANT = 11;
|
||||||
|
SOLID_SILVER = 12;
|
||||||
|
GRADIENT_SUNSET = 13;
|
||||||
|
GRADIENT_NOIR = 14;
|
||||||
|
GRADIENT_HEATMAP = 15;
|
||||||
|
GRADIENT_AQUA = 16;
|
||||||
|
GRADIENT_IRIDESCENT = 17;
|
||||||
|
GRADIENT_MONSTERA = 18;
|
||||||
|
GRADIENT_BLISS = 19;
|
||||||
|
GRADIENT_SKY = 20;
|
||||||
|
GRADIENT_PEACH = 21;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum BubbleColorPreset {
|
||||||
|
UNKNOWN_BUBBLE_COLOR_PRESET = 0;
|
||||||
|
SOLID_ULTRAMARINE = 1;
|
||||||
|
SOLID_CRIMSON = 2;
|
||||||
|
SOLID_VERMILION = 3;
|
||||||
|
SOLID_BURLAP = 4;
|
||||||
|
SOLID_FOREST = 5;
|
||||||
|
SOLID_WINTERGREEN = 6;
|
||||||
|
SOLID_TEAL = 7;
|
||||||
|
SOLID_BLUE = 8;
|
||||||
|
SOLID_INDIGO = 9;
|
||||||
|
SOLID_VIOLET = 10;
|
||||||
|
SOLID_PLUM = 11;
|
||||||
|
SOLID_TAUPE = 12;
|
||||||
|
SOLID_STEEL = 13;
|
||||||
|
GRADIENT_EMBER = 14;
|
||||||
|
GRADIENT_MIDNIGHT = 15;
|
||||||
|
GRADIENT_INFRARED = 16;
|
||||||
|
GRADIENT_LAGOON = 17;
|
||||||
|
GRADIENT_FLUORESCENT = 18;
|
||||||
|
GRADIENT_BASIL = 19;
|
||||||
|
GRADIENT_SUBLIME = 20;
|
||||||
|
GRADIENT_SEA = 21;
|
||||||
|
GRADIENT_TANGERINE = 22;
|
||||||
|
}
|
||||||
|
|
||||||
|
oneof wallpaper {
|
||||||
|
WallpaperPreset wallpaperPreset = 1;
|
||||||
|
FilePointer wallpaperPhoto = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
oneof bubbleColor {
|
||||||
|
BubbleColorPreset bubbleColorPreset = 3;
|
||||||
|
Gradient bubbleGradient = 4;
|
||||||
|
uint32 bubbleSolidColor = 5;
|
||||||
|
// Bubble setting is automatically determined based on the wallpaper setting.
|
||||||
|
AutomaticBubbleColor autoBubbleColor = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user