mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-23 02:10:44 +01:00
Get shared backup tests working.
This commit is contained in:
committed by
Nicholas Tinsley
parent
36640edfee
commit
7b0badef19
@@ -46,7 +46,6 @@ import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsTypeFe
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.RecurringInAppPaymentRepository
|
||||
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider
|
||||
import org.thoughtcrime.securesms.database.DistributionListTables
|
||||
import org.thoughtcrime.securesms.database.KeyValueDatabase
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord
|
||||
@@ -249,19 +248,15 @@ object BackupRepository {
|
||||
}
|
||||
}
|
||||
|
||||
fun export(plaintext: Boolean = false, currentTime: Long = System.currentTimeMillis()): ByteArray {
|
||||
/**
|
||||
* Exports to a blob in memory. Should only be used for testing.
|
||||
*/
|
||||
fun debugExport(plaintext: Boolean = false, currentTime: Long = System.currentTimeMillis()): ByteArray {
|
||||
val outputStream = ByteArrayOutputStream()
|
||||
export(outputStream = outputStream, append = { mac -> outputStream.write(mac) }, plaintext = plaintext, currentTime = currentTime)
|
||||
return outputStream.toByteArray()
|
||||
}
|
||||
|
||||
fun validate(length: Long, inputStreamFactory: () -> InputStream, selfData: SelfData): ValidationResult {
|
||||
val masterKey = SignalStore.svr.getOrCreateMasterKey()
|
||||
val key = MessageBackupKey(masterKey.serialize(), Aci.parseFromBinary(selfData.aci.toByteArray()))
|
||||
|
||||
return MessageBackup.validate(key, MessageBackup.Purpose.REMOTE_BACKUP, inputStreamFactory, length)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The time the backup was created, or null if the backup could not be read.
|
||||
*/
|
||||
@@ -306,9 +301,6 @@ object BackupRepository {
|
||||
SignalDatabase.recipients.setProfileKey(selfId, selfData.profileKey)
|
||||
SignalDatabase.recipients.setProfileSharing(selfId, true)
|
||||
|
||||
// Add back my story after clearing data
|
||||
DistributionListTables.insertInitialDistributionListAtCreationTime(it)
|
||||
|
||||
eventTimer.emit("setup")
|
||||
val backupState = BackupState(backupKey)
|
||||
val chatItemInserter: ChatItemImportInserter = ChatItemBackupProcessor.beginImport(backupState)
|
||||
@@ -373,6 +365,13 @@ object BackupRepository {
|
||||
return ImportResult.Success(backupTime = header.backupTimeMs)
|
||||
}
|
||||
|
||||
fun validate(length: Long, inputStreamFactory: () -> InputStream, selfData: SelfData): ValidationResult {
|
||||
val masterKey = SignalStore.svr.getOrCreateMasterKey()
|
||||
val key = MessageBackupKey(masterKey.serialize(), Aci.parseFromBinary(selfData.aci.toByteArray()))
|
||||
|
||||
return MessageBackup.validate(key, MessageBackup.Purpose.REMOTE_BACKUP, inputStreamFactory, length)
|
||||
}
|
||||
|
||||
fun listRemoteMediaObjects(limit: Int, cursor: String? = null): NetworkResult<ArchiveGetMediaItemsResponse> {
|
||||
val api = AppDependencies.signalServiceAccountManager.archiveApi
|
||||
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
|
||||
|
||||
@@ -158,8 +158,8 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
|
||||
MessageTypes.isChangeNumber(record.type) -> {
|
||||
builder.updateMessage = simpleUpdate(SimpleChatUpdate.Type.CHANGE_NUMBER)
|
||||
}
|
||||
MessageTypes.isBoostRequest(record.type) -> {
|
||||
builder.updateMessage = simpleUpdate(SimpleChatUpdate.Type.BOOST_REQUEST)
|
||||
MessageTypes.isReleaseChannelDonationRequest(record.type) -> {
|
||||
builder.updateMessage = simpleUpdate(SimpleChatUpdate.Type.RELEASE_CHANNEL_DONATION_REQUEST)
|
||||
}
|
||||
MessageTypes.isEndSessionType(record.type) -> {
|
||||
builder.updateMessage = simpleUpdate(SimpleChatUpdate.Type.END_SESSION)
|
||||
@@ -176,6 +176,12 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
|
||||
MessageTypes.isPaymentsRequestToActivate(record.type) -> {
|
||||
builder.updateMessage = simpleUpdate(SimpleChatUpdate.Type.PAYMENT_ACTIVATION_REQUEST)
|
||||
}
|
||||
MessageTypes.isUnsupportedMessageType(record.type) -> {
|
||||
builder.updateMessage = simpleUpdate(SimpleChatUpdate.Type.UNSUPPORTED_PROTOCOL_MESSAGE)
|
||||
}
|
||||
MessageTypes.isReportedSpam(record.type) -> {
|
||||
builder.updateMessage = simpleUpdate(SimpleChatUpdate.Type.REPORTED_SPAM)
|
||||
}
|
||||
MessageTypes.isExpirationTimerUpdate(record.type) -> {
|
||||
builder.updateMessage = ChatUpdateMessage(expirationTimerChange = ExpirationTimerChatUpdate(record.expiresIn.toInt()))
|
||||
builder.expiresInMs = 0
|
||||
@@ -265,7 +271,7 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
|
||||
expiresInMs = if (record.expiresIn > 0) record.expiresIn else 0
|
||||
revisions = emptyList()
|
||||
sms = record.type.isSmsType()
|
||||
if (MessageTypes.isCallLog(record.type)) {
|
||||
if (record.type.isDirectionlessType()) {
|
||||
directionless = ChatItem.DirectionlessMessageDetails()
|
||||
} else if (MessageTypes.isOutgoingMessageType(record.type)) {
|
||||
outgoing = ChatItem.OutgoingMessageDetails(
|
||||
@@ -999,6 +1005,27 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
|
||||
return MessageTypes.isOutgoingMessageType(this) || MessageTypes.isInboxType(this)
|
||||
}
|
||||
|
||||
private fun Long.isDirectionlessType(): Boolean {
|
||||
return MessageTypes.isCallLog(this) ||
|
||||
MessageTypes.isExpirationTimerUpdate(this) ||
|
||||
MessageTypes.isThreadMergeType(this) ||
|
||||
MessageTypes.isSessionSwitchoverType(this) ||
|
||||
MessageTypes.isProfileChange(this) ||
|
||||
MessageTypes.isJoinedType(this) ||
|
||||
MessageTypes.isIdentityUpdate(this) ||
|
||||
MessageTypes.isIdentityVerified(this) ||
|
||||
MessageTypes.isIdentityDefault(this) ||
|
||||
MessageTypes.isReleaseChannelDonationRequest(this) ||
|
||||
MessageTypes.isChangeNumber(this) ||
|
||||
MessageTypes.isEndSessionType(this) ||
|
||||
MessageTypes.isChatSessionRefresh(this) ||
|
||||
MessageTypes.isBadDecryptType(this) ||
|
||||
MessageTypes.isPaymentsActivated(this) ||
|
||||
MessageTypes.isPaymentsRequestToActivate(this) ||
|
||||
MessageTypes.isUnsupportedMessageType(this) ||
|
||||
MessageTypes.isReportedSpam(this)
|
||||
}
|
||||
|
||||
private fun String.e164ToLong(): Long? {
|
||||
val fixed = if (this.startsWith("+")) {
|
||||
this.substring(1)
|
||||
|
||||
@@ -624,13 +624,14 @@ class ChatItemImportInserter(
|
||||
SimpleChatUpdate.Type.IDENTITY_VERIFIED -> MessageTypes.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT or typeWithoutBase
|
||||
SimpleChatUpdate.Type.IDENTITY_DEFAULT -> MessageTypes.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT or typeWithoutBase
|
||||
SimpleChatUpdate.Type.CHANGE_NUMBER -> MessageTypes.CHANGE_NUMBER_TYPE
|
||||
SimpleChatUpdate.Type.BOOST_REQUEST -> MessageTypes.BOOST_REQUEST_TYPE
|
||||
SimpleChatUpdate.Type.RELEASE_CHANNEL_DONATION_REQUEST -> MessageTypes.RELEASE_CHANNEL_DONATION_REQUEST_TYPE
|
||||
SimpleChatUpdate.Type.END_SESSION -> MessageTypes.END_SESSION_BIT or typeWithoutBase
|
||||
SimpleChatUpdate.Type.CHAT_SESSION_REFRESH -> MessageTypes.ENCRYPTION_REMOTE_FAILED_BIT or typeWithoutBase
|
||||
SimpleChatUpdate.Type.BAD_DECRYPT -> MessageTypes.BAD_DECRYPT_TYPE or typeWithoutBase
|
||||
SimpleChatUpdate.Type.PAYMENTS_ACTIVATED -> MessageTypes.SPECIAL_TYPE_PAYMENTS_ACTIVATED or typeWithoutBase
|
||||
SimpleChatUpdate.Type.PAYMENT_ACTIVATION_REQUEST -> MessageTypes.SPECIAL_TYPE_PAYMENTS_ACTIVATE_REQUEST or typeWithoutBase
|
||||
SimpleChatUpdate.Type.UNSUPPORTED_PROTOCOL_MESSAGE -> MessageTypes.UNSUPPORTED_MESSAGE_TYPE or typeWithoutBase
|
||||
SimpleChatUpdate.Type.REPORTED_SPAM -> MessageTypes.SPECIAL_TYPE_REPORTED_SPAM or typeWithoutBase
|
||||
}
|
||||
}
|
||||
updateMessage.expirationTimerChange != null -> {
|
||||
|
||||
@@ -6,14 +6,15 @@
|
||||
package org.thoughtcrime.securesms.backup.v2.database
|
||||
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.signal.core.util.CursorUtil
|
||||
import org.signal.core.util.deleteAll
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.readToList
|
||||
import org.signal.core.util.requireBoolean
|
||||
import org.signal.core.util.requireLong
|
||||
import org.signal.core.util.requireNonNullString
|
||||
import org.signal.core.util.requireObject
|
||||
import org.signal.core.util.select
|
||||
import org.signal.core.util.withinTransaction
|
||||
import org.thoughtcrime.securesms.backup.v2.BackupState
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.DistributionList
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.DistributionListItem
|
||||
@@ -36,7 +37,6 @@ fun DistributionListTables.getAllForBackup(): List<BackupRecipient> {
|
||||
val records = readableDatabase
|
||||
.select()
|
||||
.from(DistributionListTables.ListTable.TABLE_NAME)
|
||||
.where(DistributionListTables.ListTable.IS_NOT_DELETED)
|
||||
.run()
|
||||
.readToList { cursor ->
|
||||
val id: DistributionListId = DistributionListId.from(cursor.requireLong(DistributionListTables.ListTable.ID))
|
||||
@@ -48,11 +48,11 @@ fun DistributionListTables.getAllForBackup(): List<BackupRecipient> {
|
||||
id = id,
|
||||
name = cursor.requireNonNullString(DistributionListTables.ListTable.NAME),
|
||||
distributionId = DistributionId.from(cursor.requireNonNullString(DistributionListTables.ListTable.DISTRIBUTION_ID)),
|
||||
allowsReplies = CursorUtil.requireBoolean(cursor, DistributionListTables.ListTable.ALLOWS_REPLIES),
|
||||
allowsReplies = cursor.requireBoolean(DistributionListTables.ListTable.ALLOWS_REPLIES),
|
||||
rawMembers = getRawMembers(id, privacyMode),
|
||||
members = getMembers(id),
|
||||
deletedAtTimestamp = 0L,
|
||||
isUnknown = CursorUtil.requireBoolean(cursor, DistributionListTables.ListTable.IS_UNKNOWN),
|
||||
members = getMembersForBackup(id),
|
||||
deletedAtTimestamp = cursor.requireLong(DistributionListTables.ListTable.DELETION_TIMESTAMP),
|
||||
isUnknown = cursor.requireBoolean(DistributionListTables.ListTable.IS_UNKNOWN),
|
||||
privacyMode = privacyMode
|
||||
)
|
||||
)
|
||||
@@ -82,7 +82,37 @@ fun DistributionListTables.getAllForBackup(): List<BackupRecipient> {
|
||||
}
|
||||
}
|
||||
|
||||
fun DistributionListTables.getMembersForBackup(id: DistributionListId): List<RecipientId> {
|
||||
lateinit var privacyMode: DistributionListPrivacyMode
|
||||
lateinit var rawMembers: List<RecipientId>
|
||||
|
||||
readableDatabase.withinTransaction {
|
||||
privacyMode = getPrivacyMode(id)
|
||||
rawMembers = getRawMembers(id, privacyMode)
|
||||
}
|
||||
|
||||
return when (privacyMode) {
|
||||
DistributionListPrivacyMode.ALL -> emptyList()
|
||||
DistributionListPrivacyMode.ONLY_WITH -> rawMembers
|
||||
DistributionListPrivacyMode.ALL_EXCEPT -> rawMembers
|
||||
}
|
||||
}
|
||||
|
||||
fun DistributionListTables.restoreFromBackup(dlistItem: DistributionListItem, backupState: BackupState): RecipientId? {
|
||||
if (dlistItem.deletionTimestamp != null && dlistItem.deletionTimestamp > 0) {
|
||||
val dlistId = createList(
|
||||
name = "",
|
||||
members = emptyList(),
|
||||
distributionId = DistributionId.from(UuidUtil.fromByteString(dlistItem.distributionId)),
|
||||
allowsReplies = false,
|
||||
deletionTimestamp = dlistItem.deletionTimestamp,
|
||||
storageId = null,
|
||||
privacyMode = DistributionListPrivacyMode.ONLY_WITH
|
||||
)!!
|
||||
|
||||
return SignalDatabase.distributionLists.getRecipientId(dlistId)!!
|
||||
}
|
||||
|
||||
val dlist = dlistItem.distributionList ?: return null
|
||||
val members: List<RecipientId> = dlist.memberRecipientIds
|
||||
.mapNotNull { backupState.backupToLocalRecipientId[it] }
|
||||
@@ -94,32 +124,22 @@ fun DistributionListTables.restoreFromBackup(dlistItem: DistributionListItem, ba
|
||||
val distributionId = DistributionId.from(UuidUtil.fromByteString(dlistItem.distributionId))
|
||||
val privacyMode = dlist.privacyMode.toLocalPrivacyMode()
|
||||
|
||||
val dlistId = if (distributionId == DistributionId.MY_STORY) {
|
||||
setPrivacyMode(DistributionListId.MY_STORY, privacyMode)
|
||||
members.forEach { addMemberToList(DistributionListId.MY_STORY, privacyMode, it) }
|
||||
setAllowsReplies(DistributionListId.MY_STORY, dlist.allowReplies)
|
||||
DistributionListId.MY_STORY
|
||||
} else {
|
||||
createList(
|
||||
name = dlist.name,
|
||||
members = members,
|
||||
distributionId = distributionId,
|
||||
allowsReplies = dlist.allowReplies,
|
||||
deletionTimestamp = dlistItem.deletionTimestamp ?: 0,
|
||||
storageId = null,
|
||||
privacyMode = privacyMode
|
||||
)!!
|
||||
}
|
||||
val dlistId = createList(
|
||||
name = dlist.name,
|
||||
members = members,
|
||||
distributionId = distributionId,
|
||||
allowsReplies = dlist.allowReplies,
|
||||
deletionTimestamp = dlistItem.deletionTimestamp ?: 0,
|
||||
storageId = null,
|
||||
privacyMode = privacyMode
|
||||
)!!
|
||||
|
||||
return SignalDatabase.distributionLists.getRecipientId(dlistId)!!
|
||||
}
|
||||
|
||||
fun DistributionListTables.clearAllDataForBackupRestore() {
|
||||
writableDatabase
|
||||
.deleteAll(DistributionListTables.ListTable.TABLE_NAME)
|
||||
|
||||
writableDatabase
|
||||
.deleteAll(DistributionListTables.MembershipTable.TABLE_NAME)
|
||||
writableDatabase.deleteAll(DistributionListTables.ListTable.TABLE_NAME)
|
||||
writableDatabase.deleteAll(DistributionListTables.MembershipTable.TABLE_NAME)
|
||||
}
|
||||
|
||||
private fun DistributionListPrivacyMode.toBackupPrivacyMode(): BackupDistributionList.PrivacyMode {
|
||||
|
||||
@@ -45,6 +45,7 @@ fun ThreadTable.getThreadsForBackup(): ChatIterator {
|
||||
${RecipientTable.TABLE_NAME}.${RecipientTable.CUSTOM_CHAT_COLORS_ID}
|
||||
FROM ${ThreadTable.TABLE_NAME}
|
||||
LEFT OUTER JOIN ${RecipientTable.TABLE_NAME} ON ${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} = ${RecipientTable.TABLE_NAME}.${RecipientTable.ID}
|
||||
WHERE ${ThreadTable.ACTIVE} = 1
|
||||
"""
|
||||
val cursor = readableDatabase.query(query)
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.push.UsernameLinkComponents
|
||||
import org.whispersystems.signalservice.api.subscriptions.SubscriberId
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil
|
||||
import org.whispersystems.signalservice.api.util.toByteArray
|
||||
import java.util.Currency
|
||||
|
||||
object AccountDataProcessor {
|
||||
@@ -48,6 +49,15 @@ object AccountDataProcessor {
|
||||
familyName = selfRecord.signalProfileName.familyName,
|
||||
avatarUrlPath = selfRecord.signalProfileAvatar ?: "",
|
||||
username = selfRecord.username,
|
||||
usernameLink = if (signalStore.accountValues.usernameLink != null) {
|
||||
AccountData.UsernameLink(
|
||||
entropy = signalStore.accountValues.usernameLink?.entropy?.toByteString() ?: EMPTY,
|
||||
serverId = signalStore.accountValues.usernameLink?.serverId?.toByteArray()?.toByteString() ?: EMPTY,
|
||||
color = signalStore.miscValues.usernameQrCodeColorScheme.toBackupUsernameColor() ?: AccountData.UsernameLink.Color.BLUE
|
||||
)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
accountSettings = AccountData.AccountSettings(
|
||||
storyViewReceiptsEnabled = signalStore.storyValues.viewedReceiptsEnabled,
|
||||
typingIndicators = TextSecurePreferences.isTypingIndicatorsEnabled(context),
|
||||
@@ -73,12 +83,6 @@ object AccountDataProcessor {
|
||||
)
|
||||
}
|
||||
|
||||
private fun InAppPaymentSubscriberRecord.toSubscriberData(manuallyCancelled: Boolean): AccountData.SubscriberData {
|
||||
val subscriberId = subscriberId.bytes.toByteString()
|
||||
val currencyCode = currency.currencyCode
|
||||
return AccountData.SubscriberData(subscriberId = subscriberId, currencyCode = currencyCode, manuallyCancelled = manuallyCancelled)
|
||||
}
|
||||
|
||||
fun import(accountData: AccountData, selfId: RecipientId) {
|
||||
SignalDatabase.recipients.restoreSelfFromBackup(accountData, selfId)
|
||||
|
||||
@@ -181,4 +185,23 @@ object AccountDataProcessor {
|
||||
else -> UsernameQrCodeColorScheme.Blue
|
||||
}
|
||||
}
|
||||
|
||||
private fun UsernameQrCodeColorScheme.toBackupUsernameColor(): AccountData.UsernameLink.Color {
|
||||
return when (this) {
|
||||
UsernameQrCodeColorScheme.Blue -> AccountData.UsernameLink.Color.BLUE
|
||||
UsernameQrCodeColorScheme.White -> AccountData.UsernameLink.Color.WHITE
|
||||
UsernameQrCodeColorScheme.Grey -> AccountData.UsernameLink.Color.GREY
|
||||
UsernameQrCodeColorScheme.Tan -> AccountData.UsernameLink.Color.OLIVE
|
||||
UsernameQrCodeColorScheme.Green -> AccountData.UsernameLink.Color.GREEN
|
||||
UsernameQrCodeColorScheme.Orange -> AccountData.UsernameLink.Color.ORANGE
|
||||
UsernameQrCodeColorScheme.Pink -> AccountData.UsernameLink.Color.PINK
|
||||
UsernameQrCodeColorScheme.Purple -> AccountData.UsernameLink.Color.PURPLE
|
||||
}
|
||||
}
|
||||
|
||||
private fun InAppPaymentSubscriberRecord.toSubscriberData(manuallyCancelled: Boolean): AccountData.SubscriberData {
|
||||
val subscriberId = subscriberId.bytes.toByteString()
|
||||
val currencyCode = currency.currencyCode
|
||||
return AccountData.SubscriberData(subscriberId = subscriberId, currencyCode = currencyCode, manuallyCancelled = manuallyCancelled)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ object RecipientBackupProcessor {
|
||||
val selfId = db.recipientTable.getByAci(signalStore.accountValues.aci!!).get().toLong()
|
||||
val releaseChannelId = signalStore.releaseChannelValues.releaseChannelRecipientId
|
||||
if (releaseChannelId != null) {
|
||||
state.recipientIds.add(releaseChannelId.toLong())
|
||||
emitter.emit(
|
||||
Frame(
|
||||
recipient = BackupRecipient(
|
||||
|
||||
@@ -57,7 +57,7 @@ class InternalBackupPlaygroundViewModel : ViewModel() {
|
||||
_state.value = _state.value.copy(backupState = BackupState.EXPORT_IN_PROGRESS)
|
||||
val plaintext = _state.value.plaintext
|
||||
|
||||
disposables += Single.fromCallable { BackupRepository.export(plaintext = plaintext) }
|
||||
disposables += Single.fromCallable { BackupRepository.debugExport(plaintext = plaintext) }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { data ->
|
||||
|
||||
@@ -186,7 +186,7 @@ public final class ConversationUpdateItem extends FrameLayout
|
||||
shouldCollapse(messageRecord, nextMessageRecord),
|
||||
hasWallpaper);
|
||||
|
||||
presentActionButton(hasWallpaper, conversationMessage.getMessageRecord().isBoostRequest());
|
||||
presentActionButton(hasWallpaper, conversationMessage.getMessageRecord().isReleaseChannelDonationRequest());
|
||||
|
||||
updateSelectedState();
|
||||
}
|
||||
@@ -538,7 +538,7 @@ public final class ConversationUpdateItem extends FrameLayout
|
||||
eventListener.onBlockJoinRequest(conversationMessage.getMessageRecord().getFromRecipient());
|
||||
}
|
||||
});
|
||||
} else if (conversationMessage.getMessageRecord().isBoostRequest()) {
|
||||
} else if (conversationMessage.getMessageRecord().isReleaseChannelDonationRequest()) {
|
||||
actionButton.setVisibility(VISIBLE);
|
||||
actionButton.setOnClickListener(v -> {
|
||||
if (batchSelected.isEmpty() && eventListener != null) {
|
||||
|
||||
@@ -650,7 +650,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind
|
||||
return emphasisAdded(context, context.getString(R.string.ThreadRecord_message_could_not_be_processed), defaultTint);
|
||||
} else if (MessageTypes.isProfileChange(thread.getType())) {
|
||||
return emphasisAdded(context, "", defaultTint);
|
||||
} else if (MessageTypes.isChangeNumber(thread.getType()) || MessageTypes.isBoostRequest(thread.getType())) {
|
||||
} else if (MessageTypes.isChangeNumber(thread.getType()) || MessageTypes.isReleaseChannelDonationRequest(thread.getType())) {
|
||||
return emphasisAdded(context, "", defaultTint);
|
||||
} else if (MessageTypes.isBadDecryptType(thread.getType())) {
|
||||
return emphasisAdded(context, context.getString(R.string.ThreadRecord_delivery_issue), defaultTint);
|
||||
|
||||
@@ -411,11 +411,8 @@ class DistributionListTables constructor(context: Context?, databaseHelper: Sign
|
||||
}
|
||||
|
||||
return when (privacyMode) {
|
||||
DistributionListPrivacyMode.ALL -> {
|
||||
SignalDatabase.recipients
|
||||
.getSignalContacts(false)!!
|
||||
.readToList { it.requireObject(RecipientTable.ID, RecipientId.SERIALIZER) }
|
||||
}
|
||||
DistributionListPrivacyMode.ALL -> emptyList()
|
||||
DistributionListPrivacyMode.ONLY_WITH -> rawMembers
|
||||
DistributionListPrivacyMode.ALL_EXCEPT -> {
|
||||
SignalDatabase.recipients
|
||||
.getSignalContacts(false)!!
|
||||
@@ -424,7 +421,6 @@ class DistributionListTables constructor(context: Context?, databaseHelper: Sign
|
||||
mapper = { it.requireObject(RecipientTable.ID, RecipientId.SERIALIZER) }
|
||||
)
|
||||
}
|
||||
DistributionListPrivacyMode.ONLY_WITH -> rawMembers
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,7 +473,7 @@ class DistributionListTables constructor(context: Context?, databaseHelper: Sign
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPrivacyMode(listId: DistributionListId): DistributionListPrivacyMode {
|
||||
fun getPrivacyMode(listId: DistributionListId): DistributionListPrivacyMode {
|
||||
return readableDatabase
|
||||
.select(ListTable.PRIVACY_MODE)
|
||||
.from(ListTable.TABLE_NAME)
|
||||
|
||||
@@ -420,7 +420,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
${MessageTypes.PROFILE_CHANGE_TYPE},
|
||||
${MessageTypes.GV1_MIGRATION_TYPE},
|
||||
${MessageTypes.CHANGE_NUMBER_TYPE},
|
||||
${MessageTypes.BOOST_REQUEST_TYPE},
|
||||
${MessageTypes.RELEASE_CHANNEL_DONATION_REQUEST_TYPE},
|
||||
${MessageTypes.SMS_EXPORT_TYPE}
|
||||
)
|
||||
ORDER BY $DATE_RECEIVED DESC LIMIT 1
|
||||
@@ -1237,7 +1237,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
DATE_RECEIVED to System.currentTimeMillis(),
|
||||
DATE_SENT to System.currentTimeMillis(),
|
||||
READ to 1,
|
||||
TYPE to MessageTypes.BOOST_REQUEST_TYPE,
|
||||
TYPE to MessageTypes.RELEASE_CHANNEL_DONATION_REQUEST_TYPE,
|
||||
THREAD_ID to threadId,
|
||||
BODY to null
|
||||
)
|
||||
@@ -1882,7 +1882,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
$TYPE != ${MessageTypes.PROFILE_CHANGE_TYPE} AND
|
||||
$TYPE != ${MessageTypes.CHANGE_NUMBER_TYPE} AND
|
||||
$TYPE != ${MessageTypes.SMS_EXPORT_TYPE} AND
|
||||
$TYPE != ${MessageTypes.BOOST_REQUEST_TYPE} AND
|
||||
$TYPE != ${MessageTypes.RELEASE_CHANNEL_DONATION_REQUEST_TYPE} AND
|
||||
$TYPE & ${MessageTypes.GROUP_V2_LEAVE_BITS} != ${MessageTypes.GROUP_V2_LEAVE_BITS} AND
|
||||
$TYPE & ${MessageTypes.SPECIAL_TYPES_MASK} != ${MessageTypes.SPECIAL_TYPE_REPORTED_SPAM} AND
|
||||
$TYPE & ${MessageTypes.SPECIAL_TYPES_MASK} != ${MessageTypes.SPECIAL_TYPE_MESSAGE_REQUEST_ACCEPTED}
|
||||
|
||||
@@ -33,24 +33,24 @@ public interface MessageTypes {
|
||||
// Base Types
|
||||
long BASE_TYPE_MASK = 0x1F;
|
||||
|
||||
long INCOMING_AUDIO_CALL_TYPE = 1;
|
||||
long OUTGOING_AUDIO_CALL_TYPE = 2;
|
||||
long MISSED_AUDIO_CALL_TYPE = 3;
|
||||
long JOINED_TYPE = 4;
|
||||
long UNSUPPORTED_MESSAGE_TYPE = 5;
|
||||
long INVALID_MESSAGE_TYPE = 6;
|
||||
long PROFILE_CHANGE_TYPE = 7;
|
||||
long MISSED_VIDEO_CALL_TYPE = 8;
|
||||
long GV1_MIGRATION_TYPE = 9;
|
||||
long INCOMING_VIDEO_CALL_TYPE = 10;
|
||||
long OUTGOING_VIDEO_CALL_TYPE = 11;
|
||||
long GROUP_CALL_TYPE = 12;
|
||||
long BAD_DECRYPT_TYPE = 13;
|
||||
long CHANGE_NUMBER_TYPE = 14;
|
||||
long BOOST_REQUEST_TYPE = 15;
|
||||
long THREAD_MERGE_TYPE = 16;
|
||||
long SMS_EXPORT_TYPE = 17;
|
||||
long SESSION_SWITCHOVER_TYPE = 18;
|
||||
long INCOMING_AUDIO_CALL_TYPE = 1;
|
||||
long OUTGOING_AUDIO_CALL_TYPE = 2;
|
||||
long MISSED_AUDIO_CALL_TYPE = 3;
|
||||
long JOINED_TYPE = 4;
|
||||
long UNSUPPORTED_MESSAGE_TYPE = 5;
|
||||
long INVALID_MESSAGE_TYPE = 6;
|
||||
long PROFILE_CHANGE_TYPE = 7;
|
||||
long MISSED_VIDEO_CALL_TYPE = 8;
|
||||
long GV1_MIGRATION_TYPE = 9;
|
||||
long INCOMING_VIDEO_CALL_TYPE = 10;
|
||||
long OUTGOING_VIDEO_CALL_TYPE = 11;
|
||||
long GROUP_CALL_TYPE = 12;
|
||||
long BAD_DECRYPT_TYPE = 13;
|
||||
long CHANGE_NUMBER_TYPE = 14;
|
||||
long RELEASE_CHANNEL_DONATION_REQUEST_TYPE = 15;
|
||||
long THREAD_MERGE_TYPE = 16;
|
||||
long SMS_EXPORT_TYPE = 17;
|
||||
long SESSION_SWITCHOVER_TYPE = 18;
|
||||
|
||||
long BASE_INBOX_TYPE = 20;
|
||||
long BASE_OUTBOX_TYPE = 21;
|
||||
@@ -59,7 +59,7 @@ public interface MessageTypes {
|
||||
long BASE_SENT_FAILED_TYPE = 24;
|
||||
long BASE_PENDING_SECURE_SMS_FALLBACK = 25;
|
||||
long BASE_PENDING_INSECURE_SMS_FALLBACK = 26;
|
||||
long BASE_DRAFT_TYPE = 27;
|
||||
long BASE_DRAFT_TYPE = 27;
|
||||
|
||||
long[] OUTGOING_MESSAGE_TYPES = { BASE_OUTBOX_TYPE, BASE_SENT_TYPE,
|
||||
BASE_SENDING_TYPE, BASE_SENT_FAILED_TYPE,
|
||||
@@ -351,8 +351,8 @@ public interface MessageTypes {
|
||||
return type == CHANGE_NUMBER_TYPE;
|
||||
}
|
||||
|
||||
static boolean isBoostRequest(long type) {
|
||||
return type == BOOST_REQUEST_TYPE;
|
||||
static boolean isReleaseChannelDonationRequest(long type) {
|
||||
return type == RELEASE_CHANNEL_DONATION_REQUEST_TYPE;
|
||||
}
|
||||
|
||||
static boolean isSmsExport(long type) {
|
||||
|
||||
@@ -1788,10 +1788,6 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
||||
deactivateThread(query = null)
|
||||
}
|
||||
|
||||
private fun SQLiteDatabase.deactivateThread(threadId: Long) {
|
||||
deactivateThread(SqlUtil.Query("$ID = ?", SqlUtil.buildArgs(threadId)))
|
||||
}
|
||||
|
||||
private fun SQLiteDatabase.deactivateThread(query: SqlUtil.Query?) {
|
||||
val contentValues = contentValuesOf(
|
||||
DATE to 0,
|
||||
@@ -1820,13 +1816,13 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
||||
)
|
||||
|
||||
if (query != null) {
|
||||
writableDatabase
|
||||
this
|
||||
.update(TABLE_NAME)
|
||||
.values(contentValues)
|
||||
.where(query.where, query.whereArgs)
|
||||
.run()
|
||||
} else {
|
||||
writableDatabase
|
||||
this
|
||||
.updateAll(TABLE_NAME)
|
||||
.values(contentValues)
|
||||
.run()
|
||||
@@ -1979,7 +1975,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
||||
return MessageTypes.isProfileChange(type) ||
|
||||
MessageTypes.isGroupV1MigrationEvent(type) ||
|
||||
MessageTypes.isChangeNumber(type) ||
|
||||
MessageTypes.isBoostRequest(type) ||
|
||||
MessageTypes.isReleaseChannelDonationRequest(type) ||
|
||||
MessageTypes.isGroupV2LeaveOnly(type) ||
|
||||
MessageTypes.isThreadMergeType(type)
|
||||
}
|
||||
|
||||
@@ -196,8 +196,8 @@ public abstract class DisplayRecord {
|
||||
return MessageTypes.isChangeNumber(type);
|
||||
}
|
||||
|
||||
public boolean isBoostRequest() {
|
||||
return MessageTypes.isBoostRequest(type);
|
||||
public boolean isReleaseChannelDonationRequest() {
|
||||
return MessageTypes.isReleaseChannelDonationRequest(type);
|
||||
}
|
||||
|
||||
public int getDeliveryStatus() {
|
||||
|
||||
@@ -232,7 +232,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
return getProfileChangeDescription(context);
|
||||
} else if (isChangeNumber()) {
|
||||
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_s_changed_their_phone_number, r.getDisplayName(context)), R.drawable.ic_phone_16);
|
||||
} else if (isBoostRequest()) {
|
||||
} else if (isReleaseChannelDonationRequest()) {
|
||||
return staticUpdateDescription(context.getString(R.string.MessageRecord_like_this_new_feature_help_support_signal_with_a_one_time_donation), 0);
|
||||
} else if (isEndSession()) {
|
||||
if (isOutgoing()) return staticUpdateDescription(context.getString(R.string.SmsMessageRecord_secure_session_reset), R.drawable.ic_update_info_16);
|
||||
@@ -684,7 +684,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
return isGroupAction() || isJoined() || isExpirationTimerUpdate() || isCallLog() ||
|
||||
isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() ||
|
||||
isProfileChange() || isGroupV1MigrationEvent() || isChatSessionRefresh() || isBadDecryptType() ||
|
||||
isChangeNumber() || isBoostRequest() || isThreadMergeEventType() || isSmsExportType() || isSessionSwitchoverEventType() ||
|
||||
isChangeNumber() || isReleaseChannelDonationRequest() || isThreadMergeEventType() || isSmsExportType() || isSessionSwitchoverEventType() ||
|
||||
isPaymentsRequestToActivate() || isPaymentsActivated() || isReportedSpam() || isMessageRequestAccepted();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user