Present a notification when we discover you have consumed your media tier quota

This commit is contained in:
Harry
2025-10-24 14:24:33 -07:00
committed by GitHub
parent b5133f72b6
commit 3572362892
9 changed files with 64 additions and 8 deletions

View File

@@ -43,8 +43,8 @@ public class NotificationActionHandler {
break
case .showLinkedDevices:
showLinkedDevices()
case .showBackupsEnabled:
showBackupsEnabled()
case .showBackupsSettings:
showBackupsSettings()
case .listMediaIntegrityCheck:
await submitDebugLogs(supportTag: "BackupsMedia")
}
@@ -374,7 +374,7 @@ public class NotificationActionHandler {
}
@MainActor
private class func showBackupsEnabled() {
private class func showBackupsSettings() {
SignalApp.shared.showAppSettings(mode: .backups)
}

View File

@@ -886,6 +886,12 @@
/* Title for a toggle allowing users to change the Optimize Local Storage setting. */
"BACKUP_SETTINGS_OPTIMIZE_LOCAL_STORAGE_TOGGLE_TITLE" = "Optimize On-Device Storage";
/* Subtitle for a notification telling the user they are out of remote storage space. */
"BACKUP_SETTINGS_OUT_OF_STORAGE_SPACE_NOTIFICATION_SUBTITLE" = "Youve reached your backup storage limit. Free up space in Signal to continue backing up chats and media.";
/* Title for a notification telling the user they are out of remote storage space. */
"BACKUP_SETTINGS_OUT_OF_STORAGE_SPACE_NOTIFICATION_TITLE" = "Backup Storage Full";
/* Title for a button allowing users to re-enable Backups, after it had been previously disabled. */
"BACKUP_SETTINGS_REENABLE_BACKUPS_BUTTON_TITLE" = "Re-enable Backups";

View File

@@ -55,6 +55,7 @@ class BackupAttachmentUploadQueueRunnerImpl: BackupAttachmentUploadQueueRunner {
backupSettingsStore: BackupSettingsStore,
dateProvider: @escaping DateProvider,
db: any DB,
notificationPresenter: NotificationPresenter,
orphanedBackupAttachmentStore: OrphanedBackupAttachmentStore,
progress: BackupAttachmentUploadProgress,
statusManager: BackupAttachmentUploadQueueStatusManager,
@@ -88,6 +89,7 @@ class BackupAttachmentUploadQueueRunnerImpl: BackupAttachmentUploadQueueRunner {
db: db,
listMediaManager: backupListMediaManager,
logger: logger,
notificationPresenter: notificationPresenter,
orphanedBackupAttachmentStore: orphanedBackupAttachmentStore,
progress: progress,
statusManager: statusManager,
@@ -250,6 +252,7 @@ class BackupAttachmentUploadQueueRunnerImpl: BackupAttachmentUploadQueueRunner {
private let db: any DB
private let listMediaManager: BackupListMediaManager
private let logger: PrefixedLogger
private let notificationPresenter: NotificationPresenter
private let orphanedBackupAttachmentStore: OrphanedBackupAttachmentStore
private let progress: BackupAttachmentUploadProgress
private let statusManager: BackupAttachmentUploadQueueStatusManager
@@ -272,6 +275,7 @@ class BackupAttachmentUploadQueueRunnerImpl: BackupAttachmentUploadQueueRunner {
db: any DB,
listMediaManager: BackupListMediaManager,
logger: PrefixedLogger,
notificationPresenter: NotificationPresenter,
orphanedBackupAttachmentStore: OrphanedBackupAttachmentStore,
progress: BackupAttachmentUploadProgress,
statusManager: BackupAttachmentUploadQueueStatusManager,
@@ -289,6 +293,7 @@ class BackupAttachmentUploadQueueRunnerImpl: BackupAttachmentUploadQueueRunner {
self.db = db
self.listMediaManager = listMediaManager
self.logger = logger
self.notificationPresenter = notificationPresenter
self.orphanedBackupAttachmentStore = orphanedBackupAttachmentStore
self.progress = progress
self.statusManager = statusManager
@@ -541,8 +546,18 @@ class BackupAttachmentUploadQueueRunnerImpl: BackupAttachmentUploadQueueRunner {
}
fallthrough
case .outOfCapacity:
await db.awaitableWrite { tx in
backupSettingsStore.setHasConsumedMediaTierCapacity(true, tx: tx)
let didSetConsumeMediaTierCapacity = await db.awaitableWrite { tx in
if !backupSettingsStore.hasConsumedMediaTierCapacity(tx: tx) {
backupSettingsStore.setHasConsumedMediaTierCapacity(true, tx: tx)
return true
} else {
return false
}
}
if didSetConsumeMediaTierCapacity {
await MainActor.run { [notificationPresenter] in
notificationPresenter.notifyUserOfMediaTierQuotaConsumed()
}
}
let error = OutOfCapacityError()
try? await loader.stop(reason: error)

View File

@@ -707,6 +707,7 @@ extension AppSetup.GlobalsContinuation {
backupSettingsStore: backupSettingsStore,
dateProvider: dateProvider,
db: db,
notificationPresenter: notificationPresenter,
orphanedBackupAttachmentStore: orphanedBackupAttachmentStore,
progress: backupAttachmentUploadProgress,
statusManager: backupAttachmentUploadQueueStatusManager,

View File

@@ -120,6 +120,10 @@ public class NoopNotificationPresenterImpl: NotificationPresenter {
Logger.warn("")
}
public func notifyUserOfMediaTierQuotaConsumed() {
Logger.warn("")
}
public func notifyUserOfListMediaIntegrityCheckFailure() {
Logger.warn("")
}

View File

@@ -58,6 +58,8 @@ public protocol NotificationPresenter {
func scheduleNotifyForBackupsEnabled(backupsTimestamp: Date)
func notifyUserOfMediaTierQuotaConsumed()
func notifyUserOfListMediaIntegrityCheckFailure()
/// Notify user to relaunch the app after we deliberately terminate when an incoming device transfer completes.

View File

@@ -36,6 +36,7 @@ public enum AppNotificationCategory: CaseIterable {
case deregistration
case newDeviceLinked
case backupsEnabled
case backupsMediaTierQuotaConsumed
case listMediaIntegrityCheckFailure
case pollEndNotification
case pollVoteNotification
@@ -67,7 +68,7 @@ public enum AppNotificationDefaultAction: String {
case reregister
case showChatList
case showLinkedDevices
case showBackupsEnabled
case showBackupsSettings
case listMediaIntegrityCheck
}
@@ -197,6 +198,8 @@ extension AppNotificationCategory {
return "Signal.AppNotificationCategory.newDeviceLinked"
case .backupsEnabled:
return "Signal.AppNotificationCategory.backupsEnabled"
case .backupsMediaTierQuotaConsumed:
return "Signal.AppNotificationCategory.backupsMediaTierQuotaConsumed"
case .listMediaIntegrityCheckFailure:
return "Signal.AppNotificationCategory.listMediaIntegrityCheckFailure"
case .pollEndNotification:
@@ -241,6 +244,8 @@ extension AppNotificationCategory {
return []
case .backupsEnabled:
return []
case .backupsMediaTierQuotaConsumed:
return []
case .listMediaIntegrityCheckFailure:
return []
case .pollEndNotification:
@@ -1175,7 +1180,7 @@ public class NotificationPresenterImpl: NotificationPresenter {
public func scheduleNotifyForBackupsEnabled(backupsTimestamp: Date) {
var userInfo = AppNotificationUserInfo()
userInfo.defaultAction = .showBackupsEnabled
userInfo.defaultAction = .showBackupsSettings
enqueueNotificationAction {
await self.notifyViaPresenter(
category: .backupsEnabled,
@@ -1197,6 +1202,27 @@ public class NotificationPresenterImpl: NotificationPresenter {
}
}
public func notifyUserOfMediaTierQuotaConsumed() {
var userInfo = AppNotificationUserInfo()
userInfo.defaultAction = .showBackupsSettings
enqueueNotificationAction {
await self.notifyViaPresenter(
category: .backupsMediaTierQuotaConsumed,
title: ResolvableValue(resolvedValue: OWSLocalizedString(
"BACKUP_SETTINGS_OUT_OF_STORAGE_SPACE_NOTIFICATION_TITLE",
comment: "Title for a notification telling the user they are out of remote storage space."
)),
body: OWSLocalizedString(
"BACKUP_SETTINGS_OUT_OF_STORAGE_SPACE_NOTIFICATION_SUBTITLE",
comment: "Subtitle for a notification telling the user they are out of remote storage space."
),
threadIdentifier: nil,
userInfo: userInfo,
soundQuery: .global
)
}
}
public func notifyUserOfListMediaIntegrityCheckFailure() {
var userInfo = AppNotificationUserInfo()
userInfo.defaultAction = .listMediaIntegrityCheck

View File

@@ -223,7 +223,8 @@ public class UserNotificationPresenter {
.transferRelaunch,
.deregistration,
.newDeviceLinked,
.backupsEnabled:
.backupsEnabled,
.backupsMediaTierQuotaConsumed:
// Always show these notifications
return true

View File

@@ -561,5 +561,6 @@ private enum CrashyMocks {
func cancelNotifications(reactionId: String) { failTest(Self.self) }
func cancelNotificationsForMissedCalls(threadUniqueId: String) { failTest(Self.self) }
func cancelNotifications(for storyMessage: StoryMessage) { failTest(Self.self) }
func notifyUserOfMediaTierQuotaConsumed() { failTest(Self.self) }
}
}