mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 17:29:32 +01:00
Add new dialog and sheet for handling offloaded media after a subscription is canceled or expires.
This commit is contained in:
committed by
Greyson Parrelli
parent
18b5354944
commit
1424dd6892
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.keyvalue
|
||||
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.keyvalue.BackupValues.Companion.TAG
|
||||
import org.thoughtcrime.securesms.keyvalue.protos.BackupDownloadNotifierState
|
||||
import kotlin.math.max
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.days
|
||||
import kotlin.time.Duration.Companion.hours
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
/**
|
||||
* Manages setting and snoozing notifiers informing the user to download their backup
|
||||
* before it is deleted from the Signal service.
|
||||
*
|
||||
* This is only meant to be delegated to from [BackupValues]
|
||||
*/
|
||||
object BackupDownloadNotifierUtil {
|
||||
|
||||
/**
|
||||
* Sets the notifier to trigger half way between now and the entitlement expiration time.
|
||||
*
|
||||
* @param state The current state, or null.
|
||||
* @param entitlementExpirationTime The time the user's backup entitlement expires
|
||||
* @param now The current time, for testing.
|
||||
*
|
||||
* @return the new state value.
|
||||
*/
|
||||
fun setDownloadNotifierToTriggerAtHalfwayPoint(
|
||||
state: BackupDownloadNotifierState?,
|
||||
entitlementExpirationTime: Duration,
|
||||
now: Duration = System.currentTimeMillis().milliseconds
|
||||
): BackupDownloadNotifierState? {
|
||||
if (state?.entitlementExpirationSeconds == entitlementExpirationTime.inWholeSeconds) {
|
||||
Log.d(TAG, "Entitlement expiration time already present.")
|
||||
return state
|
||||
}
|
||||
|
||||
if (now >= entitlementExpirationTime) {
|
||||
Log.i(TAG, "Entitlement expiration time is in the past. Clearing state.")
|
||||
return null
|
||||
}
|
||||
|
||||
val timeRemaining = entitlementExpirationTime - now
|
||||
val halfWayPoint = (entitlementExpirationTime - timeRemaining / 2)
|
||||
val lastDay = entitlementExpirationTime - 1.days
|
||||
|
||||
val nextIntervalSeconds: Duration = when {
|
||||
timeRemaining <= 1.days -> 0.seconds
|
||||
timeRemaining <= 4.days -> lastDay - now
|
||||
else -> halfWayPoint - now
|
||||
}
|
||||
|
||||
return BackupDownloadNotifierState(
|
||||
entitlementExpirationSeconds = entitlementExpirationTime.inWholeSeconds,
|
||||
lastSheetDisplaySeconds = now.inWholeSeconds,
|
||||
intervalSeconds = nextIntervalSeconds.inWholeSeconds,
|
||||
type = BackupDownloadNotifierState.Type.SHEET
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the notifier to trigger either one day before or four hours before expiration.
|
||||
*
|
||||
* @param state The current state, or null.
|
||||
* @param now The current time, for testing.
|
||||
*
|
||||
* @return The new state value.
|
||||
*/
|
||||
fun snoozeDownloadNotifier(
|
||||
state: BackupDownloadNotifierState?,
|
||||
now: Duration = System.currentTimeMillis().milliseconds
|
||||
): BackupDownloadNotifierState? {
|
||||
state ?: return null
|
||||
|
||||
if (state.type == BackupDownloadNotifierState.Type.DIALOG) {
|
||||
Log.i(TAG, "Clearing state after dismissing download notifier dialog.")
|
||||
return null
|
||||
}
|
||||
|
||||
val lastDay = state.entitlementExpirationSeconds.seconds - 1.days
|
||||
|
||||
return if (now >= lastDay) {
|
||||
val fourHoursPriorToExpiration = state.entitlementExpirationSeconds.seconds - 4.hours
|
||||
|
||||
state.newBuilder()
|
||||
.lastSheetDisplaySeconds(now.inWholeSeconds)
|
||||
.intervalSeconds(max(0L, (fourHoursPriorToExpiration - now).inWholeSeconds))
|
||||
.type(BackupDownloadNotifierState.Type.DIALOG)
|
||||
.build()
|
||||
} else {
|
||||
val timeUntilLastDay = lastDay - now
|
||||
|
||||
state.newBuilder()
|
||||
.lastSheetDisplaySeconds(now.inWholeSeconds)
|
||||
.intervalSeconds(timeUntilLastDay.inWholeSeconds)
|
||||
.type(BackupDownloadNotifierState.Type.SHEET)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NoRemoteArchiveGarbageCollectionPendingConstraint
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.RestoreAttachmentConstraintObserver
|
||||
import org.thoughtcrime.securesms.keyvalue.protos.ArchiveUploadProgressState
|
||||
import org.thoughtcrime.securesms.keyvalue.protos.BackupDownloadNotifierState
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.whispersystems.signalservice.api.archive.ArchiveServiceCredential
|
||||
@@ -52,6 +53,7 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
|
||||
private const val KEY_CDN_MEDIA_PATH = "backup.cdn.mediaPath"
|
||||
|
||||
private const val KEY_BACKUP_DOWNLOAD_NOTIFIER_STATE = "backup.downloadNotifierState"
|
||||
private const val KEY_BACKUP_OVER_CELLULAR = "backup.useCellular"
|
||||
private const val KEY_RESTORE_OVER_CELLULAR = "backup.restore.useCellular"
|
||||
private const val KEY_OPTIMIZE_STORAGE = "backup.optimizeStorage"
|
||||
@@ -97,6 +99,9 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
var optimizeStorage: Boolean by booleanValue(KEY_OPTIMIZE_STORAGE, false)
|
||||
var backupWithCellular: Boolean by booleanValue(KEY_BACKUP_OVER_CELLULAR, false)
|
||||
|
||||
var backupDownloadNotifierState: BackupDownloadNotifierState? by protoValue(KEY_BACKUP_DOWNLOAD_NOTIFIER_STATE, BackupDownloadNotifierState.ADAPTER)
|
||||
private set
|
||||
|
||||
var restoreWithCellular: Boolean
|
||||
get() = getBoolean(KEY_RESTORE_OVER_CELLULAR, false)
|
||||
set(value) {
|
||||
@@ -252,6 +257,28 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
*/
|
||||
var spaceAvailableOnDiskBytes: Long by longValue(KEY_BACKUP_FAIL_SPACE_REMAINING, -1L)
|
||||
|
||||
/**
|
||||
* Sets the notifier to trigger half way between now and the entitlement expiration time.
|
||||
*/
|
||||
fun setDownloadNotifierToTriggerAtHalfwayPoint(entitlementExpirationTime: Duration) {
|
||||
backupDownloadNotifierState = BackupDownloadNotifierUtil.setDownloadNotifierToTriggerAtHalfwayPoint(backupDownloadNotifierState, entitlementExpirationTime)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the notifier to trigger 24hrs before the end of the grace period.
|
||||
*
|
||||
*/
|
||||
fun snoozeDownloadNotifier() {
|
||||
backupDownloadNotifierState = BackupDownloadNotifierUtil.snoozeDownloadNotifier(backupDownloadNotifierState)
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the notifier state, done when the user subscribes to the paid tier.
|
||||
*/
|
||||
fun clearDownloadNotifierState() {
|
||||
backupDownloadNotifierState = null
|
||||
}
|
||||
|
||||
fun internalSetBackupFailedErrorState() {
|
||||
markMessageBackupFailure()
|
||||
putLong(KEY_BACKUP_FAIL_SHEET_SNOOZE_TIME, 0)
|
||||
|
||||
Reference in New Issue
Block a user