mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-18 07:47:47 +01:00
Extract base archive classes into their own module.
This commit is contained in:
committed by
Cody Henthorne
parent
08491579dd
commit
8a887b65a1
@@ -92,6 +92,7 @@ wire {
|
||||
|
||||
protoPath {
|
||||
srcDir("${project.rootDir}/lib/libsignal-service/src/main/protowire")
|
||||
srcDir("${project.rootDir}/lib/archive/src/main/protowire")
|
||||
}
|
||||
// Handled by libsignal
|
||||
prune("signalservice.DecryptionErrorMessage")
|
||||
@@ -594,6 +595,7 @@ dependencies {
|
||||
ktlintRuleset(libs.ktlint.twitter.compose)
|
||||
coreLibraryDesugaring(libs.android.tools.desugar)
|
||||
|
||||
implementation(project(":lib:archive"))
|
||||
implementation(project(":lib:libsignal-service"))
|
||||
implementation(project(":lib:paging"))
|
||||
implementation(project(":core:util"))
|
||||
|
||||
@@ -13,6 +13,8 @@ import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.archive.stream.PlainTextBackupReader
|
||||
import org.signal.core.models.ServiceId
|
||||
import org.signal.core.util.Base64
|
||||
import org.signal.core.util.logging.Log
|
||||
@@ -20,8 +22,6 @@ import org.signal.core.util.readFully
|
||||
import org.signal.libsignal.messagebackup.ComparableBackup
|
||||
import org.signal.libsignal.messagebackup.MessageBackup
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.PlainTextBackupReader
|
||||
import org.thoughtcrime.securesms.database.KeyValueDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2
|
||||
|
||||
typealias ArchiveRecipient = org.thoughtcrime.securesms.backup.v2.proto.Recipient
|
||||
typealias ArchiveGroup = org.thoughtcrime.securesms.backup.v2.proto.Group
|
||||
typealias ArchiveCallLink = org.thoughtcrime.securesms.backup.v2.proto.CallLink
|
||||
typealias ArchiveRecipient = org.signal.archive.proto.Recipient
|
||||
typealias ArchiveGroup = org.signal.archive.proto.Group
|
||||
typealias ArchiveCallLink = org.signal.archive.proto.CallLink
|
||||
|
||||
@@ -18,6 +18,15 @@ import kotlinx.coroutines.withContext
|
||||
import okio.ByteString
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.signal.archive.proto.BackupDebugInfo
|
||||
import org.signal.archive.proto.BackupInfo
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.archive.stream.BackupExportWriter
|
||||
import org.signal.archive.stream.BackupImportReader
|
||||
import org.signal.archive.stream.EncryptedBackupReader
|
||||
import org.signal.archive.stream.EncryptedBackupWriter
|
||||
import org.signal.archive.stream.PlainTextBackupReader
|
||||
import org.signal.archive.stream.PlainTextBackupWriter
|
||||
import org.signal.core.models.AccountEntropyPool
|
||||
import org.signal.core.models.ServiceId.ACI
|
||||
import org.signal.core.models.ServiceId.PNI
|
||||
@@ -76,15 +85,6 @@ import org.thoughtcrime.securesms.backup.v2.processor.ChatItemArchiveProcessor
|
||||
import org.thoughtcrime.securesms.backup.v2.processor.NotificationProfileArchiveProcessor
|
||||
import org.thoughtcrime.securesms.backup.v2.processor.RecipientArchiveProcessor
|
||||
import org.thoughtcrime.securesms.backup.v2.processor.StickerArchiveProcessor
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.BackupDebugInfo
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.BackupInfo
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.BackupExportWriter
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.BackupImportReader
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.EncryptedBackupReader
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.EncryptedBackupWriter
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.PlainTextBackupReader
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.PlainTextBackupWriter
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.BackupAlert
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsType
|
||||
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
|
||||
@@ -1311,51 +1311,59 @@ object BackupRepository {
|
||||
val totalLength = frameReader.getStreamLength()
|
||||
var frameCount = 0
|
||||
for (frame in frameReader) {
|
||||
val frameAccount = frame.account
|
||||
val frameRecipient = frame.recipient
|
||||
val frameChat = frame.chat
|
||||
val frameAdHocCall = frame.adHocCall
|
||||
val frameStickerPack = frame.stickerPack
|
||||
val frameNotificationProfile = frame.notificationProfile
|
||||
val frameChatFolder = frame.chatFolder
|
||||
val frameChatItem = frame.chatItem
|
||||
when {
|
||||
frame.account != null -> {
|
||||
AccountDataArchiveProcessor.import(frame.account, selfId, importState)
|
||||
frameAccount != null -> {
|
||||
AccountDataArchiveProcessor.import(frameAccount, selfId, importState)
|
||||
eventTimer.emit("account")
|
||||
frameCount++
|
||||
}
|
||||
|
||||
frame.recipient != null -> {
|
||||
RecipientArchiveProcessor.import(frame.recipient, importState)
|
||||
frameRecipient != null -> {
|
||||
RecipientArchiveProcessor.import(frameRecipient, importState)
|
||||
eventTimer.emit("recipient")
|
||||
frameCount++
|
||||
}
|
||||
|
||||
frame.chat != null -> {
|
||||
ChatArchiveProcessor.import(frame.chat, importState)
|
||||
frameChat != null -> {
|
||||
ChatArchiveProcessor.import(frameChat, importState)
|
||||
eventTimer.emit("chat")
|
||||
frameCount++
|
||||
}
|
||||
|
||||
frame.adHocCall != null -> {
|
||||
AdHocCallArchiveProcessor.import(frame.adHocCall, importState)
|
||||
frameAdHocCall != null -> {
|
||||
AdHocCallArchiveProcessor.import(frameAdHocCall, importState)
|
||||
eventTimer.emit("call")
|
||||
frameCount++
|
||||
}
|
||||
|
||||
frame.stickerPack != null -> {
|
||||
StickerArchiveProcessor.import(frame.stickerPack)
|
||||
frameStickerPack != null -> {
|
||||
StickerArchiveProcessor.import(frameStickerPack)
|
||||
eventTimer.emit("sticker-pack")
|
||||
frameCount++
|
||||
}
|
||||
|
||||
frame.notificationProfile != null -> {
|
||||
NotificationProfileArchiveProcessor.import(frame.notificationProfile, importState)
|
||||
frameNotificationProfile != null -> {
|
||||
NotificationProfileArchiveProcessor.import(frameNotificationProfile, importState)
|
||||
eventTimer.emit("notification-profile")
|
||||
frameCount++
|
||||
}
|
||||
|
||||
frame.chatFolder != null -> {
|
||||
ChatFolderArchiveProcessor.import(frame.chatFolder, importState)
|
||||
frameChatFolder != null -> {
|
||||
ChatFolderArchiveProcessor.import(frameChatFolder, importState)
|
||||
eventTimer.emit("chat-folder")
|
||||
frameCount++
|
||||
}
|
||||
|
||||
frame.chatItem != null -> {
|
||||
chatItemInserter.import(frame.chatItem)
|
||||
frameChatItem != null -> {
|
||||
chatItemInserter.import(frameChatItem)
|
||||
eventTimer.emit("chatItem")
|
||||
frameCount++
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.thoughtcrime.securesms.backup.v2.database
|
||||
|
||||
import android.content.ContentValues
|
||||
import org.signal.archive.proto.AccountData
|
||||
import org.signal.core.models.ServiceId
|
||||
import org.signal.core.util.Base64
|
||||
import org.signal.core.util.logging.Log
|
||||
@@ -15,7 +16,6 @@ import org.signal.core.util.update
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException
|
||||
import org.thoughtcrime.securesms.backup.v2.exporters.ContactArchiveExporter
|
||||
import org.thoughtcrime.securesms.backup.v2.exporters.GroupArchiveExporter
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.AccountData
|
||||
import org.thoughtcrime.securesms.database.GroupTable
|
||||
import org.thoughtcrime.securesms.database.IdentityTable
|
||||
import org.thoughtcrime.securesms.database.RecipientTable
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
package org.thoughtcrime.securesms.backup.v2.database
|
||||
|
||||
import android.database.Cursor
|
||||
import org.signal.archive.proto.AdHocCall
|
||||
import org.signal.core.util.requireLong
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.AdHocCall
|
||||
import org.thoughtcrime.securesms.backup.v2.util.clampToValidBackupRange
|
||||
import org.thoughtcrime.securesms.database.CallTable
|
||||
import java.io.Closeable
|
||||
|
||||
@@ -7,10 +7,10 @@ package org.thoughtcrime.securesms.backup.v2.database
|
||||
|
||||
import android.database.Cursor
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.signal.archive.proto.CallLink
|
||||
import org.signal.core.util.nullIfEmpty
|
||||
import org.signal.ringrtc.CallLinkState
|
||||
import org.thoughtcrime.securesms.backup.v2.ArchiveRecipient
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.CallLink
|
||||
import org.thoughtcrime.securesms.backup.v2.util.clampToValidBackupRange
|
||||
import org.thoughtcrime.securesms.database.CallLinkTable
|
||||
import java.io.Closeable
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.thoughtcrime.securesms.backup.v2.exporters
|
||||
|
||||
import android.database.Cursor
|
||||
import org.signal.archive.proto.Chat
|
||||
import org.signal.core.util.decodeOrNull
|
||||
import org.signal.core.util.requireBlob
|
||||
import org.signal.core.util.requireBoolean
|
||||
@@ -13,7 +14,6 @@ import org.signal.core.util.requireInt
|
||||
import org.signal.core.util.requireIntOrNull
|
||||
import org.signal.core.util.requireLong
|
||||
import org.thoughtcrime.securesms.backup.v2.ExportState
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Chat
|
||||
import org.thoughtcrime.securesms.backup.v2.util.ChatStyleConverter
|
||||
import org.thoughtcrime.securesms.backup.v2.util.isValid
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors
|
||||
|
||||
@@ -9,6 +9,38 @@ import android.database.Cursor
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import org.signal.archive.proto.AdminDeletedMessage
|
||||
import org.signal.archive.proto.ChatItem
|
||||
import org.signal.archive.proto.ChatUpdateMessage
|
||||
import org.signal.archive.proto.ContactAttachment
|
||||
import org.signal.archive.proto.ContactMessage
|
||||
import org.signal.archive.proto.DirectStoryReplyMessage
|
||||
import org.signal.archive.proto.ExpirationTimerChatUpdate
|
||||
import org.signal.archive.proto.GenericGroupUpdate
|
||||
import org.signal.archive.proto.GroupCall
|
||||
import org.signal.archive.proto.GroupChangeChatUpdate
|
||||
import org.signal.archive.proto.GroupExpirationTimerUpdate
|
||||
import org.signal.archive.proto.GroupV2MigrationUpdate
|
||||
import org.signal.archive.proto.IndividualCall
|
||||
import org.signal.archive.proto.LearnedProfileChatUpdate
|
||||
import org.signal.archive.proto.MessageAttachment
|
||||
import org.signal.archive.proto.PaymentNotification
|
||||
import org.signal.archive.proto.PinMessageUpdate
|
||||
import org.signal.archive.proto.Poll
|
||||
import org.signal.archive.proto.PollTerminateUpdate
|
||||
import org.signal.archive.proto.ProfileChangeChatUpdate
|
||||
import org.signal.archive.proto.Quote
|
||||
import org.signal.archive.proto.Reaction
|
||||
import org.signal.archive.proto.RemoteDeletedMessage
|
||||
import org.signal.archive.proto.SendStatus
|
||||
import org.signal.archive.proto.SessionSwitchoverChatUpdate
|
||||
import org.signal.archive.proto.SimpleChatUpdate
|
||||
import org.signal.archive.proto.StandardMessage
|
||||
import org.signal.archive.proto.Sticker
|
||||
import org.signal.archive.proto.StickerMessage
|
||||
import org.signal.archive.proto.Text
|
||||
import org.signal.archive.proto.ThreadMergeChatUpdate
|
||||
import org.signal.archive.proto.ViewOnceMessage
|
||||
import org.signal.core.models.ServiceId
|
||||
import org.signal.core.util.Base64
|
||||
import org.signal.core.util.EventTimer
|
||||
@@ -41,38 +73,6 @@ import org.thoughtcrime.securesms.backup.v2.BackupMode
|
||||
import org.thoughtcrime.securesms.backup.v2.ExportOddities
|
||||
import org.thoughtcrime.securesms.backup.v2.ExportSkips
|
||||
import org.thoughtcrime.securesms.backup.v2.ExportState
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.AdminDeletedMessage
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ChatItem
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ChatUpdateMessage
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ContactAttachment
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ContactMessage
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.DirectStoryReplyMessage
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ExpirationTimerChatUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GenericGroupUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupCall
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupChangeChatUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupExpirationTimerUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupV2MigrationUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.IndividualCall
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.LearnedProfileChatUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.MessageAttachment
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.PaymentNotification
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.PinMessageUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Poll
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.PollTerminateUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ProfileChangeChatUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Quote
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Reaction
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.RemoteDeletedMessage
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.SendStatus
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.SessionSwitchoverChatUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.SimpleChatUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.StandardMessage
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Sticker
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.StickerMessage
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Text
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ThreadMergeChatUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ViewOnceMessage
|
||||
import org.thoughtcrime.securesms.backup.v2.util.clampToValidBackupRange
|
||||
import org.thoughtcrime.securesms.backup.v2.util.toRemoteFilePointer
|
||||
import org.thoughtcrime.securesms.contactshare.Contact
|
||||
@@ -117,8 +117,8 @@ import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Future
|
||||
import kotlin.math.max
|
||||
import kotlin.time.Duration.Companion.days
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.BodyRange as BackupBodyRange
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GiftBadge as BackupGiftBadge
|
||||
import org.signal.archive.proto.BodyRange as BackupBodyRange
|
||||
import org.signal.archive.proto.GiftBadge as BackupGiftBadge
|
||||
|
||||
private val TAG = Log.tag(ChatItemArchiveExporter::class.java)
|
||||
private val MAX_INLINED_BODY_SIZE = 128.kibiBytes.bytes.toInt()
|
||||
@@ -958,8 +958,8 @@ private fun BackupMessageRecord.toRemoteLinkPreviews(attachments: List<DatabaseA
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
private fun LinkPreview.toRemoteLinkPreview(backupMode: BackupMode): org.thoughtcrime.securesms.backup.v2.proto.LinkPreview {
|
||||
return org.thoughtcrime.securesms.backup.v2.proto.LinkPreview(
|
||||
private fun LinkPreview.toRemoteLinkPreview(backupMode: BackupMode): org.signal.archive.proto.LinkPreview {
|
||||
return org.signal.archive.proto.LinkPreview(
|
||||
url = url,
|
||||
title = title.nullIfEmpty(),
|
||||
image = (thumbnail.orNull() as? DatabaseAttachment)?.toRemoteMessageAttachment(backupMode = backupMode)?.pointer,
|
||||
@@ -1685,17 +1685,18 @@ private fun ChatItem.validateChatItem(exportState: ExportState, selfRecipientId:
|
||||
return null
|
||||
}
|
||||
|
||||
if (this.updateMessage != null && this.updateMessage.isOnlyForIndividualChats() && exportState.threadIdToRecipientId[this.chatId] !in exportState.contactRecipientIds) {
|
||||
val validatedUpdateMessage = this.updateMessage
|
||||
if (validatedUpdateMessage != null && validatedUpdateMessage.isOnlyForIndividualChats() && exportState.threadIdToRecipientId[this.chatId] !in exportState.contactRecipientIds) {
|
||||
Log.w(TAG, ExportSkips.individualChatUpdateInWrongTypeOfChat(this.dateSent))
|
||||
return null
|
||||
}
|
||||
|
||||
if (this.updateMessage != null && this.updateMessage.isOnlyForGroupChats() && exportState.threadIdToRecipientId[this.chatId] !in exportState.groupRecipientIds) {
|
||||
if (validatedUpdateMessage != null && validatedUpdateMessage.isOnlyForGroupChats() && exportState.threadIdToRecipientId[this.chatId] !in exportState.groupRecipientIds) {
|
||||
Log.w(TAG, ExportSkips.groupChatUpdateInWrongTypeOfChat(this.dateSent))
|
||||
return null
|
||||
}
|
||||
|
||||
if (this.updateMessage != null && this.updateMessage.canOnlyBeAuthoredBySelf() && this.authorId != selfRecipientId.toLong()) {
|
||||
if (validatedUpdateMessage != null && validatedUpdateMessage.canOnlyBeAuthoredBySelf() && this.authorId != selfRecipientId.toLong()) {
|
||||
Log.w(TAG, ExportSkips.individualChatUpdateNotAuthoredBySelf(this.dateSent))
|
||||
return null
|
||||
}
|
||||
@@ -1777,17 +1778,15 @@ private fun List<MessageAttachment>.withFixedVoiceNotes(textPresent: Boolean): L
|
||||
}
|
||||
|
||||
private fun ChatItem.withDowngradeVoiceNotes(): ChatItem {
|
||||
if (this.standardMessage == null) {
|
||||
return this
|
||||
}
|
||||
val msg = this.standardMessage ?: return this
|
||||
|
||||
if (this.standardMessage.attachments.none { it.flag == MessageAttachment.Flag.VOICE_MESSAGE }) {
|
||||
if (msg.attachments.none { it.flag == MessageAttachment.Flag.VOICE_MESSAGE }) {
|
||||
return this
|
||||
}
|
||||
|
||||
return this.copy(
|
||||
standardMessage = this.standardMessage.copy(
|
||||
attachments = this.standardMessage.attachments.map {
|
||||
standardMessage = msg.copy(
|
||||
attachments = msg.attachments.map {
|
||||
if (it.flag == MessageAttachment.Flag.VOICE_MESSAGE) {
|
||||
it.copy(flag = MessageAttachment.Flag.NONE)
|
||||
} else {
|
||||
|
||||
@@ -7,6 +7,8 @@ package org.thoughtcrime.securesms.backup.v2.exporters
|
||||
|
||||
import android.database.Cursor
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.signal.archive.proto.Contact
|
||||
import org.signal.archive.proto.Self
|
||||
import org.signal.core.models.ServiceId
|
||||
import org.signal.core.util.Base64
|
||||
import org.signal.core.util.logging.Log
|
||||
@@ -18,8 +20,6 @@ import org.signal.core.util.requireLong
|
||||
import org.signal.core.util.requireString
|
||||
import org.signal.core.util.toByteArray
|
||||
import org.thoughtcrime.securesms.backup.v2.ArchiveRecipient
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Contact
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Self
|
||||
import org.thoughtcrime.securesms.backup.v2.util.clampToValidBackupRange
|
||||
import org.thoughtcrime.securesms.backup.v2.util.isValidUsername
|
||||
import org.thoughtcrime.securesms.backup.v2.util.toRemote
|
||||
|
||||
@@ -7,6 +7,8 @@ package org.thoughtcrime.securesms.backup.v2.exporters
|
||||
|
||||
import android.database.Cursor
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.signal.archive.proto.DistributionList
|
||||
import org.signal.archive.proto.DistributionListItem
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.requireBoolean
|
||||
import org.signal.core.util.requireLong
|
||||
@@ -17,8 +19,6 @@ import org.thoughtcrime.securesms.backup.v2.ArchiveRecipient
|
||||
import org.thoughtcrime.securesms.backup.v2.ExportOddities
|
||||
import org.thoughtcrime.securesms.backup.v2.ExportState
|
||||
import org.thoughtcrime.securesms.backup.v2.database.getMembersForBackup
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.DistributionList
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.DistributionListItem
|
||||
import org.thoughtcrime.securesms.backup.v2.util.clampToValidBackupRange
|
||||
import org.thoughtcrime.securesms.database.DistributionListTables
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListId
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.backup.v2.exporters
|
||||
|
||||
import android.database.Cursor
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.signal.archive.proto.Group
|
||||
import org.signal.core.models.ServiceId
|
||||
import org.signal.core.util.requireBlob
|
||||
import org.signal.core.util.requireBoolean
|
||||
@@ -24,7 +25,6 @@ import org.signal.storageservice.storage.protos.groups.local.DecryptedRequesting
|
||||
import org.signal.storageservice.storage.protos.groups.local.EnabledState
|
||||
import org.thoughtcrime.securesms.backup.v2.ArchiveGroup
|
||||
import org.thoughtcrime.securesms.backup.v2.ArchiveRecipient
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Group
|
||||
import org.thoughtcrime.securesms.backup.v2.util.toRemote
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
|
||||
import org.thoughtcrime.securesms.database.GroupTable
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.importer
|
||||
|
||||
import org.signal.archive.proto.AdHocCall
|
||||
import org.signal.core.util.insertInto
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportState
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.AdHocCall
|
||||
import org.thoughtcrime.securesms.database.CallTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.importer
|
||||
|
||||
import org.signal.archive.proto.CallLink
|
||||
import org.signal.core.util.isEmpty
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.ringrtc.CallLinkRootKey
|
||||
import org.signal.ringrtc.CallLinkState
|
||||
import org.thoughtcrime.securesms.backup.v2.ArchiveCallLink
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.CallLink
|
||||
import org.thoughtcrime.securesms.database.CallLinkTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
package org.thoughtcrime.securesms.backup.v2.importer
|
||||
|
||||
import androidx.core.content.contentValuesOf
|
||||
import org.signal.archive.proto.Chat
|
||||
import org.signal.core.util.SqlUtil
|
||||
import org.signal.core.util.insertInto
|
||||
import org.signal.core.util.toInt
|
||||
import org.thoughtcrime.securesms.attachments.AttachmentId
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportState
|
||||
import org.thoughtcrime.securesms.backup.v2.database.restoreWallpaperAttachment
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Chat
|
||||
import org.thoughtcrime.securesms.backup.v2.util.parseChatWallpaper
|
||||
import org.thoughtcrime.securesms.backup.v2.util.toLocal
|
||||
import org.thoughtcrime.securesms.backup.v2.util.toLocalAttachment
|
||||
|
||||
@@ -7,6 +7,23 @@ package org.thoughtcrime.securesms.backup.v2.importer
|
||||
|
||||
import android.content.ContentValues
|
||||
import androidx.core.content.contentValuesOf
|
||||
import org.signal.archive.proto.BodyRange
|
||||
import org.signal.archive.proto.ChatItem
|
||||
import org.signal.archive.proto.ChatUpdateMessage
|
||||
import org.signal.archive.proto.ContactAttachment
|
||||
import org.signal.archive.proto.DirectStoryReplyMessage
|
||||
import org.signal.archive.proto.GroupCall
|
||||
import org.signal.archive.proto.IndividualCall
|
||||
import org.signal.archive.proto.LinkPreview
|
||||
import org.signal.archive.proto.MessageAttachment
|
||||
import org.signal.archive.proto.PaymentNotification
|
||||
import org.signal.archive.proto.Quote
|
||||
import org.signal.archive.proto.Reaction
|
||||
import org.signal.archive.proto.SendStatus
|
||||
import org.signal.archive.proto.SimpleChatUpdate
|
||||
import org.signal.archive.proto.StandardMessage
|
||||
import org.signal.archive.proto.Sticker
|
||||
import org.signal.archive.proto.ViewOnceMessage
|
||||
import org.signal.core.models.ServiceId
|
||||
import org.signal.core.util.Base64
|
||||
import org.signal.core.util.Hex
|
||||
@@ -24,23 +41,6 @@ import org.thoughtcrime.securesms.attachments.PointerAttachment
|
||||
import org.thoughtcrime.securesms.attachments.TombstoneAttachment
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportSkips
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportState
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.BodyRange
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ChatItem
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ChatUpdateMessage
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ContactAttachment
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.DirectStoryReplyMessage
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupCall
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.IndividualCall
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.LinkPreview
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.MessageAttachment
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.PaymentNotification
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Quote
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Reaction
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.SendStatus
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.SimpleChatUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.StandardMessage
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Sticker
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ViewOnceMessage
|
||||
import org.thoughtcrime.securesms.backup.v2.util.toLocalAttachment
|
||||
import org.thoughtcrime.securesms.contactshare.Contact
|
||||
import org.thoughtcrime.securesms.database.AttachmentTable
|
||||
@@ -89,7 +89,7 @@ import java.math.BigInteger
|
||||
import java.sql.SQLException
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GiftBadge as BackupGiftBadge
|
||||
import org.signal.archive.proto.GiftBadge as BackupGiftBadge
|
||||
|
||||
/**
|
||||
* An object that will ingest all of the [ChatItem]s you want to write, buffer them until hitting a specified batch size, and then batch insert them
|
||||
@@ -194,7 +194,8 @@ class ChatItemArchiveImporter(
|
||||
return
|
||||
}
|
||||
|
||||
if (chatItem.adminDeletedMessage != null && importState.remoteToLocalRecipientId[chatItem.adminDeletedMessage.adminId] == null) {
|
||||
val adminDeletedMessage = chatItem.adminDeletedMessage
|
||||
if (adminDeletedMessage != null && importState.remoteToLocalRecipientId[adminDeletedMessage.adminId] == null) {
|
||||
Log.w(TAG, ImportSkips.missingAdminDeleteRecipient(chatItem.dateSent, chatItem.chatId))
|
||||
return
|
||||
}
|
||||
@@ -286,17 +287,22 @@ class ChatItemArchiveImporter(
|
||||
|
||||
val followUps: MutableList<(Long) -> Unit> = mutableListOf()
|
||||
|
||||
if (this.updateMessage != null) {
|
||||
if (this.updateMessage.individualCall != null && this.updateMessage.individualCall.callId != null) {
|
||||
val updateMessage = this.updateMessage
|
||||
if (updateMessage != null) {
|
||||
val individualCall = updateMessage.individualCall
|
||||
val groupCall = updateMessage.groupCall
|
||||
val pollTerminate = updateMessage.pollTerminate
|
||||
val pinMessage = updateMessage.pinMessage
|
||||
if (individualCall != null && individualCall.callId != null) {
|
||||
followUps += { messageRowId ->
|
||||
val values = contentValuesOf(
|
||||
CallTable.CALL_ID to updateMessage.individualCall.callId,
|
||||
CallTable.CALL_ID to individualCall.callId,
|
||||
CallTable.MESSAGE_ID to messageRowId,
|
||||
CallTable.PEER to chatRecipientId.serialize(),
|
||||
CallTable.TYPE to CallTable.Type.serialize(if (updateMessage.individualCall.type == IndividualCall.Type.VIDEO_CALL) CallTable.Type.VIDEO_CALL else CallTable.Type.AUDIO_CALL),
|
||||
CallTable.DIRECTION to CallTable.Direction.serialize(if (updateMessage.individualCall.direction == IndividualCall.Direction.OUTGOING) CallTable.Direction.OUTGOING else CallTable.Direction.INCOMING),
|
||||
CallTable.TYPE to CallTable.Type.serialize(if (individualCall.type == IndividualCall.Type.VIDEO_CALL) CallTable.Type.VIDEO_CALL else CallTable.Type.AUDIO_CALL),
|
||||
CallTable.DIRECTION to CallTable.Direction.serialize(if (individualCall.direction == IndividualCall.Direction.OUTGOING) CallTable.Direction.OUTGOING else CallTable.Direction.INCOMING),
|
||||
CallTable.EVENT to CallTable.Event.serialize(
|
||||
when (updateMessage.individualCall.state) {
|
||||
when (individualCall.state) {
|
||||
IndividualCall.State.MISSED -> CallTable.Event.MISSED
|
||||
IndividualCall.State.MISSED_NOTIFICATION_PROFILE -> CallTable.Event.MISSED_NOTIFICATION_PROFILE
|
||||
IndividualCall.State.ACCEPTED -> CallTable.Event.ACCEPTED
|
||||
@@ -304,24 +310,24 @@ class ChatItemArchiveImporter(
|
||||
else -> CallTable.Event.MISSED
|
||||
}
|
||||
),
|
||||
CallTable.TIMESTAMP to updateMessage.individualCall.startedCallTimestamp,
|
||||
CallTable.READ to updateMessage.individualCall.read
|
||||
CallTable.TIMESTAMP to individualCall.startedCallTimestamp,
|
||||
CallTable.READ to individualCall.read
|
||||
)
|
||||
db.insert(CallTable.TABLE_NAME, SQLiteDatabase.CONFLICT_IGNORE, values)
|
||||
}
|
||||
} else if (this.updateMessage.groupCall != null && this.updateMessage.groupCall.callId != null) {
|
||||
} else if (groupCall != null && groupCall.callId != null) {
|
||||
followUps += { messageRowId ->
|
||||
val ringer: RecipientId? = this.updateMessage.groupCall.ringerRecipientId?.let { importState.remoteToLocalRecipientId[it] }
|
||||
val ringer: RecipientId? = groupCall.ringerRecipientId?.let { importState.remoteToLocalRecipientId[it] }
|
||||
|
||||
val values = contentValuesOf(
|
||||
CallTable.CALL_ID to updateMessage.groupCall.callId,
|
||||
CallTable.CALL_ID to groupCall.callId,
|
||||
CallTable.MESSAGE_ID to messageRowId,
|
||||
CallTable.PEER to chatRecipientId.serialize(),
|
||||
CallTable.RINGER to ringer?.serialize(),
|
||||
CallTable.TYPE to CallTable.Type.serialize(CallTable.Type.GROUP_CALL),
|
||||
CallTable.DIRECTION to CallTable.Direction.serialize(if (ringer == selfId) CallTable.Direction.OUTGOING else CallTable.Direction.INCOMING),
|
||||
CallTable.EVENT to CallTable.Event.serialize(
|
||||
when (updateMessage.groupCall.state) {
|
||||
when (groupCall.state) {
|
||||
GroupCall.State.ACCEPTED -> CallTable.Event.ACCEPTED
|
||||
GroupCall.State.MISSED -> CallTable.Event.MISSED
|
||||
GroupCall.State.MISSED_NOTIFICATION_PROFILE -> CallTable.Event.MISSED_NOTIFICATION_PROFILE
|
||||
@@ -333,17 +339,17 @@ class ChatItemArchiveImporter(
|
||||
else -> CallTable.Event.GENERIC_GROUP_CALL
|
||||
}
|
||||
),
|
||||
CallTable.TIMESTAMP to updateMessage.groupCall.startedCallTimestamp,
|
||||
CallTable.TIMESTAMP to groupCall.startedCallTimestamp,
|
||||
CallTable.READ to CallTable.ReadState.serialize(CallTable.ReadState.READ)
|
||||
)
|
||||
db.insert(CallTable.TABLE_NAME, SQLiteDatabase.CONFLICT_IGNORE, values)
|
||||
}
|
||||
} else if (this.updateMessage.pollTerminate != null) {
|
||||
} else if (pollTerminate != null) {
|
||||
followUps += { endPollMessageId ->
|
||||
val pollMessageId = SignalDatabase.messages.getMessageFor(updateMessage.pollTerminate.targetSentTimestamp, fromRecipientId)?.id ?: -1
|
||||
val pollMessageId = SignalDatabase.messages.getMessageFor(pollTerminate.targetSentTimestamp, fromRecipientId)?.id ?: -1
|
||||
val pollId = SignalDatabase.polls.getPollId(pollMessageId)
|
||||
|
||||
val messageExtras = MessageExtras(pollTerminate = PollTerminate(question = updateMessage.pollTerminate.question, messageId = pollMessageId, targetTimestamp = updateMessage.pollTerminate.targetSentTimestamp))
|
||||
val messageExtras = MessageExtras(pollTerminate = PollTerminate(question = pollTerminate.question, messageId = pollMessageId, targetTimestamp = pollTerminate.targetSentTimestamp))
|
||||
db.update(MessageTable.TABLE_NAME)
|
||||
.values(MessageTable.MESSAGE_EXTRAS to messageExtras.encode())
|
||||
.where("${MessageTable.ID} = ?", endPollMessageId)
|
||||
@@ -353,16 +359,16 @@ class ChatItemArchiveImporter(
|
||||
SignalDatabase.polls.endPoll(pollId = pollId, endingMessageId = endPollMessageId)
|
||||
}
|
||||
}
|
||||
} else if (this.updateMessage.pinMessage != null) {
|
||||
} else if (pinMessage != null) {
|
||||
followUps += { pinUpdateMessageId ->
|
||||
val targetAuthorId = importState.remoteToLocalRecipientId[updateMessage.pinMessage.authorId]
|
||||
val targetAuthorId = importState.remoteToLocalRecipientId[pinMessage.authorId]
|
||||
if (targetAuthorId != null) {
|
||||
val pinnedMessageId = SignalDatabase.messages.getMessageFor(updateMessage.pinMessage.targetSentTimestamp, targetAuthorId)?.id ?: -1
|
||||
val pinnedMessageId = SignalDatabase.messages.getMessageFor(pinMessage.targetSentTimestamp, targetAuthorId)?.id ?: -1
|
||||
val messageExtras = MessageExtras(
|
||||
pinnedMessage = PinnedMessage(
|
||||
pinnedMessageId = pinnedMessageId,
|
||||
targetAuthorAci = recipients.getRecord(targetAuthorId).aci!!.toByteString(),
|
||||
targetTimestamp = updateMessage.pinMessage.targetSentTimestamp
|
||||
targetTimestamp = pinMessage.targetSentTimestamp
|
||||
)
|
||||
)
|
||||
|
||||
@@ -397,8 +403,9 @@ class ChatItemArchiveImporter(
|
||||
}
|
||||
}
|
||||
|
||||
if (this.contactMessage != null) {
|
||||
val contact = this.contactMessage.contact?.let { backupContact ->
|
||||
val contactMessage = this.contactMessage
|
||||
if (contactMessage != null) {
|
||||
val contact = contactMessage.contact?.let { backupContact ->
|
||||
Contact(
|
||||
backupContact.name.toLocal(),
|
||||
backupContact.organization,
|
||||
@@ -453,8 +460,9 @@ class ChatItemArchiveImporter(
|
||||
}
|
||||
}
|
||||
|
||||
if (this.directStoryReplyMessage != null) {
|
||||
val (trimmedBodyText, longTextAttachment) = this.directStoryReplyMessage.parseBodyText(importState)
|
||||
val directStoryReplyMessage = this.directStoryReplyMessage
|
||||
if (directStoryReplyMessage != null) {
|
||||
val (trimmedBodyText, longTextAttachment) = directStoryReplyMessage.parseBodyText(importState)
|
||||
if (trimmedBodyText != null) {
|
||||
contentValues.put(MessageTable.BODY, trimmedBodyText)
|
||||
}
|
||||
@@ -469,25 +477,26 @@ class ChatItemArchiveImporter(
|
||||
}
|
||||
}
|
||||
|
||||
if (this.standardMessage != null) {
|
||||
val mentions = this.standardMessage.text?.bodyRanges.filterToLocalMentions()
|
||||
val standardMessage = this.standardMessage
|
||||
if (standardMessage != null) {
|
||||
val mentions = standardMessage.text?.bodyRanges.filterToLocalMentions()
|
||||
if (mentions.isNotEmpty()) {
|
||||
followUps += { messageId ->
|
||||
SignalDatabase.mentions.insert(threadId, messageId, mentions)
|
||||
}
|
||||
}
|
||||
val linkPreviews = this.standardMessage.linkPreview.map { it.toLocalLinkPreview() }
|
||||
val linkPreviews = standardMessage.linkPreview.map { it.toLocalLinkPreview() }
|
||||
val linkPreviewAttachments: List<Attachment> = linkPreviews.mapNotNull { it.thumbnail.orNull() }
|
||||
val attachments: List<Attachment> = this.standardMessage.attachments.mapNotNull { attachment ->
|
||||
val attachments: List<Attachment> = standardMessage.attachments.mapNotNull { attachment ->
|
||||
attachment.toLocalAttachment()
|
||||
}
|
||||
|
||||
val (trimmedBodyText, longTextAttachment) = this.standardMessage.parseBodyText(importState)
|
||||
val (trimmedBodyText, longTextAttachment) = standardMessage.parseBodyText(importState)
|
||||
if (trimmedBodyText != null) {
|
||||
contentValues.put(MessageTable.BODY, trimmedBodyText)
|
||||
}
|
||||
|
||||
val quoteAttachments: List<Attachment> = this.standardMessage.quote?.toLocalAttachments() ?: emptyList()
|
||||
val quoteAttachments: List<Attachment> = standardMessage.quote?.toLocalAttachments() ?: emptyList()
|
||||
|
||||
val hasAttachments = attachments.isNotEmpty() || linkPreviewAttachments.isNotEmpty() || quoteAttachments.isNotEmpty() || longTextAttachment != null
|
||||
|
||||
@@ -515,8 +524,9 @@ class ChatItemArchiveImporter(
|
||||
}
|
||||
}
|
||||
|
||||
if (this.stickerMessage != null) {
|
||||
val sticker = this.stickerMessage.sticker
|
||||
val stickerMessage = this.stickerMessage
|
||||
if (stickerMessage != null) {
|
||||
val sticker = stickerMessage.sticker
|
||||
val attachment = sticker.toLocalAttachment()
|
||||
if (attachment != null) {
|
||||
followUps += { messageRowId ->
|
||||
@@ -525,8 +535,9 @@ class ChatItemArchiveImporter(
|
||||
}
|
||||
}
|
||||
|
||||
if (this.viewOnceMessage != null) {
|
||||
val attachment = this.viewOnceMessage.attachment?.toLocalAttachment()
|
||||
val viewOnceMessage = this.viewOnceMessage
|
||||
if (viewOnceMessage != null) {
|
||||
val attachment = viewOnceMessage.attachment?.toLocalAttachment()
|
||||
if (attachment != null) {
|
||||
followUps += { messageRowId ->
|
||||
SignalDatabase.attachments.insertAttachmentsForMessage(messageRowId, listOf(attachment), emptyList())
|
||||
@@ -534,7 +545,8 @@ class ChatItemArchiveImporter(
|
||||
}
|
||||
}
|
||||
|
||||
if (this.poll != null) {
|
||||
val poll = this.poll
|
||||
if (poll != null) {
|
||||
contentValues.put(MessageTable.BODY, poll.question)
|
||||
contentValues.put(MessageTable.VOTES_LAST_SEEN, System.currentTimeMillis())
|
||||
|
||||
@@ -582,15 +594,14 @@ class ChatItemArchiveImporter(
|
||||
* If the attachment is non-null, then you should store it along with the message, as it contains the long text.
|
||||
*/
|
||||
private fun StandardMessage.parseBodyText(importState: ImportState): Pair<String?, Attachment?> {
|
||||
if (this.longText != null) {
|
||||
return null to this.longText.toLocalAttachment(contentType = "text/x-signal-plain")
|
||||
val longText = this.longText
|
||||
if (longText != null) {
|
||||
return null to longText.toLocalAttachment(contentType = "text/x-signal-plain")
|
||||
}
|
||||
|
||||
if (this.text?.body == null) {
|
||||
return null to null
|
||||
}
|
||||
val body = this.text?.body ?: return null to null
|
||||
|
||||
val splitResult = MessageUtil.getSplitMessage(AppDependencies.application, this.text.body)
|
||||
val splitResult = MessageUtil.getSplitMessage(AppDependencies.application, body)
|
||||
if (splitResult.textSlide.isPresent) {
|
||||
return splitResult.body to splitResult.textSlide.get().asAttachment()
|
||||
}
|
||||
@@ -606,15 +617,15 @@ class ChatItemArchiveImporter(
|
||||
* If the attachment is non-null, then you should store it along with the message, as it contains the long text.
|
||||
*/
|
||||
private fun DirectStoryReplyMessage.parseBodyText(importState: ImportState): Pair<String?, Attachment?> {
|
||||
if (this.textReply?.longText != null) {
|
||||
return null to this.textReply.longText.toLocalAttachment(contentType = "text/x-signal-plain")
|
||||
val textReply = this.textReply
|
||||
val longText = textReply?.longText
|
||||
if (longText != null) {
|
||||
return null to longText.toLocalAttachment(contentType = "text/x-signal-plain")
|
||||
}
|
||||
|
||||
if (this.textReply?.text == null) {
|
||||
return null to null
|
||||
}
|
||||
val body = textReply?.text?.body ?: return null to null
|
||||
|
||||
val splitResult = MessageUtil.getSplitMessage(AppDependencies.application, this.textReply.text.body)
|
||||
val splitResult = MessageUtil.getSplitMessage(AppDependencies.application, body)
|
||||
if (splitResult.textSlide.isPresent) {
|
||||
return splitResult.body to splitResult.textSlide.get().asAttachment()
|
||||
}
|
||||
@@ -625,16 +636,20 @@ class ChatItemArchiveImporter(
|
||||
private fun ChatItem.toMessageContentValues(fromRecipientId: RecipientId, chatRecipientId: RecipientId, threadId: Long): ContentValues {
|
||||
val contentValues = ContentValues()
|
||||
|
||||
val toRecipientId = if (this.outgoing != null) chatRecipientId else selfId
|
||||
val outgoing = this.outgoing
|
||||
val incoming = this.incoming
|
||||
val directionless = this.directionless
|
||||
|
||||
val toRecipientId = if (outgoing != null) chatRecipientId else selfId
|
||||
|
||||
contentValues.put(MessageTable.TYPE, this.getMessageType())
|
||||
contentValues.put(MessageTable.DATE_SENT, this.dateSent)
|
||||
contentValues.put(MessageTable.DATE_SERVER, this.incoming?.dateServerSent ?: -1)
|
||||
contentValues.put(MessageTable.DATE_SERVER, incoming?.dateServerSent ?: -1)
|
||||
contentValues.put(MessageTable.FROM_RECIPIENT_ID, fromRecipientId.serialize())
|
||||
contentValues.put(MessageTable.TO_RECIPIENT_ID, toRecipientId.serialize())
|
||||
contentValues.put(MessageTable.THREAD_ID, threadId)
|
||||
contentValues.put(MessageTable.DATE_RECEIVED, this.incoming?.dateReceived ?: this.outgoing?.dateReceived?.takeUnless { it == 0L } ?: this.dateSent)
|
||||
contentValues.put(MessageTable.RECEIPT_TIMESTAMP, this.outgoing?.sendStatus?.maxOfOrNull { it.timestamp } ?: 0)
|
||||
contentValues.put(MessageTable.DATE_RECEIVED, incoming?.dateReceived ?: outgoing?.dateReceived?.takeUnless { it == 0L } ?: this.dateSent)
|
||||
contentValues.put(MessageTable.RECEIPT_TIMESTAMP, outgoing?.sendStatus?.maxOfOrNull { it.timestamp } ?: 0)
|
||||
contentValues.putNull(MessageTable.LATEST_REVISION_ID)
|
||||
contentValues.putNull(MessageTable.ORIGINAL_MESSAGE_ID)
|
||||
contentValues.put(MessageTable.REVISION_NUMBER, 0)
|
||||
@@ -642,29 +657,29 @@ class ChatItemArchiveImporter(
|
||||
contentValues.put(MessageTable.EXPIRE_STARTED, this.expireStartDate ?: 0)
|
||||
|
||||
when {
|
||||
this.outgoing != null -> {
|
||||
val viewed = this.outgoing.sendStatus.any { it.viewed != null }
|
||||
val hasReadReceipt = viewed || this.outgoing.sendStatus.any { it.read != null }
|
||||
val hasDeliveryReceipt = viewed || hasReadReceipt || this.outgoing.sendStatus.any { it.delivered != null }
|
||||
outgoing != null -> {
|
||||
val viewed = outgoing.sendStatus.any { it.viewed != null }
|
||||
val hasReadReceipt = viewed || outgoing.sendStatus.any { it.read != null }
|
||||
val hasDeliveryReceipt = viewed || hasReadReceipt || outgoing.sendStatus.any { it.delivered != null }
|
||||
|
||||
contentValues.put(MessageTable.VIEWED_COLUMN, viewed.toInt())
|
||||
contentValues.put(MessageTable.HAS_READ_RECEIPT, hasReadReceipt.toInt())
|
||||
contentValues.put(MessageTable.HAS_DELIVERY_RECEIPT, hasDeliveryReceipt.toInt())
|
||||
contentValues.put(MessageTable.UNIDENTIFIED, this.outgoing.sendStatus.count { it.sealedSender })
|
||||
contentValues.put(MessageTable.UNIDENTIFIED, outgoing.sendStatus.count { it.sealedSender })
|
||||
contentValues.put(MessageTable.READ, 1)
|
||||
|
||||
contentValues.addNetworkFailures(this, importState)
|
||||
contentValues.addIdentityKeyMismatches(this, importState)
|
||||
}
|
||||
this.incoming != null -> {
|
||||
incoming != null -> {
|
||||
contentValues.put(MessageTable.VIEWED_COLUMN, 0)
|
||||
contentValues.put(MessageTable.HAS_READ_RECEIPT, 0)
|
||||
contentValues.put(MessageTable.HAS_DELIVERY_RECEIPT, 0)
|
||||
contentValues.put(MessageTable.UNIDENTIFIED, this.incoming.sealedSender.toInt())
|
||||
contentValues.put(MessageTable.READ, this.incoming.read.toInt())
|
||||
contentValues.put(MessageTable.UNIDENTIFIED, incoming.sealedSender.toInt())
|
||||
contentValues.put(MessageTable.READ, incoming.read.toInt())
|
||||
contentValues.put(MessageTable.NOTIFIED, 1)
|
||||
}
|
||||
this.directionless != null -> {
|
||||
directionless != null -> {
|
||||
contentValues.put(MessageTable.VIEWED_COLUMN, 0)
|
||||
contentValues.put(MessageTable.HAS_READ_RECEIPT, 0)
|
||||
contentValues.put(MessageTable.HAS_DELIVERY_RECEIPT, 0)
|
||||
@@ -680,21 +695,30 @@ class ChatItemArchiveImporter(
|
||||
contentValues.put(MessageTable.VIEW_ONCE, 0)
|
||||
contentValues.put(MessageTable.PARENT_STORY_ID, 0)
|
||||
|
||||
if (this.pinDetails != null) {
|
||||
val pinnedUntil = if (this.pinDetails.pinNeverExpires == true) MessageTable.PIN_FOREVER else this.pinDetails.pinExpiresAtTimestamp
|
||||
val pinDetails = this.pinDetails
|
||||
if (pinDetails != null) {
|
||||
val pinnedUntil = if (pinDetails.pinNeverExpires == true) MessageTable.PIN_FOREVER else pinDetails.pinExpiresAtTimestamp
|
||||
contentValues.put(MessageTable.PINNED_UNTIL, pinnedUntil ?: 0)
|
||||
contentValues.put(MessageTable.PINNED_AT, this.pinDetails.pinnedAtTimestamp)
|
||||
contentValues.put(MessageTable.PINNED_AT, pinDetails.pinnedAtTimestamp)
|
||||
}
|
||||
|
||||
val itemStandardMessage = this.standardMessage
|
||||
val itemRemoteDeletedMessage = this.remoteDeletedMessage
|
||||
val itemUpdateMessage = this.updateMessage
|
||||
val itemPaymentNotification = this.paymentNotification
|
||||
val itemGiftBadge = this.giftBadge
|
||||
val itemViewOnceMessage = this.viewOnceMessage
|
||||
val itemDirectStoryReplyMessage = this.directStoryReplyMessage
|
||||
val itemAdminDeletedMessage = this.adminDeletedMessage
|
||||
when {
|
||||
this.standardMessage != null -> contentValues.addStandardMessage(this.standardMessage)
|
||||
this.remoteDeletedMessage != null -> contentValues.put(MessageTable.DELETED_BY, fromRecipientId.toLong())
|
||||
this.updateMessage != null -> contentValues.addUpdateMessage(this.updateMessage, fromRecipientId, toRecipientId)
|
||||
this.paymentNotification != null -> contentValues.addPaymentNotification(this, chatRecipientId)
|
||||
this.giftBadge != null -> contentValues.addGiftBadge(this.giftBadge)
|
||||
this.viewOnceMessage != null -> contentValues.addViewOnce(this.viewOnceMessage)
|
||||
this.directStoryReplyMessage != null -> contentValues.addDirectStoryReply(this.directStoryReplyMessage, toRecipientId)
|
||||
this.adminDeletedMessage != null -> contentValues.put(MessageTable.DELETED_BY, importState.remoteToLocalRecipientId[this.adminDeletedMessage.adminId]!!.toLong())
|
||||
itemStandardMessage != null -> contentValues.addStandardMessage(itemStandardMessage)
|
||||
itemRemoteDeletedMessage != null -> contentValues.put(MessageTable.DELETED_BY, fromRecipientId.toLong())
|
||||
itemUpdateMessage != null -> contentValues.addUpdateMessage(itemUpdateMessage, fromRecipientId, toRecipientId)
|
||||
itemPaymentNotification != null -> contentValues.addPaymentNotification(this, chatRecipientId)
|
||||
itemGiftBadge != null -> contentValues.addGiftBadge(itemGiftBadge)
|
||||
itemViewOnceMessage != null -> contentValues.addViewOnce(itemViewOnceMessage)
|
||||
itemDirectStoryReplyMessage != null -> contentValues.addDirectStoryReply(itemDirectStoryReplyMessage, toRecipientId)
|
||||
itemAdminDeletedMessage != null -> contentValues.put(MessageTable.DELETED_BY, importState.remoteToLocalRecipientId[itemAdminDeletedMessage.adminId]!!.toLong())
|
||||
}
|
||||
|
||||
return contentValues
|
||||
@@ -733,15 +757,13 @@ class ChatItemArchiveImporter(
|
||||
}
|
||||
|
||||
private fun ChatItem.toReactionContentValues(messageId: Long): List<ContentValues> {
|
||||
val reactions: List<Reaction> = when {
|
||||
this.standardMessage != null -> this.standardMessage.reactions
|
||||
this.contactMessage != null -> this.contactMessage.reactions
|
||||
this.stickerMessage != null -> this.stickerMessage.reactions
|
||||
this.viewOnceMessage != null -> this.viewOnceMessage.reactions
|
||||
this.directStoryReplyMessage != null -> this.directStoryReplyMessage.reactions
|
||||
this.poll != null -> this.poll.reactions
|
||||
else -> emptyList()
|
||||
}
|
||||
val reactions: List<Reaction> = this.standardMessage?.reactions
|
||||
?: this.contactMessage?.reactions
|
||||
?: this.stickerMessage?.reactions
|
||||
?: this.viewOnceMessage?.reactions
|
||||
?: this.directStoryReplyMessage?.reactions
|
||||
?: this.poll?.reactions
|
||||
?: emptyList()
|
||||
|
||||
return reactions
|
||||
.mapNotNull {
|
||||
@@ -763,16 +785,14 @@ class ChatItemArchiveImporter(
|
||||
}
|
||||
|
||||
private fun ChatItem.toGroupReceiptContentValues(messageId: Long, chatBackupRecipientId: Long): List<ContentValues> {
|
||||
if (this.outgoing == null) {
|
||||
return emptyList()
|
||||
}
|
||||
val outgoing = this.outgoing ?: return emptyList()
|
||||
|
||||
// TODO [backup] This seems like an indirect/bad way to detect if this is a 1:1 or group convo
|
||||
if (this.outgoing.sendStatus.size == 1 && this.outgoing.sendStatus[0].recipientId == chatBackupRecipientId) {
|
||||
if (outgoing.sendStatus.size == 1 && outgoing.sendStatus[0].recipientId == chatBackupRecipientId) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
return this.outgoing.sendStatus.mapNotNull { sendStatus ->
|
||||
return outgoing.sendStatus.mapNotNull { sendStatus ->
|
||||
val recipientId = importState.remoteToLocalRecipientId[sendStatus.recipientId]
|
||||
|
||||
if (recipientId != null) {
|
||||
@@ -791,16 +811,17 @@ class ChatItemArchiveImporter(
|
||||
}
|
||||
|
||||
private fun ChatItem.getMessageType(): Long {
|
||||
var type: Long = if (this.outgoing != null) {
|
||||
if (this.outgoing.sendStatus.any { it.pending != null }) {
|
||||
val outgoing = this.outgoing
|
||||
var type: Long = if (outgoing != null) {
|
||||
if (outgoing.sendStatus.any { it.pending != null }) {
|
||||
MessageTypes.BASE_SENDING_TYPE
|
||||
} else if (this.outgoing.sendStatus.any { it.failed?.reason == SendStatus.Failed.FailureReason.IDENTITY_KEY_MISMATCH }) {
|
||||
} else if (outgoing.sendStatus.any { it.failed?.reason == SendStatus.Failed.FailureReason.IDENTITY_KEY_MISMATCH }) {
|
||||
MessageTypes.BASE_SENT_FAILED_TYPE
|
||||
} else if (this.outgoing.sendStatus.any { it.failed?.reason == SendStatus.Failed.FailureReason.UNKNOWN }) {
|
||||
} else if (outgoing.sendStatus.any { it.failed?.reason == SendStatus.Failed.FailureReason.UNKNOWN }) {
|
||||
MessageTypes.BASE_SENT_FAILED_TYPE
|
||||
} else if (this.outgoing.sendStatus.any { it.failed?.reason == SendStatus.Failed.FailureReason.NETWORK }) {
|
||||
} else if (outgoing.sendStatus.any { it.failed?.reason == SendStatus.Failed.FailureReason.NETWORK }) {
|
||||
MessageTypes.BASE_SENT_FAILED_TYPE
|
||||
} else if (this.outgoing.sendStatus.all { it.skipped != null }) {
|
||||
} else if (outgoing.sendStatus.all { it.skipped != null }) {
|
||||
MessageTypes.BASE_SENDING_SKIPPED_TYPE
|
||||
} else {
|
||||
MessageTypes.BASE_SENT_TYPE
|
||||
@@ -825,25 +846,38 @@ class ChatItemArchiveImporter(
|
||||
}
|
||||
|
||||
private fun ContentValues.addStandardMessage(standardMessage: StandardMessage) {
|
||||
if (standardMessage.text != null) {
|
||||
this.put(MessageTable.BODY, standardMessage.text.body)
|
||||
val text = standardMessage.text
|
||||
if (text != null) {
|
||||
this.put(MessageTable.BODY, text.body)
|
||||
|
||||
if (standardMessage.text.bodyRanges.isNotEmpty()) {
|
||||
this.put(MessageTable.MESSAGE_RANGES, standardMessage.text.bodyRanges.toLocalBodyRanges()?.encode())
|
||||
if (text.bodyRanges.isNotEmpty()) {
|
||||
this.put(MessageTable.MESSAGE_RANGES, text.bodyRanges.toLocalBodyRanges()?.encode())
|
||||
}
|
||||
}
|
||||
|
||||
if (standardMessage.quote != null) {
|
||||
this.addQuote(standardMessage.quote)
|
||||
val quote = standardMessage.quote
|
||||
if (quote != null) {
|
||||
this.addQuote(quote)
|
||||
}
|
||||
}
|
||||
|
||||
private fun ContentValues.addUpdateMessage(updateMessage: ChatUpdateMessage, fromRecipientId: RecipientId, toRecipientId: RecipientId) {
|
||||
var typeFlags: Long = 0
|
||||
val simpleUpdate = updateMessage.simpleUpdate
|
||||
val expirationTimerChange = updateMessage.expirationTimerChange
|
||||
val profileChange = updateMessage.profileChange
|
||||
val learnedProfileChange = updateMessage.learnedProfileChange
|
||||
val pollTerminate = updateMessage.pollTerminate
|
||||
val pinMessage = updateMessage.pinMessage
|
||||
val sessionSwitchover = updateMessage.sessionSwitchover
|
||||
val threadMerge = updateMessage.threadMerge
|
||||
val individualCall = updateMessage.individualCall
|
||||
val groupCall = updateMessage.groupCall
|
||||
val groupChange = updateMessage.groupChange
|
||||
when {
|
||||
updateMessage.simpleUpdate != null -> {
|
||||
simpleUpdate != null -> {
|
||||
val typeWithoutBase = (getAsLong(MessageTable.TYPE) and MessageTypes.BASE_TYPE_MASK.inv())
|
||||
typeFlags = when (updateMessage.simpleUpdate.type) {
|
||||
typeFlags = when (simpleUpdate.type) {
|
||||
SimpleChatUpdate.Type.UNKNOWN -> typeWithoutBase
|
||||
SimpleChatUpdate.Type.JOINED_SIGNAL -> MessageTypes.JOINED_TYPE or typeWithoutBase
|
||||
SimpleChatUpdate.Type.IDENTITY_UPDATE -> MessageTypes.KEY_EXCHANGE_IDENTITY_UPDATE_BIT or typeWithoutBase
|
||||
@@ -864,59 +898,59 @@ class ChatItemArchiveImporter(
|
||||
}
|
||||
|
||||
// Identity verification changes have to/from swapped
|
||||
if (updateMessage.simpleUpdate.type == SimpleChatUpdate.Type.IDENTITY_VERIFIED || updateMessage.simpleUpdate.type == SimpleChatUpdate.Type.IDENTITY_DEFAULT) {
|
||||
if (simpleUpdate.type == SimpleChatUpdate.Type.IDENTITY_VERIFIED || simpleUpdate.type == SimpleChatUpdate.Type.IDENTITY_DEFAULT) {
|
||||
put(MessageTable.FROM_RECIPIENT_ID, toRecipientId.serialize())
|
||||
put(MessageTable.TO_RECIPIENT_ID, fromRecipientId.serialize())
|
||||
}
|
||||
}
|
||||
updateMessage.expirationTimerChange != null -> {
|
||||
expirationTimerChange != null -> {
|
||||
typeFlags = getAsLong(MessageTable.TYPE) or MessageTypes.EXPIRATION_TIMER_UPDATE_BIT
|
||||
put(MessageTable.EXPIRES_IN, updateMessage.expirationTimerChange.expiresInMs)
|
||||
put(MessageTable.EXPIRES_IN, expirationTimerChange.expiresInMs)
|
||||
}
|
||||
updateMessage.profileChange != null -> {
|
||||
profileChange != null -> {
|
||||
typeFlags = MessageTypes.PROFILE_CHANGE_TYPE
|
||||
val profileChangeDetails = ProfileChangeDetails(profileNameChange = ProfileChangeDetails.StringChange(previous = updateMessage.profileChange.previousName, newValue = updateMessage.profileChange.newName))
|
||||
val profileChangeDetails = ProfileChangeDetails(profileNameChange = ProfileChangeDetails.StringChange(previous = profileChange.previousName, newValue = profileChange.newName))
|
||||
val messageExtras = MessageExtras(profileChangeDetails = profileChangeDetails).encode()
|
||||
put(MessageTable.MESSAGE_EXTRAS, messageExtras)
|
||||
}
|
||||
updateMessage.learnedProfileChange != null -> {
|
||||
learnedProfileChange != null -> {
|
||||
typeFlags = MessageTypes.PROFILE_CHANGE_TYPE
|
||||
val profileChangeDetails = ProfileChangeDetails(learnedProfileName = ProfileChangeDetails.LearnedProfileName(e164 = updateMessage.learnedProfileChange.e164?.toString(), username = updateMessage.learnedProfileChange.username))
|
||||
val profileChangeDetails = ProfileChangeDetails(learnedProfileName = ProfileChangeDetails.LearnedProfileName(e164 = learnedProfileChange.e164?.toString(), username = learnedProfileChange.username))
|
||||
val messageExtras = MessageExtras(profileChangeDetails = profileChangeDetails).encode()
|
||||
put(MessageTable.MESSAGE_EXTRAS, messageExtras)
|
||||
}
|
||||
updateMessage.pollTerminate != null -> {
|
||||
pollTerminate != null -> {
|
||||
typeFlags = MessageTypes.SPECIAL_TYPE_POLL_TERMINATE or (getAsLong(MessageTable.TYPE) and MessageTypes.BASE_TYPE_MASK.inv())
|
||||
}
|
||||
updateMessage.pinMessage != null -> {
|
||||
pinMessage != null -> {
|
||||
typeFlags = MessageTypes.SPECIAL_TYPE_PINNED_MESSAGE or (getAsLong(MessageTable.TYPE) and MessageTypes.BASE_TYPE_MASK.inv())
|
||||
}
|
||||
updateMessage.sessionSwitchover != null -> {
|
||||
sessionSwitchover != null -> {
|
||||
typeFlags = MessageTypes.SESSION_SWITCHOVER_TYPE or (getAsLong(MessageTable.TYPE) and MessageTypes.BASE_TYPE_MASK.inv())
|
||||
val sessionSwitchoverDetails = SessionSwitchoverEvent(e164 = updateMessage.sessionSwitchover.e164.toString()).encode()
|
||||
val sessionSwitchoverDetails = SessionSwitchoverEvent(e164 = sessionSwitchover.e164.toString()).encode()
|
||||
put(MessageTable.BODY, Base64.encodeWithPadding(sessionSwitchoverDetails))
|
||||
}
|
||||
updateMessage.threadMerge != null -> {
|
||||
threadMerge != null -> {
|
||||
typeFlags = MessageTypes.THREAD_MERGE_TYPE or (getAsLong(MessageTable.TYPE) and MessageTypes.BASE_TYPE_MASK.inv())
|
||||
val threadMergeDetails = ThreadMergeEvent(previousE164 = updateMessage.threadMerge.previousE164.toString()).encode()
|
||||
val threadMergeDetails = ThreadMergeEvent(previousE164 = threadMerge.previousE164.toString()).encode()
|
||||
put(MessageTable.BODY, Base64.encodeWithPadding(threadMergeDetails))
|
||||
}
|
||||
updateMessage.individualCall != null -> {
|
||||
if (updateMessage.individualCall.state == IndividualCall.State.MISSED || updateMessage.individualCall.state == IndividualCall.State.MISSED_NOTIFICATION_PROFILE) {
|
||||
typeFlags = if (updateMessage.individualCall.type == IndividualCall.Type.AUDIO_CALL) {
|
||||
individualCall != null -> {
|
||||
if (individualCall.state == IndividualCall.State.MISSED || individualCall.state == IndividualCall.State.MISSED_NOTIFICATION_PROFILE) {
|
||||
typeFlags = if (individualCall.type == IndividualCall.Type.AUDIO_CALL) {
|
||||
MessageTypes.MISSED_AUDIO_CALL_TYPE
|
||||
} else {
|
||||
MessageTypes.MISSED_VIDEO_CALL_TYPE
|
||||
}
|
||||
} else {
|
||||
typeFlags = if (updateMessage.individualCall.direction == IndividualCall.Direction.OUTGOING) {
|
||||
if (updateMessage.individualCall.type == IndividualCall.Type.AUDIO_CALL) {
|
||||
typeFlags = if (individualCall.direction == IndividualCall.Direction.OUTGOING) {
|
||||
if (individualCall.type == IndividualCall.Type.AUDIO_CALL) {
|
||||
MessageTypes.OUTGOING_AUDIO_CALL_TYPE
|
||||
} else {
|
||||
MessageTypes.OUTGOING_VIDEO_CALL_TYPE
|
||||
}
|
||||
} else {
|
||||
if (updateMessage.individualCall.type == IndividualCall.Type.AUDIO_CALL) {
|
||||
if (individualCall.type == IndividualCall.Type.AUDIO_CALL) {
|
||||
MessageTypes.INCOMING_AUDIO_CALL_TYPE
|
||||
} else {
|
||||
MessageTypes.INCOMING_VIDEO_CALL_TYPE
|
||||
@@ -925,28 +959,24 @@ class ChatItemArchiveImporter(
|
||||
}
|
||||
this.put(MessageTable.READ, 1)
|
||||
}
|
||||
updateMessage.groupCall != null -> {
|
||||
val startedCallRecipientId = if (updateMessage.groupCall.startedCallRecipientId != null) {
|
||||
importState.remoteToLocalRecipientId[updateMessage.groupCall.startedCallRecipientId]
|
||||
} else {
|
||||
null
|
||||
}
|
||||
groupCall != null -> {
|
||||
val startedCallRecipientId = groupCall.startedCallRecipientId?.let { importState.remoteToLocalRecipientId[it] }
|
||||
val startedCall = if (startedCallRecipientId != null) {
|
||||
recipients.getRecord(startedCallRecipientId).aci
|
||||
} else {
|
||||
null
|
||||
}
|
||||
this.put(MessageTable.BODY, GroupCallUpdateDetailsUtil.createBodyFromBackup(updateMessage.groupCall, startedCall))
|
||||
this.put(MessageTable.READ, updateMessage.groupCall.read.toInt())
|
||||
this.put(MessageTable.BODY, GroupCallUpdateDetailsUtil.createBodyFromBackup(groupCall, startedCall))
|
||||
this.put(MessageTable.READ, groupCall.read.toInt())
|
||||
typeFlags = MessageTypes.GROUP_CALL_TYPE
|
||||
}
|
||||
updateMessage.groupChange != null -> {
|
||||
groupChange != null -> {
|
||||
put(MessageTable.BODY, "")
|
||||
put(
|
||||
MessageTable.MESSAGE_EXTRAS,
|
||||
MessageExtras(
|
||||
gv2UpdateDescription =
|
||||
GV2UpdateDescription(groupChangeUpdate = updateMessage.groupChange)
|
||||
GV2UpdateDescription(groupChangeUpdate = groupChange)
|
||||
).encode()
|
||||
)
|
||||
typeFlags = getAsLong(MessageTable.TYPE) or MessageTypes.GROUP_V2_BIT or MessageTypes.GROUP_UPDATE_BIT
|
||||
@@ -962,18 +992,18 @@ class ChatItemArchiveImporter(
|
||||
*/
|
||||
private fun ContentValues.addPaymentNotification(chatItem: ChatItem, chatRecipientId: RecipientId) {
|
||||
val paymentNotification = chatItem.paymentNotification!!
|
||||
if (chatItem.paymentNotification.amountMob.isNullOrEmpty()) {
|
||||
if (paymentNotification.amountMob.isNullOrEmpty()) {
|
||||
this.addPaymentTombstoneNoAmount()
|
||||
return
|
||||
}
|
||||
val amount = paymentNotification.amountMob?.tryParseMoney() ?: return this.addPaymentTombstoneNoAmount()
|
||||
val fee = paymentNotification.feeMob?.tryParseMoney() ?: return this.addPaymentTombstoneNoAmount()
|
||||
|
||||
if (chatItem.paymentNotification.transactionDetails?.failedTransaction != null) {
|
||||
if (paymentNotification.transactionDetails?.failedTransaction != null) {
|
||||
this.addFailedPaymentNotification(chatItem, amount, fee, chatRecipientId)
|
||||
return
|
||||
}
|
||||
this.addPaymentTombstoneNoMetadata(chatItem.paymentNotification)
|
||||
this.addPaymentTombstoneNoMetadata(paymentNotification)
|
||||
}
|
||||
|
||||
private fun PaymentNotification.TransactionDetails.MobileCoinTxoIdentification.toLocal(): PaymentMetaData {
|
||||
@@ -1062,13 +1092,15 @@ class ChatItemArchiveImporter(
|
||||
put(MessageTable.QUOTE_ID, MessageTable.QUOTE_TARGET_MISSING_ID)
|
||||
put(MessageTable.QUOTE_AUTHOR, toRecipientId.serialize())
|
||||
|
||||
if (directStoryReply.emoji != null) {
|
||||
put(MessageTable.BODY, directStoryReply.emoji)
|
||||
val emoji = directStoryReply.emoji
|
||||
if (emoji != null) {
|
||||
put(MessageTable.BODY, emoji)
|
||||
}
|
||||
|
||||
if (directStoryReply.textReply != null) {
|
||||
put(MessageTable.BODY, directStoryReply.textReply.text?.body)
|
||||
put(MessageTable.MESSAGE_RANGES, directStoryReply.textReply.text?.bodyRanges?.toLocalBodyRanges()?.encode())
|
||||
val textReply = directStoryReply.textReply
|
||||
if (textReply != null) {
|
||||
put(MessageTable.BODY, textReply.text?.body)
|
||||
put(MessageTable.MESSAGE_RANGES, textReply.text?.bodyRanges?.toLocalBodyRanges()?.encode())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1126,11 +1158,9 @@ class ChatItemArchiveImporter(
|
||||
}
|
||||
|
||||
private fun ContentValues.addNetworkFailures(chatItem: ChatItem, importState: ImportState) {
|
||||
if (chatItem.outgoing == null) {
|
||||
return
|
||||
}
|
||||
val outgoing = chatItem.outgoing ?: return
|
||||
|
||||
val networkFailures = chatItem.outgoing.sendStatus
|
||||
val networkFailures = outgoing.sendStatus
|
||||
.filter { status -> status.failed?.reason == SendStatus.Failed.FailureReason.NETWORK }
|
||||
.mapNotNull { status -> importState.remoteToLocalRecipientId[status.recipientId] }
|
||||
.map { recipientId -> NetworkFailure(recipientId) }
|
||||
@@ -1142,11 +1172,9 @@ class ChatItemArchiveImporter(
|
||||
}
|
||||
|
||||
private fun ContentValues.addIdentityKeyMismatches(chatItem: ChatItem, importState: ImportState) {
|
||||
if (chatItem.outgoing == null) {
|
||||
return
|
||||
}
|
||||
val outgoing = chatItem.outgoing ?: return
|
||||
|
||||
val mismatches = chatItem.outgoing.sendStatus
|
||||
val mismatches = outgoing.sendStatus
|
||||
.filter { status -> status.failed?.reason == SendStatus.Failed.FailureReason.IDENTITY_KEY_MISMATCH }
|
||||
.mapNotNull { status -> importState.remoteToLocalRecipientId[status.recipientId] }
|
||||
.map { recipientId -> IdentityKeyMismatch(recipientId, null) } // TODO We probably want the actual identity key in this status situation?
|
||||
@@ -1166,8 +1194,8 @@ class ChatItemArchiveImporter(
|
||||
ranges = this.filter { includeMentions || it.mentionAci == null }.map { bodyRange ->
|
||||
BodyRangeList.BodyRange(
|
||||
mentionUuid = bodyRange.mentionAci?.let { UuidUtil.fromByteString(it) }?.toString(),
|
||||
style = bodyRange.style?.let {
|
||||
when (bodyRange.style) {
|
||||
style = bodyRange.style?.let { style ->
|
||||
when (style) {
|
||||
BodyRange.Style.BOLD -> BodyRangeList.BodyRange.Style.BOLD
|
||||
BodyRange.Style.ITALIC -> BodyRangeList.BodyRange.Style.ITALIC
|
||||
BodyRange.Style.MONOSPACE -> BodyRangeList.BodyRange.Style.MONOSPACE
|
||||
@@ -1217,13 +1245,11 @@ class ChatItemArchiveImporter(
|
||||
return@mapNotNull thumbnail
|
||||
}
|
||||
|
||||
if (attachment.contentType == null) {
|
||||
return@mapNotNull null
|
||||
}
|
||||
val contentType = attachment.contentType ?: return@mapNotNull null
|
||||
|
||||
return@mapNotNull PointerAttachment.forPointer(
|
||||
quotedAttachment = DataMessage.Quote.QuotedAttachment(
|
||||
contentType = attachment.contentType,
|
||||
contentType = contentType,
|
||||
fileName = attachment.fileName,
|
||||
thumbnail = null
|
||||
)
|
||||
@@ -1259,7 +1285,8 @@ class ChatItemArchiveImporter(
|
||||
}
|
||||
|
||||
private fun MessageAttachment.toLocalAttachment(quote: Boolean = false, quoteTargetContentType: String? = null, contentType: String? = pointer?.contentType): Attachment? {
|
||||
return pointer?.toLocalAttachment(
|
||||
val pointer = this.pointer ?: return null
|
||||
return pointer.toLocalAttachment(
|
||||
voiceNote = flag == MessageAttachment.Flag.VOICE_MESSAGE,
|
||||
borderless = flag == MessageAttachment.Flag.BORDERLESS,
|
||||
gif = flag == MessageAttachment.Flag.GIF,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.thoughtcrime.securesms.backup.v2.importer
|
||||
|
||||
import androidx.core.content.contentValuesOf
|
||||
import org.signal.archive.proto.Contact
|
||||
import org.signal.core.models.ServiceId.ACI
|
||||
import org.signal.core.models.ServiceId.PNI
|
||||
import org.signal.core.util.Base64
|
||||
@@ -14,7 +15,6 @@ import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.toInt
|
||||
import org.signal.core.util.update
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportSkips
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Contact
|
||||
import org.thoughtcrime.securesms.backup.v2.util.toLocal
|
||||
import org.thoughtcrime.securesms.database.IdentityTable
|
||||
import org.thoughtcrime.securesms.database.RecipientTable
|
||||
@@ -70,11 +70,12 @@ object ContactArchiveImporter {
|
||||
RecipientTable.KEY_TRANSPARENCY_DATA to contact.keyTransparencyData?.toByteArray()
|
||||
)
|
||||
|
||||
val notRegistered = contact.notRegistered
|
||||
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)
|
||||
} else if (notRegistered != null) {
|
||||
values.put(RecipientTable.UNREGISTERED_TIMESTAMP, notRegistered.unregisteredTimestamp)
|
||||
values.put(RecipientTable.REGISTERED, RecipientTable.RegisteredState.NOT_REGISTERED.id)
|
||||
}
|
||||
|
||||
@@ -84,12 +85,13 @@ object ContactArchiveImporter {
|
||||
.where("${RecipientTable.ID} = ?", id)
|
||||
.run()
|
||||
|
||||
if (contact.identityKey != null && (aci != null || pni != null)) {
|
||||
val identityKey = contact.identityKey
|
||||
if (identityKey != null && (aci != null || pni != null)) {
|
||||
SignalDatabase.writableDatabase
|
||||
.insertInto(IdentityTable.TABLE_NAME)
|
||||
.values(
|
||||
IdentityTable.ADDRESS to (aci ?: pni).toString(),
|
||||
IdentityTable.IDENTITY_KEY to Base64.encodeWithPadding(contact.identityKey.toByteArray()),
|
||||
IdentityTable.IDENTITY_KEY to Base64.encodeWithPadding(identityKey.toByteArray()),
|
||||
IdentityTable.VERIFIED to contact.identityState.toLocal().toInt()
|
||||
)
|
||||
.run(SQLiteDatabase.CONFLICT_REPLACE)
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.importer
|
||||
|
||||
import org.signal.archive.proto.DistributionList
|
||||
import org.signal.archive.proto.DistributionListItem
|
||||
import org.signal.core.util.UuidUtil
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportState
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.DistributionList
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.DistributionListItem
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListPrivacyMode
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
@@ -23,13 +23,14 @@ object DistributionListArchiveImporter {
|
||||
private val TAG = Log.tag(DistributionListArchiveImporter.javaClass)
|
||||
|
||||
fun import(dlistItem: DistributionListItem, importState: ImportState): RecipientId? {
|
||||
if (dlistItem.deletionTimestamp != null && dlistItem.deletionTimestamp > 0) {
|
||||
val deletionTimestamp = dlistItem.deletionTimestamp
|
||||
if (deletionTimestamp != null && deletionTimestamp > 0) {
|
||||
val dlistId = SignalDatabase.distributionLists.createList(
|
||||
name = "",
|
||||
members = emptyList(),
|
||||
distributionId = DistributionId.from(UuidUtil.fromByteString(dlistItem.distributionId)),
|
||||
allowsReplies = false,
|
||||
deletionTimestamp = dlistItem.deletionTimestamp,
|
||||
deletionTimestamp = deletionTimestamp,
|
||||
storageId = null,
|
||||
privacyMode = DistributionListPrivacyMode.ONLY_WITH
|
||||
)!!
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.thoughtcrime.securesms.backup.v2.importer
|
||||
|
||||
import android.content.ContentValues
|
||||
import org.signal.archive.proto.Group
|
||||
import org.signal.core.models.ServiceId
|
||||
import org.signal.core.util.Base64
|
||||
import org.signal.core.util.toInt
|
||||
@@ -21,7 +22,6 @@ import org.signal.storageservice.storage.protos.groups.local.DecryptedRequesting
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedTimer
|
||||
import org.signal.storageservice.storage.protos.groups.local.EnabledState
|
||||
import org.thoughtcrime.securesms.backup.v2.ArchiveGroup
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Group
|
||||
import org.thoughtcrime.securesms.backup.v2.util.toLocal
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColorHash
|
||||
import org.thoughtcrime.securesms.database.GroupTable
|
||||
@@ -45,10 +45,11 @@ object GroupArchiveImporter {
|
||||
val groupId = GroupId.v2(masterKey)
|
||||
|
||||
val operations = AppDependencies.groupsV2Operations.forGroup(GroupSecretParams.deriveFromMasterKey(masterKey))
|
||||
val decryptedState = if (group.snapshot == null) {
|
||||
val snapshot = group.snapshot
|
||||
val decryptedState = if (snapshot == null) {
|
||||
DecryptedGroup(revision = GroupsV2StateProcessor.RESTORE_PLACEHOLDER_REVISION)
|
||||
} else {
|
||||
group.snapshot.toLocal(operations)
|
||||
snapshot.toLocal(operations)
|
||||
}
|
||||
|
||||
val values = ContentValues().apply {
|
||||
@@ -84,12 +85,13 @@ private fun Group.StorySendMode.toLocal(): GroupTable.ShowAsStoryState {
|
||||
}
|
||||
|
||||
private fun Group.MemberPendingProfileKey.toLocal(operations: GroupsV2Operations.GroupOperations): DecryptedPendingMember {
|
||||
val m = member!!
|
||||
return DecryptedPendingMember(
|
||||
serviceIdBytes = member!!.userId,
|
||||
role = member.role.toLocal(),
|
||||
serviceIdBytes = m.userId,
|
||||
role = m.role.toLocal(),
|
||||
addedByAci = addedByUserId,
|
||||
timestamp = timestamp,
|
||||
serviceIdCipherText = operations.encryptServiceId(ServiceId.Companion.parseOrNull(member.userId))
|
||||
serviceIdCipherText = operations.encryptServiceId(ServiceId.Companion.parseOrNull(m.userId))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.signal.archive.local.ArchivedFilesReader
|
||||
import org.signal.core.models.backup.MediaName
|
||||
import org.signal.core.util.Stopwatch
|
||||
import org.signal.core.util.androidx.DocumentFileInfo
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
package org.thoughtcrime.securesms.backup.v2.local
|
||||
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.signal.archive.local.ArchivedFilesWriter
|
||||
import org.signal.archive.local.proto.FilesFrame
|
||||
import org.signal.archive.local.proto.Metadata
|
||||
import org.signal.archive.stream.EncryptedBackupReader
|
||||
import org.signal.core.models.backup.BackupId
|
||||
import org.signal.core.models.backup.MediaName
|
||||
import org.signal.core.models.backup.MessageBackupKey
|
||||
@@ -16,9 +20,6 @@ import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.readFully
|
||||
import org.thoughtcrime.securesms.attachments.AttachmentId
|
||||
import org.thoughtcrime.securesms.backup.v2.BackupRepository
|
||||
import org.thoughtcrime.securesms.backup.v2.local.proto.FilesFrame
|
||||
import org.thoughtcrime.securesms.backup.v2.local.proto.Metadata
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.EncryptedBackupReader
|
||||
import org.thoughtcrime.securesms.database.AttachmentTable
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.keyvalue.protos.LocalBackupCreationProgress
|
||||
@@ -166,12 +167,13 @@ object LocalArchiver {
|
||||
return RestoreResult.failure(RestoreFailure.VersionMismatch(metadata.version, VERSION))
|
||||
}
|
||||
|
||||
if (metadata.backupId == null) {
|
||||
val encryptedBackupId = metadata.backupId
|
||||
if (encryptedBackupId == null) {
|
||||
Log.w(TAG, "Local backup metadata missing encrypted backup id")
|
||||
return RestoreResult.failure(RestoreFailure.BackupIdMissing)
|
||||
}
|
||||
|
||||
val backupId = decryptBackupId(metadata.backupId, messageBackupKey)
|
||||
val backupId = decryptBackupId(encryptedBackupId, messageBackupKey)
|
||||
|
||||
val mainStreamLength = snapshotFileSystem.mainLength() ?: return ArchiveResult.failure(RestoreFailure.MainStream)
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@ package org.thoughtcrime.securesms.backup.v2.processor
|
||||
import android.content.Context
|
||||
import okio.ByteString.Companion.EMPTY
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.signal.archive.proto.AccountData
|
||||
import org.signal.archive.proto.ChatStyle
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.archive.stream.BackupFrameEmitter
|
||||
import org.signal.core.util.UuidUtil
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.toByteArray
|
||||
@@ -18,10 +22,6 @@ import org.thoughtcrime.securesms.backup.v2.ImportState
|
||||
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
|
||||
import org.thoughtcrime.securesms.backup.v2.database.restoreSelfFromBackup
|
||||
import org.thoughtcrime.securesms.backup.v2.database.restoreWallpaperAttachment
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.AccountData
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ChatStyle
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.BackupFrameEmitter
|
||||
import org.thoughtcrime.securesms.backup.v2.util.ChatStyleConverter
|
||||
import org.thoughtcrime.securesms.backup.v2.util.isValid
|
||||
import org.thoughtcrime.securesms.backup.v2.util.isValidUsername
|
||||
@@ -178,10 +178,11 @@ object AccountDataArchiveProcessor {
|
||||
importSettings(context, settings, importState)
|
||||
}
|
||||
|
||||
if (accountData.androidSpecificSettings != null) {
|
||||
SignalStore.settings.isPreferSystemEmoji = accountData.androidSpecificSettings.useSystemEmoji
|
||||
TextSecurePreferences.setScreenSecurityEnabled(context, accountData.androidSpecificSettings.screenshotSecurity)
|
||||
SignalStore.settings.useCompactNavigationBar = accountData.androidSpecificSettings.navigationBarSize.toLocalNavigationBarSize()
|
||||
val androidSpecificSettings = accountData.androidSpecificSettings
|
||||
if (androidSpecificSettings != null) {
|
||||
SignalStore.settings.isPreferSystemEmoji = androidSpecificSettings.useSystemEmoji
|
||||
TextSecurePreferences.setScreenSecurityEnabled(context, androidSpecificSettings.screenshotSecurity)
|
||||
SignalStore.settings.useCompactNavigationBar = androidSpecificSettings.navigationBarSize.toLocalNavigationBarSize()
|
||||
} else if (Environment.IS_INSTRUMENTATION) {
|
||||
SignalStore.backup.importedEmptyAndroidSettings = true
|
||||
}
|
||||
@@ -190,16 +191,17 @@ object AccountDataArchiveProcessor {
|
||||
SignalDatabase.recipients.setAbout(selfId, accountData.bioText.takeIf { it.isNotBlank() }, accountData.bioEmoji.takeIf { it.isNotBlank() })
|
||||
}
|
||||
|
||||
if (accountData.donationSubscriberData != null) {
|
||||
if (accountData.donationSubscriberData.subscriberId.size > 0) {
|
||||
val remoteSubscriberId = SubscriberId.fromBytes(accountData.donationSubscriberData.subscriberId.toByteArray())
|
||||
val donationSubscriberData = accountData.donationSubscriberData
|
||||
if (donationSubscriberData != null) {
|
||||
if (donationSubscriberData.subscriberId.size > 0) {
|
||||
val remoteSubscriberId = SubscriberId.fromBytes(donationSubscriberData.subscriberId.toByteArray())
|
||||
val localSubscriber = InAppPaymentsRepository.getSubscriber(InAppPaymentSubscriberRecord.Type.DONATION)
|
||||
|
||||
val subscriber = InAppPaymentSubscriberRecord(
|
||||
subscriberId = remoteSubscriberId,
|
||||
currency = Currency.getInstance(accountData.donationSubscriberData.currencyCode),
|
||||
currency = Currency.getInstance(donationSubscriberData.currencyCode),
|
||||
type = InAppPaymentSubscriberRecord.Type.DONATION,
|
||||
requiresCancel = localSubscriber?.requiresCancel ?: accountData.donationSubscriberData.manuallyCancelled,
|
||||
requiresCancel = localSubscriber?.requiresCancel ?: donationSubscriberData.manuallyCancelled,
|
||||
paymentMethodType = InAppPaymentsRepository.getLatestPaymentMethodType(InAppPaymentSubscriberRecord.Type.DONATION),
|
||||
iapSubscriptionId = null
|
||||
)
|
||||
@@ -207,25 +209,27 @@ object AccountDataArchiveProcessor {
|
||||
InAppPaymentsRepository.setSubscriber(subscriber)
|
||||
}
|
||||
|
||||
if (accountData.donationSubscriberData.manuallyCancelled) {
|
||||
if (donationSubscriberData.manuallyCancelled) {
|
||||
SignalStore.inAppPayments.updateLocalStateForManualCancellation(InAppPaymentSubscriberRecord.Type.DONATION)
|
||||
}
|
||||
}
|
||||
|
||||
if (accountData.backupsSubscriberData != null && accountData.backupsSubscriberData.subscriberId.size > 0 && (accountData.backupsSubscriberData.purchaseToken != null || accountData.backupsSubscriberData.originalTransactionId != null)) {
|
||||
val remoteSubscriberId = SubscriberId.fromBytes(accountData.backupsSubscriberData.subscriberId.toByteArray())
|
||||
val backupsSubscriberData = accountData.backupsSubscriberData
|
||||
if (backupsSubscriberData != null && backupsSubscriberData.subscriberId.size > 0 && (backupsSubscriberData.purchaseToken != null || backupsSubscriberData.originalTransactionId != null)) {
|
||||
val remoteSubscriberId = SubscriberId.fromBytes(backupsSubscriberData.subscriberId.toByteArray())
|
||||
val localSubscriber = InAppPaymentsRepository.getSubscriber(InAppPaymentSubscriberRecord.Type.BACKUP)
|
||||
|
||||
val purchaseToken = backupsSubscriberData.purchaseToken
|
||||
val subscriber = InAppPaymentSubscriberRecord(
|
||||
subscriberId = remoteSubscriberId,
|
||||
currency = localSubscriber?.currency,
|
||||
type = InAppPaymentSubscriberRecord.Type.BACKUP,
|
||||
requiresCancel = localSubscriber?.requiresCancel ?: false,
|
||||
paymentMethodType = InAppPaymentData.PaymentMethodType.UNKNOWN,
|
||||
iapSubscriptionId = if (accountData.backupsSubscriberData.purchaseToken != null) {
|
||||
GooglePlayBillingPurchaseToken(accountData.backupsSubscriberData.purchaseToken)
|
||||
iapSubscriptionId = if (purchaseToken != null) {
|
||||
GooglePlayBillingPurchaseToken(purchaseToken)
|
||||
} else {
|
||||
AppleIAPOriginalTransactionId(accountData.backupsSubscriberData.originalTransactionId!!)
|
||||
AppleIAPOriginalTransactionId(backupsSubscriberData.originalTransactionId!!)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -236,12 +240,13 @@ object AccountDataArchiveProcessor {
|
||||
AppDependencies.jobManager.add(RetrieveProfileAvatarJob(Recipient.self().fresh(), accountData.avatarUrlPath))
|
||||
}
|
||||
|
||||
if (accountData.usernameLink != null) {
|
||||
val usernameLink = accountData.usernameLink
|
||||
if (usernameLink != null) {
|
||||
SignalStore.account.usernameLink = UsernameLinkComponents(
|
||||
accountData.usernameLink.entropy.toByteArray(),
|
||||
UuidUtil.parseOrThrow(accountData.usernameLink.serverId.toByteArray())
|
||||
usernameLink.entropy.toByteArray(),
|
||||
UuidUtil.parseOrThrow(usernameLink.serverId.toByteArray())
|
||||
)
|
||||
SignalStore.misc.usernameQrCodeColorScheme = accountData.usernameLink.color.toLocalUsernameColor()
|
||||
SignalStore.misc.usernameQrCodeColorScheme = usernameLink.color.toLocalUsernameColor()
|
||||
} else {
|
||||
SignalStore.account.usernameLink = null
|
||||
}
|
||||
@@ -278,9 +283,10 @@ object AccountDataArchiveProcessor {
|
||||
SignalStore.settings.setCallDataMode(settings.callsUseLessDataSetting.toLocalCallDataMode())
|
||||
SignalStore.settings.automaticVerificationEnabled = settings.allowAutomaticKeyVerification
|
||||
|
||||
if (settings.autoDownloadSettings != null) {
|
||||
val mobileAndWifiDownloadSet = settings.autoDownloadSettings.toLocalAutoDownloadSet(AccountData.AutoDownloadSettings.AutoDownloadOption.WIFI_AND_CELLULAR)
|
||||
val wifiDownloadSet = mobileAndWifiDownloadSet + settings.autoDownloadSettings.toLocalAutoDownloadSet(AccountData.AutoDownloadSettings.AutoDownloadOption.WIFI)
|
||||
val autoDownloadSettings = settings.autoDownloadSettings
|
||||
if (autoDownloadSettings != null) {
|
||||
val mobileAndWifiDownloadSet = autoDownloadSettings.toLocalAutoDownloadSet(AccountData.AutoDownloadSettings.AutoDownloadOption.WIFI_AND_CELLULAR)
|
||||
val wifiDownloadSet = mobileAndWifiDownloadSet + autoDownloadSettings.toLocalAutoDownloadSet(AccountData.AutoDownloadSettings.AutoDownloadOption.WIFI)
|
||||
|
||||
TextSecurePreferences.getSharedPreferences(context).edit().apply {
|
||||
putStringSet(TextSecurePreferences.MEDIA_DOWNLOAD_MOBILE_PREF, mobileAndWifiDownloadSet)
|
||||
@@ -289,28 +295,32 @@ object AccountDataArchiveProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.screenLockTimeoutMinutes != null) {
|
||||
SignalStore.settings.screenLockTimeout = settings.screenLockTimeoutMinutes.minutes.inWholeSeconds
|
||||
val screenLockTimeoutMinutes = settings.screenLockTimeoutMinutes
|
||||
if (screenLockTimeoutMinutes != null) {
|
||||
SignalStore.settings.screenLockTimeout = screenLockTimeoutMinutes.minutes.inWholeSeconds
|
||||
}
|
||||
|
||||
if (settings.pinReminders != null) {
|
||||
SignalStore.pin.setPinRemindersEnabled(settings.pinReminders)
|
||||
val pinReminders = settings.pinReminders
|
||||
if (pinReminders != null) {
|
||||
SignalStore.pin.setPinRemindersEnabled(pinReminders)
|
||||
}
|
||||
|
||||
settings.customChatColors
|
||||
.mapNotNull { chatColor ->
|
||||
val id = ChatColors.Id.forLongValue(chatColor.id)
|
||||
val solidColor = chatColor.solid
|
||||
val gradientColor = chatColor.gradient
|
||||
when {
|
||||
chatColor.solid != null -> {
|
||||
ChatColors.forColor(id, chatColor.solid)
|
||||
solidColor != null -> {
|
||||
ChatColors.forColor(id, solidColor)
|
||||
}
|
||||
chatColor.gradient != null -> {
|
||||
gradientColor != null -> {
|
||||
ChatColors.forGradient(
|
||||
id,
|
||||
ChatColors.LinearGradient(
|
||||
degrees = chatColor.gradient.angle.toFloat(),
|
||||
colors = chatColor.gradient.colors.toIntArray(),
|
||||
positions = chatColor.gradient.positions.toFloatArray()
|
||||
degrees = gradientColor.angle.toFloat(),
|
||||
colors = gradientColor.colors.toIntArray(),
|
||||
positions = gradientColor.positions.toFloatArray()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -323,17 +333,18 @@ object AccountDataArchiveProcessor {
|
||||
importState.remoteToLocalColorId[chatColor.id.longValue] = saved.id.longValue
|
||||
}
|
||||
|
||||
if (settings.defaultChatStyle != null) {
|
||||
val chatColors = settings.defaultChatStyle.toLocal(importState)
|
||||
val defaultChatStyle = settings.defaultChatStyle
|
||||
if (defaultChatStyle != null) {
|
||||
val chatColors = defaultChatStyle.toLocal(importState)
|
||||
SignalStore.chatColors.chatColors = chatColors
|
||||
|
||||
val wallpaperAttachmentId: AttachmentId? = settings.defaultChatStyle.wallpaperPhoto?.let { filePointer ->
|
||||
val wallpaperAttachmentId: AttachmentId? = defaultChatStyle.wallpaperPhoto?.let { filePointer ->
|
||||
filePointer.toLocalAttachment()?.let {
|
||||
SignalDatabase.attachments.restoreWallpaperAttachment(it)
|
||||
}
|
||||
}
|
||||
|
||||
SignalStore.wallpaper.wallpaper = settings.defaultChatStyle.parseChatWallpaper(wallpaperAttachmentId)
|
||||
SignalStore.wallpaper.wallpaper = defaultChatStyle.parseChatWallpaper(wallpaperAttachmentId)
|
||||
} else {
|
||||
SignalStore.chatColors.chatColors = null
|
||||
SignalStore.wallpaper.wallpaper = null
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.processor
|
||||
|
||||
import org.signal.archive.proto.AdHocCall
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.archive.stream.BackupFrameEmitter
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.backup.v2.ExportSkips
|
||||
import org.thoughtcrime.securesms.backup.v2.ExportState
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportState
|
||||
import org.thoughtcrime.securesms.backup.v2.database.getAdhocCallsForBackup
|
||||
import org.thoughtcrime.securesms.backup.v2.importer.AdHodCallArchiveImporter
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.AdHocCall
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.BackupFrameEmitter
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.processor
|
||||
|
||||
import org.signal.archive.proto.Chat
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.archive.stream.BackupFrameEmitter
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.backup.v2.ExportState
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportSkips
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportState
|
||||
import org.thoughtcrime.securesms.backup.v2.database.getThreadsForBackup
|
||||
import org.thoughtcrime.securesms.backup.v2.importer.ChatArchiveImporter
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Chat
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.BackupFrameEmitter
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@ package org.thoughtcrime.securesms.backup.v2.processor
|
||||
|
||||
import androidx.core.content.contentValuesOf
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.signal.archive.proto.ChatFolder
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.archive.stream.BackupFrameEmitter
|
||||
import org.signal.core.util.Base64
|
||||
import org.signal.core.util.SqlUtil
|
||||
import org.signal.core.util.UuidUtil
|
||||
@@ -15,16 +18,13 @@ import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.backup.v2.ExportState
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportSkips
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportState
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ChatFolder
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.BackupFrameEmitter
|
||||
import org.thoughtcrime.securesms.components.settings.app.chats.folders.ChatFolderRecord
|
||||
import org.thoughtcrime.securesms.database.ChatFolderTables.ChatFolderMembershipTable
|
||||
import org.thoughtcrime.securesms.database.ChatFolderTables.ChatFolderTable
|
||||
import org.thoughtcrime.securesms.database.ChatFolderTables.MembershipType
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ChatFolder as ChatFolderProto
|
||||
import org.signal.archive.proto.ChatFolder as ChatFolderProto
|
||||
|
||||
/**
|
||||
* Handles exporting and importing [ChatFolderRecord]s.
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.processor
|
||||
|
||||
import org.signal.archive.proto.ChatItem
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.archive.stream.BackupFrameEmitter
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.backup.v2.ExportState
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportState
|
||||
import org.thoughtcrime.securesms.backup.v2.database.createChatItemInserter
|
||||
import org.thoughtcrime.securesms.backup.v2.database.getMessagesForBackup
|
||||
import org.thoughtcrime.securesms.backup.v2.importer.ChatItemArchiveImporter
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ChatItem
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.BackupFrameEmitter
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
package org.thoughtcrime.securesms.backup.v2.processor
|
||||
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.archive.stream.BackupFrameEmitter
|
||||
import org.signal.core.util.Base64
|
||||
import org.signal.core.util.UuidUtil
|
||||
import org.signal.core.util.insertInto
|
||||
@@ -14,8 +16,6 @@ import org.signal.core.util.toInt
|
||||
import org.thoughtcrime.securesms.backup.v2.ExportState
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportSkips
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportState
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.BackupFrameEmitter
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
|
||||
import org.thoughtcrime.securesms.database.NotificationProfileTables.NotificationProfileAllowedMembersTable
|
||||
import org.thoughtcrime.securesms.database.NotificationProfileTables.NotificationProfileScheduleTable
|
||||
@@ -26,7 +26,7 @@ import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper
|
||||
import java.time.DayOfWeek
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.NotificationProfile as NotificationProfileProto
|
||||
import org.signal.archive.proto.NotificationProfile as NotificationProfileProto
|
||||
|
||||
/**
|
||||
* Handles exporting and importing [NotificationProfile] models.
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.processor
|
||||
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.archive.proto.ReleaseNotes
|
||||
import org.signal.archive.stream.BackupFrameEmitter
|
||||
import org.signal.core.models.ServiceId
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.update
|
||||
@@ -22,9 +25,6 @@ import org.thoughtcrime.securesms.backup.v2.importer.CallLinkArchiveImporter
|
||||
import org.thoughtcrime.securesms.backup.v2.importer.ContactArchiveImporter
|
||||
import org.thoughtcrime.securesms.backup.v2.importer.DistributionListArchiveImporter
|
||||
import org.thoughtcrime.securesms.backup.v2.importer.GroupArchiveImporter
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ReleaseNotes
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.BackupFrameEmitter
|
||||
import org.thoughtcrime.securesms.backup.v2.util.toLocal
|
||||
import org.thoughtcrime.securesms.database.RecipientTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
@@ -110,16 +110,21 @@ object RecipientArchiveProcessor {
|
||||
}
|
||||
|
||||
fun import(recipient: ArchiveRecipient, importState: ImportState) {
|
||||
val recipientContact = recipient.contact
|
||||
val recipientGroup = recipient.group
|
||||
val recipientDistributionList = recipient.distributionList
|
||||
val recipientCallLink = recipient.callLink
|
||||
val recipientSelf = recipient.self
|
||||
val newId: RecipientId? = when {
|
||||
recipient.contact != null -> ContactArchiveImporter.import(recipient.contact)
|
||||
recipient.group != null -> GroupArchiveImporter.import(recipient.group)
|
||||
recipient.distributionList != null -> DistributionListArchiveImporter.import(recipient.distributionList, importState)
|
||||
recipientContact != null -> ContactArchiveImporter.import(recipientContact)
|
||||
recipientGroup != null -> GroupArchiveImporter.import(recipientGroup)
|
||||
recipientDistributionList != null -> DistributionListArchiveImporter.import(recipientDistributionList, importState)
|
||||
recipient.releaseNotes != null -> SignalDatabase.recipients.restoreReleaseNotes()
|
||||
recipient.callLink != null -> CallLinkArchiveImporter.import(recipient.callLink)
|
||||
recipient.self != null -> {
|
||||
recipientCallLink != null -> CallLinkArchiveImporter.import(recipientCallLink)
|
||||
recipientSelf != null -> {
|
||||
SignalDatabase.writableDatabase
|
||||
.update(RecipientTable.TABLE_NAME)
|
||||
.values(RecipientTable.AVATAR_COLOR to recipient.self.avatarColor?.toLocal()?.serialize())
|
||||
.values(RecipientTable.AVATAR_COLOR to recipientSelf.avatarColor?.toLocal()?.serialize())
|
||||
.where("${RecipientTable.ID} = ?", Recipient.self().id)
|
||||
.run()
|
||||
Recipient.self().id
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
package org.thoughtcrime.securesms.backup.v2.processor
|
||||
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.archive.proto.StickerPack
|
||||
import org.signal.archive.stream.BackupFrameEmitter
|
||||
import org.signal.core.util.Hex
|
||||
import org.signal.core.util.insertInto
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.backup.v2.ExportSkips
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.StickerPack
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.BackupFrameEmitter
|
||||
import org.thoughtcrime.securesms.database.SQLiteDatabase
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.StickerTable
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.backup.v2.util
|
||||
|
||||
import okio.ByteString
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.signal.archive.proto.FilePointer
|
||||
import org.signal.core.util.Base64
|
||||
import org.signal.core.util.UuidUtil
|
||||
import org.signal.core.util.isNotNullOrBlank
|
||||
@@ -22,7 +23,6 @@ import org.thoughtcrime.securesms.attachments.PointerAttachment
|
||||
import org.thoughtcrime.securesms.attachments.TombstoneAttachment
|
||||
import org.thoughtcrime.securesms.backup.v2.BackupMode
|
||||
import org.thoughtcrime.securesms.backup.v2.ExportState
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.FilePointer
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors
|
||||
import org.thoughtcrime.securesms.database.AttachmentTable
|
||||
@@ -30,7 +30,7 @@ import org.thoughtcrime.securesms.stickers.StickerLocator
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId
|
||||
import java.util.Optional
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.AvatarColor as RemoteAvatarColor
|
||||
import org.signal.archive.proto.AvatarColor as RemoteAvatarColor
|
||||
|
||||
/**
|
||||
* Converts a [FilePointer] to a local [Attachment] object for inserting into the database.
|
||||
@@ -47,11 +47,12 @@ fun FilePointer?.toLocalAttachment(
|
||||
quote: Boolean = false,
|
||||
quoteTargetContentType: String? = null
|
||||
): Attachment? {
|
||||
if (this == null || this.locatorInfo == null) return null
|
||||
if (this == null) return null
|
||||
val locatorInfo = this.locatorInfo ?: return null
|
||||
|
||||
val attachmentType = when {
|
||||
this.locatorInfo.plaintextHash != null -> AttachmentType.ARCHIVE
|
||||
this.locatorInfo.encryptedDigest != null && this.locatorInfo.transitCdnKey != null -> AttachmentType.TRANSIT
|
||||
locatorInfo.plaintextHash != null -> AttachmentType.ARCHIVE
|
||||
locatorInfo.encryptedDigest != null && locatorInfo.transitCdnKey != null -> AttachmentType.TRANSIT
|
||||
else -> AttachmentType.INVALID
|
||||
}
|
||||
|
||||
@@ -59,13 +60,13 @@ fun FilePointer?.toLocalAttachment(
|
||||
AttachmentType.ARCHIVE -> {
|
||||
ArchivedAttachment(
|
||||
contentType = contentType,
|
||||
size = this.locatorInfo.size.toLong(),
|
||||
cdn = this.locatorInfo.transitCdnNumber ?: Cdn.CDN_0.cdnNumber,
|
||||
uploadTimestamp = this.locatorInfo.transitTierUploadTimestamp ?: 0,
|
||||
key = this.locatorInfo.key.toByteArray(),
|
||||
cdnKey = this.locatorInfo.transitCdnKey?.nullIfBlank(),
|
||||
archiveCdn = this.locatorInfo.mediaTierCdnNumber,
|
||||
plaintextHash = this.locatorInfo.plaintextHash!!.toByteArray(),
|
||||
size = locatorInfo.size.toLong(),
|
||||
cdn = locatorInfo.transitCdnNumber ?: Cdn.CDN_0.cdnNumber,
|
||||
uploadTimestamp = locatorInfo.transitTierUploadTimestamp ?: 0,
|
||||
key = locatorInfo.key.toByteArray(),
|
||||
cdnKey = locatorInfo.transitCdnKey?.nullIfBlank(),
|
||||
archiveCdn = locatorInfo.mediaTierCdnNumber,
|
||||
plaintextHash = locatorInfo.plaintextHash!!.toByteArray(),
|
||||
incrementalMac = this.incrementalMac?.toByteArray(),
|
||||
incrementalMacChunkSize = this.incrementalMacChunkSize,
|
||||
width = this.width,
|
||||
@@ -80,20 +81,20 @@ fun FilePointer?.toLocalAttachment(
|
||||
quoteTargetContentType = quoteTargetContentType,
|
||||
uuid = UuidUtil.fromByteStringOrNull(uuid),
|
||||
fileName = fileName,
|
||||
localBackupKey = this.locatorInfo.localKey?.toByteArray()
|
||||
localBackupKey = locatorInfo.localKey?.toByteArray()
|
||||
)
|
||||
}
|
||||
AttachmentType.TRANSIT -> {
|
||||
val signalAttachmentPointer = SignalServiceAttachmentPointer(
|
||||
cdnNumber = this.locatorInfo.transitCdnNumber ?: Cdn.CDN_0.cdnNumber,
|
||||
cdnNumber = locatorInfo.transitCdnNumber ?: Cdn.CDN_0.cdnNumber,
|
||||
remoteId = SignalServiceAttachmentRemoteId.from(locatorInfo.transitCdnKey!!),
|
||||
contentType = contentType,
|
||||
key = this.locatorInfo.key.toByteArray(),
|
||||
key = locatorInfo.key.toByteArray(),
|
||||
size = Optional.ofNullable(locatorInfo.size),
|
||||
preview = Optional.empty(),
|
||||
width = this.width ?: 0,
|
||||
height = this.height ?: 0,
|
||||
digest = Optional.ofNullable(this.locatorInfo.encryptedDigest!!.toByteArray()),
|
||||
digest = Optional.ofNullable(locatorInfo.encryptedDigest!!.toByteArray()),
|
||||
incrementalDigest = Optional.ofNullable(this.incrementalMac?.toByteArray()),
|
||||
incrementalMacChunkSize = this.incrementalMacChunkSize ?: 0,
|
||||
fileName = Optional.ofNullable(fileName),
|
||||
@@ -102,7 +103,7 @@ fun FilePointer?.toLocalAttachment(
|
||||
isGif = gif,
|
||||
caption = Optional.ofNullable(this.caption),
|
||||
blurHash = Optional.ofNullable(this.blurHash),
|
||||
uploadTimestamp = this.locatorInfo.transitTierUploadTimestamp?.clampToValidBackupRange() ?: 0,
|
||||
uploadTimestamp = locatorInfo.transitTierUploadTimestamp?.clampToValidBackupRange() ?: 0,
|
||||
uuid = UuidUtil.fromByteStringOrNull(uuid)
|
||||
)
|
||||
PointerAttachment.forPointer(
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.util
|
||||
|
||||
import org.signal.archive.proto.ChatStyle
|
||||
import org.signal.archive.proto.FilePointer
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.attachments.AttachmentId
|
||||
import org.thoughtcrime.securesms.backup.v2.BackupMode
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportState
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ChatStyle
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.FilePointer
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColorsPalette
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
@@ -122,6 +122,7 @@ fun ChatStyle.toLocal(importState: ImportState): ChatColors? {
|
||||
ChatStyle.BubbleColorPreset.GRADIENT_SEA -> ChatColorsPalette.Bubbles.SEA
|
||||
ChatStyle.BubbleColorPreset.GRADIENT_TANGERINE -> ChatColorsPalette.Bubbles.TANGERINE
|
||||
ChatStyle.BubbleColorPreset.UNKNOWN_BUBBLE_COLOR_PRESET, ChatStyle.BubbleColorPreset.SOLID_ULTRAMARINE -> ChatColorsPalette.Bubbles.ULTRAMARINE
|
||||
else -> ChatColorsPalette.Bubbles.ULTRAMARINE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,8 +199,9 @@ fun ChatStyle.WallpaperPreset.toLocal(): ChatWallpaper? {
|
||||
}
|
||||
|
||||
fun ChatStyle.parseChatWallpaper(wallpaperAttachmentId: AttachmentId?): ChatWallpaper? {
|
||||
val chatWallpaper = if (this.wallpaperPreset != null) {
|
||||
this.wallpaperPreset.toLocal()
|
||||
val localWallpaperPreset = this.wallpaperPreset
|
||||
val chatWallpaper = if (localWallpaperPreset != null) {
|
||||
localWallpaperPreset.toLocal()
|
||||
} else if (wallpaperAttachmentId != null) {
|
||||
UriChatWallpaper(PartAuthority.getAttachmentDataUri(wallpaperAttachmentId), 0f)
|
||||
} else {
|
||||
|
||||
@@ -6,20 +6,23 @@
|
||||
package org.thoughtcrime.securesms.backup.v2.util
|
||||
|
||||
import okio.ByteString
|
||||
import org.signal.archive.proto.AccountData
|
||||
import org.signal.archive.proto.Chat
|
||||
import org.signal.archive.proto.ChatItem
|
||||
import org.signal.archive.proto.FilePointer
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.core.models.backup.MediaName
|
||||
import org.thoughtcrime.securesms.attachments.Cdn
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.AccountData
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Chat
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.ChatItem
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.FilePointer
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
|
||||
fun Frame.getAllReferencedArchiveAttachmentInfos(): Set<ArchiveAttachmentInfo> {
|
||||
val infos: MutableSet<ArchiveAttachmentInfo> = mutableSetOf()
|
||||
val account = this.account
|
||||
val chat = this.chat
|
||||
val chatItem = this.chatItem
|
||||
when {
|
||||
this.account != null -> infos += this.account.getAllReferencedArchiveAttachmentInfos()
|
||||
this.chat != null -> infos += this.chat.getAllReferencedArchiveAttachmentInfos()
|
||||
this.chatItem != null -> infos += this.chatItem.getAllReferencedArchiveAttachmentInfos()
|
||||
account != null -> infos += account.getAllReferencedArchiveAttachmentInfos()
|
||||
chat != null -> infos += chat.getAllReferencedArchiveAttachmentInfos()
|
||||
chatItem != null -> infos += chatItem.getAllReferencedArchiveAttachmentInfos()
|
||||
}
|
||||
return infos.toSet()
|
||||
}
|
||||
@@ -74,18 +77,15 @@ private fun ChatItem.getAllReferencedArchiveAttachmentInfos(): Set<ArchiveAttach
|
||||
}
|
||||
|
||||
private fun FilePointer.toArchiveAttachmentInfo(forQuote: Boolean = false, isWallpaper: Boolean = false): ArchiveAttachmentInfo? {
|
||||
if (this.locatorInfo?.key == null) {
|
||||
return null
|
||||
}
|
||||
val locatorInfo = this.locatorInfo
|
||||
|
||||
if (this.locatorInfo.plaintextHash == null) {
|
||||
return null
|
||||
}
|
||||
val key = locatorInfo?.key ?: return null
|
||||
val plaintextHash = locatorInfo.plaintextHash ?: return null
|
||||
|
||||
return ArchiveAttachmentInfo(
|
||||
plaintextHash = this.locatorInfo.plaintextHash,
|
||||
remoteKey = this.locatorInfo.key,
|
||||
cdn = this.locatorInfo.mediaTierCdnNumber ?: Cdn.CDN_0.cdnNumber,
|
||||
plaintextHash = plaintextHash,
|
||||
remoteKey = key,
|
||||
cdn = locatorInfo.mediaTierCdnNumber ?: Cdn.CDN_0.cdnNumber,
|
||||
contentType = this.contentType,
|
||||
forQuote = forQuote,
|
||||
isWallpaper = isWallpaper
|
||||
|
||||
@@ -22,6 +22,8 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.signal.archive.stream.EncryptedBackupReader
|
||||
import org.signal.archive.stream.EncryptedBackupReader.Companion.MAC_SIZE
|
||||
import org.signal.core.models.ServiceId.ACI
|
||||
import org.signal.core.models.backup.MessageBackupKey
|
||||
import org.signal.core.util.Hex
|
||||
@@ -42,8 +44,6 @@ import org.thoughtcrime.securesms.backup.v2.BackupRepository
|
||||
import org.thoughtcrime.securesms.backup.v2.DebugBackupMetadata
|
||||
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
|
||||
import org.thoughtcrime.securesms.backup.v2.RemoteRestoreResult
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.EncryptedBackupReader
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.EncryptedBackupReader.Companion.MAC_SIZE
|
||||
import org.thoughtcrime.securesms.database.AttachmentTable
|
||||
import org.thoughtcrime.securesms.database.AttachmentTable.DebugAttachmentStats
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
|
||||
@@ -25,6 +25,7 @@ import androidx.annotation.WorkerThread
|
||||
import androidx.core.content.contentValuesOf
|
||||
import com.bumptech.glide.Glide
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.signal.archive.proto.BackupDebugInfo
|
||||
import org.signal.blurhash.BlurHash
|
||||
import org.signal.core.models.backup.MediaId
|
||||
import org.signal.core.models.backup.MediaName
|
||||
@@ -76,7 +77,6 @@ import org.thoughtcrime.securesms.attachments.WallpaperAttachment
|
||||
import org.thoughtcrime.securesms.audio.AudioHash
|
||||
import org.thoughtcrime.securesms.backup.v2.ArchivedMediaObject
|
||||
import org.thoughtcrime.securesms.backup.v2.exporters.ChatItemArchiveExporter
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.BackupDebugInfo
|
||||
import org.thoughtcrime.securesms.crypto.AttachmentSecret
|
||||
import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream
|
||||
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream
|
||||
|
||||
@@ -8,12 +8,12 @@ package org.thoughtcrime.securesms.database.helpers.migration
|
||||
import android.app.Application
|
||||
import androidx.core.content.contentValuesOf
|
||||
import okio.IOException
|
||||
import org.signal.archive.proto.GroupInvitationRevokedUpdate
|
||||
import org.signal.core.models.ServiceId
|
||||
import org.signal.core.util.forEach
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.requireBlob
|
||||
import org.signal.core.util.requireLong
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInvitationRevokedUpdate
|
||||
import org.thoughtcrime.securesms.database.SQLiteDatabase
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExtras
|
||||
|
||||
@@ -50,8 +50,9 @@ object V258_FixGroupRevokedInviteeUpdate : SignalDatabaseMigration {
|
||||
|
||||
updates
|
||||
.replaceAll { change ->
|
||||
if (change.groupInvitationRevokedUpdate != null) {
|
||||
val invitees = change.groupInvitationRevokedUpdate.invitees.toMutableList()
|
||||
val revokedUpdate = change.groupInvitationRevokedUpdate
|
||||
if (revokedUpdate != null) {
|
||||
val invitees = revokedUpdate.invitees.toMutableList()
|
||||
|
||||
invitees.replaceAll { invitee ->
|
||||
val inviteeAciFieldServiceId = ServiceId.parseOrNull(invitee.inviteeAci)
|
||||
@@ -69,7 +70,7 @@ object V258_FixGroupRevokedInviteeUpdate : SignalDatabaseMigration {
|
||||
}
|
||||
}
|
||||
|
||||
change.copy(groupInvitationRevokedUpdate = change.groupInvitationRevokedUpdate.copy(invitees = invitees))
|
||||
change.copy(groupInvitationRevokedUpdate = revokedUpdate.copy(invitees = invitees))
|
||||
} else {
|
||||
change
|
||||
}
|
||||
|
||||
@@ -8,12 +8,12 @@ package org.thoughtcrime.securesms.database.helpers.migration
|
||||
import android.app.Application
|
||||
import androidx.core.content.contentValuesOf
|
||||
import okio.IOException
|
||||
import org.signal.archive.proto.GroupMemberAddedUpdate
|
||||
import org.signal.core.models.ServiceId
|
||||
import org.signal.core.util.forEach
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.requireBlob
|
||||
import org.signal.core.util.requireLong
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberAddedUpdate
|
||||
import org.thoughtcrime.securesms.database.SQLiteDatabase
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExtras
|
||||
|
||||
@@ -50,9 +50,10 @@ object V264_FixGroupAddMemberUpdate : SignalDatabaseMigration {
|
||||
|
||||
updates
|
||||
.replaceAll { change ->
|
||||
if (change.groupMemberAddedUpdate != null && ServiceId.parseOrNull(change.groupMemberAddedUpdate.updaterAci) is ServiceId.PNI) {
|
||||
val addedUpdate = change.groupMemberAddedUpdate
|
||||
if (addedUpdate != null && ServiceId.parseOrNull(addedUpdate.updaterAci) is ServiceId.PNI) {
|
||||
dataMigrated = true
|
||||
change.copy(groupMemberAddedUpdate = change.groupMemberAddedUpdate.copy(updaterAci = null))
|
||||
change.copy(groupMemberAddedUpdate = addedUpdate.copy(updaterAci = null))
|
||||
} else {
|
||||
change
|
||||
}
|
||||
|
||||
@@ -8,12 +8,12 @@ package org.thoughtcrime.securesms.database.helpers.migration
|
||||
import android.app.Application
|
||||
import androidx.core.content.contentValuesOf
|
||||
import okio.IOException
|
||||
import org.signal.archive.proto.GroupInvitationDeclinedUpdate
|
||||
import org.signal.core.models.ServiceId
|
||||
import org.signal.core.util.forEach
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.requireBlob
|
||||
import org.signal.core.util.requireLong
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInvitationDeclinedUpdate
|
||||
import org.thoughtcrime.securesms.database.SQLiteDatabase
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExtras
|
||||
|
||||
@@ -49,8 +49,9 @@ object V267_FixGroupInvitationDeclinedUpdate : SignalDatabaseMigration {
|
||||
|
||||
updates
|
||||
.replaceAll { change ->
|
||||
if (change.groupInvitationDeclinedUpdate != null && ServiceId.parseOrNull(change.groupInvitationDeclinedUpdate.inviteeAci) is ServiceId.PNI) {
|
||||
change.copy(groupInvitationDeclinedUpdate = change.groupInvitationDeclinedUpdate.copy(inviteeAci = null))
|
||||
val declinedUpdate = change.groupInvitationDeclinedUpdate
|
||||
if (declinedUpdate != null && ServiceId.parseOrNull(declinedUpdate.inviteeAci) is ServiceId.PNI) {
|
||||
change.copy(groupInvitationDeclinedUpdate = declinedUpdate.copy(inviteeAci = null))
|
||||
} else {
|
||||
change
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import org.signal.core.util.Base64;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupCall;
|
||||
import org.signal.archive.proto.GroupCall;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GroupCallUpdateDetails;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.signal.core.models.ServiceId;
|
||||
|
||||
@@ -6,6 +6,40 @@
|
||||
package org.thoughtcrime.securesms.database.model
|
||||
|
||||
import okio.ByteString
|
||||
import org.signal.archive.proto.GenericGroupUpdate
|
||||
import org.signal.archive.proto.GroupAdminStatusUpdate
|
||||
import org.signal.archive.proto.GroupAnnouncementOnlyChangeUpdate
|
||||
import org.signal.archive.proto.GroupAttributesAccessLevelChangeUpdate
|
||||
import org.signal.archive.proto.GroupAvatarUpdate
|
||||
import org.signal.archive.proto.GroupChangeChatUpdate
|
||||
import org.signal.archive.proto.GroupCreationUpdate
|
||||
import org.signal.archive.proto.GroupDescriptionUpdate
|
||||
import org.signal.archive.proto.GroupExpirationTimerUpdate
|
||||
import org.signal.archive.proto.GroupInvitationAcceptedUpdate
|
||||
import org.signal.archive.proto.GroupInvitationDeclinedUpdate
|
||||
import org.signal.archive.proto.GroupInvitationRevokedUpdate
|
||||
import org.signal.archive.proto.GroupInviteLinkAdminApprovalUpdate
|
||||
import org.signal.archive.proto.GroupInviteLinkDisabledUpdate
|
||||
import org.signal.archive.proto.GroupInviteLinkEnabledUpdate
|
||||
import org.signal.archive.proto.GroupInviteLinkResetUpdate
|
||||
import org.signal.archive.proto.GroupJoinRequestApprovalUpdate
|
||||
import org.signal.archive.proto.GroupJoinRequestCanceledUpdate
|
||||
import org.signal.archive.proto.GroupJoinRequestUpdate
|
||||
import org.signal.archive.proto.GroupMemberAddedUpdate
|
||||
import org.signal.archive.proto.GroupMemberJoinedByLinkUpdate
|
||||
import org.signal.archive.proto.GroupMemberJoinedUpdate
|
||||
import org.signal.archive.proto.GroupMemberLabelAccessLevelChangeUpdate
|
||||
import org.signal.archive.proto.GroupMemberLeftUpdate
|
||||
import org.signal.archive.proto.GroupMemberRemovedUpdate
|
||||
import org.signal.archive.proto.GroupMembershipAccessLevelChangeUpdate
|
||||
import org.signal.archive.proto.GroupNameUpdate
|
||||
import org.signal.archive.proto.GroupSelfInvitationRevokedUpdate
|
||||
import org.signal.archive.proto.GroupSequenceOfRequestsAndCancelsUpdate
|
||||
import org.signal.archive.proto.GroupTerminateChangeUpdate
|
||||
import org.signal.archive.proto.GroupUnknownInviteeUpdate
|
||||
import org.signal.archive.proto.GroupV2AccessLevel
|
||||
import org.signal.archive.proto.SelfInvitedOtherUserToGroupUpdate
|
||||
import org.signal.archive.proto.SelfInvitedToGroupUpdate
|
||||
import org.signal.core.models.ServiceId
|
||||
import org.signal.core.util.BidiUtil
|
||||
import org.signal.core.util.UuidUtil
|
||||
@@ -18,40 +52,6 @@ import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChang
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember
|
||||
import org.signal.storageservice.storage.protos.groups.local.EnabledState
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GenericGroupUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupAdminStatusUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupAnnouncementOnlyChangeUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupAttributesAccessLevelChangeUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupAvatarUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupChangeChatUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupCreationUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupDescriptionUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupExpirationTimerUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInvitationAcceptedUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInvitationDeclinedUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInvitationRevokedUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInviteLinkAdminApprovalUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInviteLinkDisabledUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInviteLinkEnabledUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInviteLinkResetUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupJoinRequestApprovalUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupJoinRequestCanceledUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupJoinRequestUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberAddedUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberJoinedByLinkUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberJoinedUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberLabelAccessLevelChangeUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberLeftUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberRemovedUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMembershipAccessLevelChangeUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupNameUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupSelfInvitationRevokedUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupSequenceOfRequestsAndCancelsUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupTerminateChangeUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupUnknownInviteeUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupV2AccessLevel
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.SelfInvitedOtherUserToGroupUpdate
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.SelfInvitedToGroupUpdate
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil
|
||||
import org.whispersystems.signalservice.api.push.ServiceIds
|
||||
|
||||
@@ -26,43 +26,43 @@ import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMem
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember;
|
||||
import org.signal.storageservice.storage.protos.groups.local.EnabledState;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GenericGroupUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupAdminStatusUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupAnnouncementOnlyChangeUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupAttributesAccessLevelChangeUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupAvatarUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupChangeChatUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupCreationUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupDescriptionUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupExpirationTimerUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInvitationAcceptedUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInvitationDeclinedUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInvitationRevokedUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInviteLinkAdminApprovalUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInviteLinkDisabledUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInviteLinkEnabledUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInviteLinkResetUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupJoinRequestApprovalUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupJoinRequestCanceledUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupJoinRequestUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberAddedUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberJoinedByLinkUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberJoinedUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberLabelAccessLevelChangeUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberLeftUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMemberRemovedUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupMembershipAccessLevelChangeUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupNameUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupSelfInvitationRevokedUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupTerminateChangeUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupUnknownInviteeUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupV2AccessLevel;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupV2MigrationDroppedMembersUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupV2MigrationInvitedMembersUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupV2MigrationSelfInvitedUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupV2MigrationUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.SelfInvitedOtherUserToGroupUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.SelfInvitedToGroupUpdate;
|
||||
import org.signal.archive.proto.GenericGroupUpdate;
|
||||
import org.signal.archive.proto.GroupAdminStatusUpdate;
|
||||
import org.signal.archive.proto.GroupAnnouncementOnlyChangeUpdate;
|
||||
import org.signal.archive.proto.GroupAttributesAccessLevelChangeUpdate;
|
||||
import org.signal.archive.proto.GroupAvatarUpdate;
|
||||
import org.signal.archive.proto.GroupChangeChatUpdate;
|
||||
import org.signal.archive.proto.GroupCreationUpdate;
|
||||
import org.signal.archive.proto.GroupDescriptionUpdate;
|
||||
import org.signal.archive.proto.GroupExpirationTimerUpdate;
|
||||
import org.signal.archive.proto.GroupInvitationAcceptedUpdate;
|
||||
import org.signal.archive.proto.GroupInvitationDeclinedUpdate;
|
||||
import org.signal.archive.proto.GroupInvitationRevokedUpdate;
|
||||
import org.signal.archive.proto.GroupInviteLinkAdminApprovalUpdate;
|
||||
import org.signal.archive.proto.GroupInviteLinkDisabledUpdate;
|
||||
import org.signal.archive.proto.GroupInviteLinkEnabledUpdate;
|
||||
import org.signal.archive.proto.GroupInviteLinkResetUpdate;
|
||||
import org.signal.archive.proto.GroupJoinRequestApprovalUpdate;
|
||||
import org.signal.archive.proto.GroupJoinRequestCanceledUpdate;
|
||||
import org.signal.archive.proto.GroupJoinRequestUpdate;
|
||||
import org.signal.archive.proto.GroupMemberAddedUpdate;
|
||||
import org.signal.archive.proto.GroupMemberJoinedByLinkUpdate;
|
||||
import org.signal.archive.proto.GroupMemberJoinedUpdate;
|
||||
import org.signal.archive.proto.GroupMemberLabelAccessLevelChangeUpdate;
|
||||
import org.signal.archive.proto.GroupMemberLeftUpdate;
|
||||
import org.signal.archive.proto.GroupMemberRemovedUpdate;
|
||||
import org.signal.archive.proto.GroupMembershipAccessLevelChangeUpdate;
|
||||
import org.signal.archive.proto.GroupNameUpdate;
|
||||
import org.signal.archive.proto.GroupSelfInvitationRevokedUpdate;
|
||||
import org.signal.archive.proto.GroupTerminateChangeUpdate;
|
||||
import org.signal.archive.proto.GroupUnknownInviteeUpdate;
|
||||
import org.signal.archive.proto.GroupV2AccessLevel;
|
||||
import org.signal.archive.proto.GroupV2MigrationDroppedMembersUpdate;
|
||||
import org.signal.archive.proto.GroupV2MigrationInvitedMembersUpdate;
|
||||
import org.signal.archive.proto.GroupV2MigrationSelfInvitedUpdate;
|
||||
import org.signal.archive.proto.GroupV2MigrationUpdate;
|
||||
import org.signal.archive.proto.SelfInvitedOtherUserToGroupUpdate;
|
||||
import org.signal.archive.proto.SelfInvitedToGroupUpdate;
|
||||
import org.thoughtcrime.securesms.fonts.SignalSymbols.Glyph;
|
||||
import org.thoughtcrime.securesms.groups.GV2AccessLevelUtil;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
@@ -38,8 +38,8 @@ import org.signal.core.util.logging.Log;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupChangeChatUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupCreationUpdate;
|
||||
import org.signal.archive.proto.GroupChangeChatUpdate;
|
||||
import org.signal.archive.proto.GroupCreationUpdate;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.parsing.EmojiParser;
|
||||
import org.thoughtcrime.securesms.components.transfercontrols.TransferControlView;
|
||||
|
||||
@@ -10,7 +10,7 @@ import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupChangeChatUpdate;
|
||||
import org.signal.archive.proto.GroupChangeChatUpdate;
|
||||
import org.thoughtcrime.securesms.database.model.GroupsV2UpdateMessageConverter;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GV2UpdateDescription;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package org.thoughtcrime.securesms.keyvalue
|
||||
|
||||
import org.signal.archive.proto.BackupDebugInfo
|
||||
import org.signal.ringrtc.CallManager.DataMode
|
||||
import org.thoughtcrime.securesms.BuildConfig
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.BackupDebugInfo
|
||||
import org.thoughtcrime.securesms.util.Environment.Calling.defaultSfuUrl
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
package org.thoughtcrime.securesms
|
||||
|
||||
import okio.ByteString
|
||||
import org.signal.archive.proto.AccountData
|
||||
import org.signal.archive.proto.BackupDebugInfo
|
||||
import org.signal.archive.proto.FilePointer
|
||||
import org.signal.archive.stream.EncryptedBackupReader
|
||||
import org.signal.core.util.bytes
|
||||
import org.signal.core.util.decodeOrNull
|
||||
import org.signal.core.util.logging.Log
|
||||
@@ -14,10 +18,6 @@ import org.signal.spinner.Plugin
|
||||
import org.signal.spinner.PluginResult
|
||||
import org.thoughtcrime.securesms.backup.v2.BackupRepository
|
||||
import org.thoughtcrime.securesms.backup.v2.local.SnapshotFileSystem
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.AccountData
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.BackupDebugInfo
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.FilePointer
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.EncryptedBackupReader
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.net.SignalNetwork
|
||||
@@ -205,7 +205,7 @@ class BackupPlugin : Plugin {
|
||||
}
|
||||
frame.recipient != null -> {
|
||||
totalRecipients++
|
||||
val recipient = frame.recipient
|
||||
val recipient = frame.recipient!!
|
||||
recipientNames[recipient.id] = extractRecipientName(recipient)
|
||||
|
||||
when {
|
||||
@@ -218,7 +218,7 @@ class BackupPlugin : Plugin {
|
||||
}
|
||||
}
|
||||
frame.chat != null -> {
|
||||
val chat = frame.chat
|
||||
val chat = frame.chat!!
|
||||
chatInfos[chat.id] = ChatInfo(
|
||||
chatId = chat.id,
|
||||
recipientId = chat.recipientId,
|
||||
@@ -234,7 +234,7 @@ class BackupPlugin : Plugin {
|
||||
}
|
||||
}
|
||||
frame.chatItem != null -> {
|
||||
val item = frame.chatItem
|
||||
val item = frame.chatItem!!
|
||||
chatInfos[item.chatId]?.let { chatInfo ->
|
||||
chatInfo.messageCount++
|
||||
chatInfo.attachmentCount += item.standardMessage?.attachments?.size ?: 0
|
||||
@@ -319,7 +319,7 @@ class BackupPlugin : Plugin {
|
||||
counters.total++
|
||||
|
||||
// Check for plaintextHash
|
||||
val hasPlaintextHash = filePointer.locatorInfo?.plaintextHash != null && filePointer.locatorInfo.plaintextHash.size > 0
|
||||
val hasPlaintextHash = filePointer.locatorInfo?.plaintextHash != null && filePointer.locatorInfo?.plaintextHash!!.size > 0
|
||||
if (hasPlaintextHash) {
|
||||
counters.withPlaintextHash++
|
||||
} else {
|
||||
@@ -328,7 +328,7 @@ class BackupPlugin : Plugin {
|
||||
}
|
||||
|
||||
// Check for localKey
|
||||
val hasLocalKey = filePointer.locatorInfo?.localKey != null && filePointer.locatorInfo.localKey.size > 0
|
||||
val hasLocalKey = filePointer.locatorInfo?.localKey != null && filePointer.locatorInfo?.localKey!!.size > 0
|
||||
if (hasLocalKey) {
|
||||
counters.withLocalKey++
|
||||
} else {
|
||||
@@ -527,12 +527,12 @@ class BackupPlugin : Plugin {
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
private fun extractRecipientName(recipient: org.thoughtcrime.securesms.backup.v2.proto.Recipient?): String {
|
||||
private fun extractRecipientName(recipient: org.signal.archive.proto.Recipient?): String {
|
||||
if (recipient == null) return "Unknown"
|
||||
|
||||
return when {
|
||||
recipient.contact != null -> {
|
||||
val contact = recipient.contact
|
||||
val contact = recipient.contact!!
|
||||
val name = buildString {
|
||||
if (contact.profileGivenName?.isNotEmpty() == true) {
|
||||
append(contact.profileGivenName)
|
||||
@@ -540,9 +540,9 @@ class BackupPlugin : Plugin {
|
||||
append(" ${contact.profileFamilyName}")
|
||||
}
|
||||
} else if (contact.nickname?.given?.isNotEmpty() == true) {
|
||||
append(contact.nickname.given)
|
||||
if (contact.nickname.family.isNotEmpty()) {
|
||||
append(" ${contact.nickname.family}")
|
||||
append(contact.nickname!!.given)
|
||||
if (contact.nickname!!.family.isNotEmpty()) {
|
||||
append(" ${contact.nickname!!.family}")
|
||||
}
|
||||
} else if (contact.e164 != null) {
|
||||
append("+${contact.e164}")
|
||||
@@ -553,7 +553,7 @@ class BackupPlugin : Plugin {
|
||||
name
|
||||
}
|
||||
recipient.group != null -> {
|
||||
val group = recipient.group
|
||||
val group = recipient.group!!
|
||||
group.snapshot?.title?.title ?: "Group ${recipient.id}"
|
||||
}
|
||||
recipient.self != null -> "Self"
|
||||
|
||||
@@ -18,14 +18,14 @@ import org.junit.rules.TemporaryFolder
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.signal.archive.local.proto.Metadata
|
||||
import org.signal.archive.proto.AccountData
|
||||
import org.signal.archive.proto.BackupInfo
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.archive.stream.EncryptedBackupWriter
|
||||
import org.signal.core.models.backup.BackupId
|
||||
import org.signal.core.models.backup.MessageBackupKey
|
||||
import org.signal.core.util.Util
|
||||
import org.thoughtcrime.securesms.backup.v2.local.proto.Metadata
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.AccountData
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.BackupInfo
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import org.thoughtcrime.securesms.backup.v2.stream.EncryptedBackupWriter
|
||||
import java.io.ByteArrayOutputStream
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
|
||||
@@ -7,6 +7,11 @@ package org.thoughtcrime.securesms.backup.v2.stream
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.signal.archive.proto.AccountData
|
||||
import org.signal.archive.proto.BackupInfo
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.archive.stream.EncryptedBackupReader
|
||||
import org.signal.archive.stream.EncryptedBackupWriter
|
||||
import org.signal.core.models.ServiceId.ACI
|
||||
import org.signal.core.models.backup.BackupId
|
||||
import org.signal.core.models.backup.MessageBackupKey
|
||||
@@ -14,9 +19,6 @@ import org.signal.core.util.Base64
|
||||
import org.signal.core.util.Hex
|
||||
import org.signal.core.util.Util
|
||||
import org.signal.libsignal.messagebackup.BackupForwardSecrecyToken
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.AccountData
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.BackupInfo
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.util.UUID
|
||||
|
||||
|
||||
27
lib/archive/build.gradle.kts
Normal file
27
lib/archive/build.gradle.kts
Normal file
@@ -0,0 +1,27 @@
|
||||
plugins {
|
||||
id("signal-library")
|
||||
id("com.squareup.wire")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "org.signal.archive"
|
||||
}
|
||||
|
||||
wire {
|
||||
kotlin {
|
||||
javaInterop = true
|
||||
}
|
||||
|
||||
sourcePath {
|
||||
srcDir("src/main/protowire")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":core:util"))
|
||||
implementation(project(":core:models-jvm"))
|
||||
implementation(project(":lib:libsignal-service"))
|
||||
|
||||
implementation(libs.libsignal.android)
|
||||
implementation(libs.google.guava.android)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.signal.archive
|
||||
|
||||
/**
|
||||
* Metadata about a local backup file available for restore.
|
||||
*/
|
||||
data class LocalBackupMetadata(
|
||||
/** Size of the backup in bytes. */
|
||||
val sizeBytes: Long,
|
||||
/** Timestamp when the backup was created, in milliseconds since epoch. */
|
||||
val timestampMs: Long
|
||||
)
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.signal.archive
|
||||
|
||||
/**
|
||||
* Represents the progress of a local backup restore operation.
|
||||
* Emitted as a flow from the storage controller during restore.
|
||||
*/
|
||||
sealed interface LocalBackupRestoreProgress {
|
||||
/** The restore is being prepared (e.g., reading metadata, validating). */
|
||||
data object Preparing : LocalBackupRestoreProgress
|
||||
|
||||
/** The restore is actively in progress. */
|
||||
data class InProgress(
|
||||
val bytesRead: Long,
|
||||
val totalBytes: Long
|
||||
) : LocalBackupRestoreProgress {
|
||||
val progressFraction: Float
|
||||
get() = if (totalBytes > 0) (bytesRead.toFloat() / totalBytes.toFloat()).coerceIn(0f, 1f) else 0f
|
||||
}
|
||||
|
||||
/** The restore completed successfully. */
|
||||
data object Complete : LocalBackupRestoreProgress
|
||||
|
||||
/** The restore failed with an error. */
|
||||
data class Error(val cause: Throwable) : LocalBackupRestoreProgress
|
||||
}
|
||||
@@ -3,11 +3,11 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.local
|
||||
package org.signal.archive.local
|
||||
|
||||
import org.signal.archive.local.proto.FilesFrame
|
||||
import org.signal.core.util.readNBytesOrThrow
|
||||
import org.signal.core.util.readVarInt32
|
||||
import org.thoughtcrime.securesms.backup.v2.local.proto.FilesFrame
|
||||
import java.io.EOFException
|
||||
import java.io.InputStream
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.local
|
||||
package org.signal.archive.local
|
||||
|
||||
import org.signal.archive.local.proto.FilesFrame
|
||||
import org.signal.core.util.writeVarInt32
|
||||
import org.thoughtcrime.securesms.backup.v2.local.proto.FilesFrame
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.stream
|
||||
package org.signal.archive.stream
|
||||
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.BackupInfo
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import org.signal.archive.proto.BackupInfo
|
||||
import org.signal.archive.proto.Frame
|
||||
|
||||
interface BackupExportWriter : AutoCloseable {
|
||||
fun write(header: BackupInfo)
|
||||
@@ -3,9 +3,9 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.stream
|
||||
package org.signal.archive.stream
|
||||
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import org.signal.archive.proto.Frame
|
||||
|
||||
/**
|
||||
* An interface that lets sub-processors emit [Frame]s as they export data.
|
||||
@@ -3,10 +3,10 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.stream
|
||||
package org.signal.archive.stream
|
||||
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.BackupInfo
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import org.signal.archive.proto.BackupInfo
|
||||
import org.signal.archive.proto.Frame
|
||||
|
||||
interface BackupImportReader : Iterator<Frame>, AutoCloseable {
|
||||
fun getHeader(): BackupInfo?
|
||||
@@ -3,9 +3,9 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.stream
|
||||
package org.signal.archive.stream
|
||||
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import org.signal.archive.proto.Frame
|
||||
|
||||
interface BackupImportStream {
|
||||
fun read(): Frame?
|
||||
@@ -3,10 +3,12 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.stream
|
||||
package org.signal.archive.stream
|
||||
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import com.google.common.io.CountingInputStream
|
||||
import org.signal.archive.proto.BackupInfo
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.core.models.ServiceId.ACI
|
||||
import org.signal.core.models.backup.BackupId
|
||||
import org.signal.core.models.backup.MessageBackupKey
|
||||
@@ -17,8 +19,6 @@ import org.signal.core.util.stream.LimitedInputStream
|
||||
import org.signal.core.util.stream.MacInputStream
|
||||
import org.signal.core.util.writeVarInt32
|
||||
import org.signal.libsignal.messagebackup.BackupForwardSecrecyToken
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.BackupInfo
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.EOFException
|
||||
import java.io.IOException
|
||||
@@ -3,8 +3,11 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.stream
|
||||
package org.signal.archive.stream
|
||||
|
||||
import org.signal.archive.proto.BackupInfo
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.archive.stream.EncryptedBackupReader.Companion.createForSignalBackup
|
||||
import org.signal.core.models.ServiceId.ACI
|
||||
import org.signal.core.models.backup.BackupId
|
||||
import org.signal.core.models.backup.MessageBackupKey
|
||||
@@ -12,8 +15,6 @@ import org.signal.core.util.Util
|
||||
import org.signal.core.util.stream.MacOutputStream
|
||||
import org.signal.core.util.writeVarInt32
|
||||
import org.signal.libsignal.messagebackup.BackupForwardSecrecyToken
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.BackupInfo
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
import javax.crypto.Cipher
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.stream
|
||||
package org.signal.archive.stream
|
||||
|
||||
import org.whispersystems.signalservice.internal.crypto.PaddingInputStream
|
||||
import java.io.FilterOutputStream
|
||||
@@ -3,13 +3,13 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.stream
|
||||
package org.signal.archive.stream
|
||||
|
||||
import com.google.common.io.CountingInputStream
|
||||
import org.signal.archive.proto.BackupInfo
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.core.util.readNBytesOrThrow
|
||||
import org.signal.core.util.readVarInt32
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.BackupInfo
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import java.io.EOFException
|
||||
import java.io.InputStream
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.stream
|
||||
package org.signal.archive.stream
|
||||
|
||||
import org.signal.archive.proto.BackupInfo
|
||||
import org.signal.archive.proto.Frame
|
||||
import org.signal.core.util.writeVarInt32
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.BackupInfo
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.Frame
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
|
||||
@@ -2,7 +2,7 @@ syntax = "proto3";
|
||||
|
||||
package signal.backup;
|
||||
|
||||
option java_package = "org.thoughtcrime.securesms.backup.v2.proto";
|
||||
option java_package = "org.signal.archive.proto";
|
||||
option swift_prefix = "BackupProto_";
|
||||
|
||||
message BackupInfo {
|
||||
@@ -1,6 +1,6 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option java_package = "org.thoughtcrime.securesms.backup.v2.proto";
|
||||
option java_package = "org.signal.archive.proto";
|
||||
|
||||
message BackupDebugInfo {
|
||||
message AttachmentDetails {
|
||||
@@ -2,7 +2,7 @@ syntax = "proto3";
|
||||
|
||||
package signal.backup.local;
|
||||
|
||||
option java_package = "org.thoughtcrime.securesms.backup.v2.local.proto";
|
||||
option java_package = "org.signal.archive.local.proto";
|
||||
option swift_prefix = "LocalBackupProto_";
|
||||
|
||||
message Metadata {
|
||||
@@ -88,6 +88,7 @@ include(":lib:image-editor")
|
||||
include(":lib:debuglogs-viewer")
|
||||
include(":lib:blurhash")
|
||||
include(":lib:apng")
|
||||
include(":lib:archive")
|
||||
|
||||
// Feature modules
|
||||
include(":feature:registration")
|
||||
|
||||
Reference in New Issue
Block a user