From 8f47592fc050fd71ad3f09e88e31ca4f24ace359 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Mon, 6 Apr 2026 14:23:23 +0000 Subject: [PATCH] Fix reconciliation error for thumbnails for quotes. --- .../securesms/database/AttachmentTable.kt | 27 ++++++++++++++++--- .../securesms/jobs/BackupMessagesJob.kt | 2 +- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentTable.kt index 180b8dc9d2..30a2c54577 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentTable.kt @@ -422,26 +422,45 @@ class AttachmentTable( } /** - * Returns a list that has any permanently-failed thumbnails removed. + * Filters thumbnail snapshot entries down to only those that have at least one eligible attachment capable of thumbnail upload. */ - fun filterPermanentlyFailedThumbnails(entries: Set): Set { + fun filterThumbnailsWithoutEligibleAttachment(entries: Set): Set { + if (entries.isEmpty()) { + return entries + } + val entriesByMediaName: MutableMap = entries .associateBy { MediaName.fromPlaintextHashAndRemoteKeyForThumbnail(it.plaintextHash, it.remoteKey).name } .toMutableMap() + val eligibleMediaNames: MutableSet = mutableSetOf() + readableDatabase .select(DATA_HASH_END, REMOTE_KEY) .from(TABLE_NAME) - .where("$DATA_HASH_END NOT NULL AND $REMOTE_KEY NOT NULL AND $ARCHIVE_THUMBNAIL_TRANSFER_STATE = ${ArchiveTransferState.PERMANENT_FAILURE.value}") + .where( + """ + $DATA_HASH_END NOT NULL AND + $REMOTE_KEY NOT NULL AND + $DATA_FILE NOT NULL AND + $TRANSFER_STATE = $TRANSFER_PROGRESS_DONE AND + $QUOTE = 0 AND + $ARCHIVE_THUMBNAIL_TRANSFER_STATE != ${ArchiveTransferState.PERMANENT_FAILURE.value} + """ + ) .run() .forEach { cursor -> val hashEnd = cursor.requireNonNullString(DATA_HASH_END) val remoteKey = cursor.requireNonNullString(REMOTE_KEY) val thumbnailMediaName = MediaName.fromPlaintextHashAndRemoteKeyForThumbnail(Base64.decode(hashEnd), Base64.decode(remoteKey)).name - entriesByMediaName.remove(thumbnailMediaName) + if (thumbnailMediaName in entriesByMediaName) { + eligibleMediaNames += thumbnailMediaName + } } + entriesByMediaName.keys.retainAll(eligibleMediaNames) + return entriesByMediaName.values.toSet() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/BackupMessagesJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/BackupMessagesJob.kt index 8dd7ae509c..47dc81550a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/BackupMessagesJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/BackupMessagesJob.kt @@ -617,7 +617,7 @@ class BackupMessagesJob private constructor( ) } .toSet() - .let { SignalDatabase.attachments.filterPermanentlyFailedThumbnails(it) } + .let { SignalDatabase.attachments.filterThumbnailsWithoutEligibleAttachment(it) } } class Factory : Job.Factory {