From faa6d743c047fdac326738c8b25f4050c1332e04 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Fri, 1 Nov 2024 13:23:57 -0300 Subject: [PATCH] Add support for watermarking backup failure sheet. --- .../securesms/backup/v2/BackupRepository.kt | 18 +++++------ .../securesms/keyvalue/BackupValues.kt | 32 ++++++++++++++++++- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt index 759d8287a3..9be2e667f4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt @@ -93,7 +93,6 @@ import java.io.OutputStream import java.time.ZonedDateTime import java.util.Locale import java.util.concurrent.atomic.AtomicLong -import kotlin.time.Duration.Companion.days import kotlin.time.Duration.Companion.milliseconds import org.signal.libsignal.messagebackup.MessageBackupKey as LibSignalMessageBackupKey @@ -158,6 +157,13 @@ object BackupRepository { SignalStore.backup.updateMessageBackupFailureWatermark() } + /** + * Updates the watermark for the sheet display. + */ + fun markBackupFailedSheetDismissed() { + SignalStore.backup.updateMessageBackupFailureSheetWatermark() + } + /** * Whether or not the "Could not complete backup" sheet should be displayed. */ @@ -167,15 +173,7 @@ object BackupRepository { return false } - val lastBackupTime = SignalStore.backup.lastBackupTime.milliseconds - val isTimeoutElapsed = when (SignalStore.backup.backupFrequency) { - BackupFrequency.DAILY -> lastBackupTime > 7.days - BackupFrequency.WEEKLY -> lastBackupTime > 14.days - BackupFrequency.MONTHLY -> lastBackupTime > 44.days - BackupFrequency.MANUAL -> false - } - - return isTimeoutElapsed && false // TODO [backups] -- watermarking necessary, otherwise this'll show up on every resume. + return System.currentTimeMillis().milliseconds > SignalStore.backup.nextBackupFailureSheetSnoozeTime } private fun shouldNotDisplayBackupFailedMessaging(): Boolean { diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/BackupValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/BackupValues.kt index 86e60776d1..f694cc9aa9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/BackupValues.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/BackupValues.kt @@ -55,6 +55,7 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) { private const val KEY_BACKUP_FAIL = "backup.failed" private const val KEY_BACKUP_FAIL_ACKNOWLEDGED_SNOOZE_TIME = "backup.failed.acknowledged.snooze.time" private const val KEY_BACKUP_FAIL_ACKNOWLEDGED_SNOOZE_COUNT = "backup.failed.acknowledged.snooze.count" + private const val KEY_BACKUP_FAIL_SHEET_SNOOZE_TIME = "backup.failed.sheet.snooze" private const val KEY_MEDIA_ROOT_BACKUP_KEY = "backup.mediaRootBackupKey" @@ -78,7 +79,13 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) { var backupWithCellular: Boolean by booleanValue(KEY_BACKUP_OVER_CELLULAR, false) var nextBackupTime: Long by longValue(KEY_NEXT_BACKUP_TIME, -1) - var lastBackupTime: Long by longValue(KEY_LAST_BACKUP_TIME, -1) + var lastBackupTime: Long + get() = getLong(KEY_LAST_BACKUP_TIME, -1) + set(value) { + putLong(KEY_LAST_BACKUP_TIME, value) + clearMessageBackupFailureSheetWatermark() + } + var lastMediaSyncTime: Long by longValue(KEY_LAST_BACKUP_MEDIA_SYNC_TIME, -1) var backupFrequency: BackupFrequency by enumValue(KEY_BACKUP_FREQUENCY, BackupFrequency.MANUAL, BackupFrequency.Serializer) @@ -165,6 +172,7 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) { val hasBackupFailure: Boolean = getBoolean(KEY_BACKUP_FAIL, false) val nextBackupFailureSnoozeTime: Duration get() = getLong(KEY_BACKUP_FAIL_ACKNOWLEDGED_SNOOZE_TIME, 0L).milliseconds + val nextBackupFailureSheetSnoozeTime: Duration get() = getLong(KEY_BACKUP_FAIL_SHEET_SNOOZE_TIME, getNextBackupFailureSheetSnoozeTime(lastBackupTime.milliseconds).inWholeMilliseconds).milliseconds /** * Call when the user disables backups. Clears/resets all relevant fields. @@ -287,6 +295,28 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) { putBoolean(KEY_BACKUP_FAIL, false) } + fun updateMessageBackupFailureSheetWatermark() { + val lastSnoozeTime = getLong(KEY_BACKUP_FAIL_SHEET_SNOOZE_TIME, lastBackupTime).milliseconds + val nextSnoozeTime = getNextBackupFailureSheetSnoozeTime(lastSnoozeTime) + + putLong(KEY_BACKUP_FAIL_SHEET_SNOOZE_TIME, nextSnoozeTime.inWholeMilliseconds) + } + + private fun clearMessageBackupFailureSheetWatermark() { + remove(KEY_BACKUP_FAIL_SHEET_SNOOZE_TIME) + } + + private fun getNextBackupFailureSheetSnoozeTime(previous: Duration): Duration { + val timeoutPerSnooze = when (SignalStore.backup.backupFrequency) { + BackupFrequency.DAILY -> 7.days + BackupFrequency.WEEKLY -> 14.days + BackupFrequency.MONTHLY -> 14.days + BackupFrequency.MANUAL -> Int.MAX_VALUE.days + } + + return previous + timeoutPerSnooze + } + class SerializedCredentials( @JsonProperty val credentialsByDay: Map