Skip to content

Commit f08f086

Browse files
Add dedicated "low power mode" paused case for Backup upload/download
1 parent eee7318 commit f08f086

11 files changed

+142
-33
lines changed

Signal/Backups/BackupSettingsAttachmentDownloadTracker.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ final class BackupSettingsAttachmentDownloadTracker {
1111
case suspended
1212
case running
1313
case pausedLowBattery
14+
case pausedLowPowerMode
1415
case pausedNeedsWifi
1516
case pausedNeedsInternet
1617
case outOfDiskSpace(bytesRequired: UInt64)
@@ -205,6 +206,8 @@ private class Tracker {
205206
return .pausedNeedsInternet
206207
case .lowBattery:
207208
return .pausedLowBattery
209+
case .lowPowerMode:
210+
return .pausedLowPowerMode
208211
case .lowDiskSpace:
209212
return .outOfDiskSpace(bytesRequired: max(
210213
lastReportedDownloadProgress.remainingUnitCount,

Signal/Backups/BackupSettingsAttachmentUploadTracker.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ final class BackupSettingsAttachmentUploadTracker {
1111
enum State {
1212
case running
1313
case pausedLowBattery
14+
case pausedLowPowerMode
1415
case pausedNeedsWifi
1516
case pausedNeedsInternet
1617
}
@@ -186,7 +187,7 @@ private class Tracker {
186187

187188
_state.uploadProgressObserver = nil
188189

189-
case .noWifiReachability, .lowBattery, .noReachability:
190+
case .noWifiReachability, .lowBattery, .lowPowerMode, .noReachability:
190191
break
191192
}
192193

@@ -221,6 +222,8 @@ private class Tracker {
221222
return .pausedNeedsWifi
222223
case .lowBattery:
223224
return .pausedLowBattery
225+
case .lowPowerMode:
226+
return .pausedLowPowerMode
224227
case .empty, .notRegisteredAndReady, .appBackgrounded:
225228
return nil
226229
}

Signal/Backups/BackupSettingsViewController.swift

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ class BackupSettingsViewController:
522522
switch currentDownloadQueueStatus {
523523
case .empty, .suspended, .notRegisteredAndReady, .appBackgrounded:
524524
break
525-
case .running, .noWifiReachability, .noReachability, .lowBattery, .lowDiskSpace:
525+
case .running, .noWifiReachability, .noReachability, .lowBattery, .lowPowerMode, .lowDiskSpace:
526526
OWSActionSheets.showActionSheet(
527527
title: OWSLocalizedString(
528528
"BACKUP_SETTINGS_DISABLING_DOWNLOADS_STARTED_ACTION_SHEET_TITLE",
@@ -1261,7 +1261,7 @@ struct BackupSettingsView: View {
12611261
switch latestDownloadUpdate?.state {
12621262
case nil, .suspended:
12631263
return .disabling
1264-
case .running, .pausedLowBattery, .pausedNeedsWifi, .pausedNeedsInternet, .outOfDiskSpace:
1264+
case .running, .pausedLowBattery, .pausedLowPowerMode, .pausedNeedsWifi, .pausedNeedsInternet, .outOfDiskSpace:
12651265
return .disablingDownloadsRunning(latestDownloadUpdate!)
12661266
}
12671267
}
@@ -1621,7 +1621,7 @@ private struct BackupAttachmentDownloadProgressView: View {
16211621
let progressViewColor: Color? = switch latestDownloadUpdate.state {
16221622
case .suspended:
16231623
nil
1624-
case .running, .pausedLowBattery, .pausedNeedsWifi, .pausedNeedsInternet:
1624+
case .running, .pausedLowBattery, .pausedLowPowerMode, .pausedNeedsWifi, .pausedNeedsInternet:
16251625
.Signal.accent
16261626
case .outOfDiskSpace:
16271627
.yellow
@@ -1662,6 +1662,11 @@ private struct BackupAttachmentDownloadProgressView: View {
16621662
"BACKUP_SETTINGS_DOWNLOAD_PROGRESS_SUBTITLE_PAUSED_LOW_BATTERY",
16631663
comment: "Subtitle for a progress bar tracking downloads that are paused because of low battery."
16641664
)
1665+
case .pausedLowPowerMode:
1666+
OWSLocalizedString(
1667+
"BACKUP_SETTINGS_DOWNLOAD_PROGRESS_SUBTITLE_PAUSED_LOW_POWER_MODE",
1668+
comment: "Subtitle for a progress bar tracking downloads that are paused because of low power mode."
1669+
)
16651670
case .pausedNeedsWifi:
16661671
OWSLocalizedString(
16671672
"BACKUP_SETTINGS_DOWNLOAD_PROGRESS_SUBTITLE_PAUSED_NEEDS_WIFI",
@@ -1742,7 +1747,7 @@ private struct BackupAttachmentDownloadProgressView: View {
17421747
}
17431748
}
17441749
.foregroundStyle(Color.Signal.label)
1745-
case .pausedLowBattery, .pausedNeedsInternet:
1750+
case .pausedLowBattery, .pausedLowPowerMode, .pausedNeedsInternet:
17461751
EmptyView()
17471752
}
17481753
}
@@ -1787,6 +1792,11 @@ private struct BackupAttachmentUploadProgressView: View {
17871792
"BACKUP_SETTINGS_UPLOAD_PROGRESS_SUBTITLE_PAUSED_LOW_BATTERY",
17881793
comment: "Subtitle for a progress bar tracking uploads that are paused because of low battery."
17891794
)
1795+
case .pausedLowPowerMode:
1796+
OWSLocalizedString(
1797+
"BACKUP_SETTINGS_UPLOAD_PROGRESS_SUBTITLE_PAUSED_LOW_POWER_MODE",
1798+
comment: "Subtitle for a progress bar tracking uploads that are paused because of low power mode."
1799+
)
17901800
case .pausedNeedsWifi:
17911801
OWSLocalizedString(
17921802
"BACKUP_SETTINGS_UPLOAD_PROGRESS_SUBTITLE_PAUSED_NEEDS_WIFI",
@@ -2291,7 +2301,7 @@ extension OWSSequentialProgress<BackupExportJobStep> {
22912301
))
22922302
}
22932303

2294-
#Preview("Manual Backup: Media Upload Paused (Battery)") {
2304+
#Preview("Manual Backup: Media Upload Paused (Low Battery)") {
22952305
BackupSettingsView(viewModel: .forPreview(
22962306
backupPlan: .free,
22972307
latestBackupExportProgressUpdate: .forPreview(.attachmentUpload, 0.80),
@@ -2300,6 +2310,15 @@ extension OWSSequentialProgress<BackupExportJobStep> {
23002310
))
23012311
}
23022312

2313+
#Preview("Manual Backup: Media Upload Paused (Low Power Mode)") {
2314+
BackupSettingsView(viewModel: .forPreview(
2315+
backupPlan: .free,
2316+
latestBackupExportProgressUpdate: .forPreview(.attachmentUpload, 0.80),
2317+
latestBackupAttachmentUploadUpdateState: .pausedLowPowerMode,
2318+
backupSubscriptionLoadingState: .loaded(.paidButFreeForTesters)
2319+
))
2320+
}
2321+
23032322
#Preview("Manual Backup: Media Upload Paused (WiFi)") {
23042323
BackupSettingsView(viewModel: .forPreview(
23052324
backupPlan: .free,
@@ -2345,14 +2364,22 @@ extension OWSSequentialProgress<BackupExportJobStep> {
23452364
))
23462365
}
23472366

2348-
#Preview("Downloads: Paused (Battery)") {
2367+
#Preview("Downloads: Paused (Low Battery)") {
23492368
BackupSettingsView(viewModel: .forPreview(
23502369
backupPlan: .free,
23512370
latestBackupAttachmentDownloadUpdateState: .pausedLowBattery,
23522371
backupSubscriptionLoadingState: .loaded(.free)
23532372
))
23542373
}
23552374

2375+
#Preview("Downloads: Paused (Low Power Mode)") {
2376+
BackupSettingsView(viewModel: .forPreview(
2377+
backupPlan: .free,
2378+
latestBackupAttachmentDownloadUpdateState: .pausedLowPowerMode,
2379+
backupSubscriptionLoadingState: .loaded(.free)
2380+
))
2381+
}
2382+
23562383
#Preview("Downloads: Paused (WiFi)") {
23572384
BackupSettingsView(viewModel: .forPreview(
23582385
backupPlan: .free,

Signal/src/ViewControllers/HomeView/Chat List/ChatListViewController+BackupDownloadProgressView.swift

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ public class CLVBackupDownloadProgressView {
187187
return nil
188188
case .lowBattery:
189189
return .paused(reason: .lowBattery)
190+
case .lowPowerMode:
191+
return .paused(reason: .lowPowerMode)
190192
case .lowDiskSpace:
191193
let minRequiredDiskSpace = backupAttachmentDownloadQueueStatusReporter
192194
.minimumRequiredDiskSpaceToCompleteDownloads()
@@ -227,6 +229,7 @@ private class BackupAttachmentDownloadProgressView: UIView {
227229
public enum PauseReason {
228230
case notReachable
229231
case lowBattery
232+
case lowPowerMode
230233
}
231234
}
232235

@@ -248,11 +251,11 @@ private class BackupAttachmentDownloadProgressView: UIView {
248251
fatalError("init(frame:) has not been implemented")
249252
}
250253

251-
private let backupAttachmentDownloadManager: BackupAttachmentDownloadManager
252-
private let backupAttachmentDownloadQueueStatusReporter: BackupAttachmentDownloadQueueStatusReporter
253-
private let backupAttachmentDownloadStore: BackupAttachmentDownloadStore
254-
private let backupSettingsStore: BackupSettingsStore
255-
private let db: DB
254+
private let backupAttachmentDownloadManager: BackupAttachmentDownloadManager!
255+
private let backupAttachmentDownloadQueueStatusReporter: BackupAttachmentDownloadQueueStatusReporter!
256+
private let backupAttachmentDownloadStore: BackupAttachmentDownloadStore!
257+
private let backupSettingsStore: BackupSettingsStore!
258+
private let db: DB!
256259

257260
init(
258261
backupAttachmentDownloadManager: BackupAttachmentDownloadManager,
@@ -278,6 +281,20 @@ private class BackupAttachmentDownloadProgressView: UIView {
278281
initialRender()
279282
}
280283

284+
fileprivate init(forPreview: (), state: State) {
285+
self.backupAttachmentDownloadManager = nil
286+
self.backupAttachmentDownloadQueueStatusReporter = nil
287+
self.backupAttachmentDownloadStore = nil
288+
self.backupSettingsStore = nil
289+
self.db = nil
290+
291+
self.state = state
292+
293+
super.init(frame: .zero)
294+
295+
initialRender()
296+
}
297+
281298
// MARK: - Rendering
282299

283300
private lazy var backgroundView: UIView = {
@@ -707,6 +724,11 @@ private class BackupAttachmentDownloadProgressView: UIView {
707724
"RESTORING_MEDIA_BANNER_PAUSED_BATTERY_SUBTITLE",
708725
comment: "Subtitle shown on chat list banner for restoring media from a backup when paused because the device has low battery"
709726
)
727+
case .lowPowerMode:
728+
OWSLocalizedString(
729+
"RESTORING_MEDIA_BANNER_PAUSED_LOW_POWER_MODE_SUBTITLE",
730+
comment: "Subtitle shown on chat list banner for restoring media from a backup when paused because the device is in low power mode"
731+
)
710732
case .notReachable:
711733
OWSLocalizedString(
712734
"RESTORING_MEDIA_BANNER_PAUSED_NOT_REACHABLE_SUBTITLE",
@@ -993,3 +1015,36 @@ private class BackupAttachmentDownloadProgressView: UIView {
9931015
}
9941016
}
9951017
}
1018+
1019+
// MARK: -
1020+
1021+
#if DEBUG
1022+
1023+
private class BackupDownloadProgressPreviewViewController: UIViewController {
1024+
private let state: BackupAttachmentDownloadProgressView.State
1025+
1026+
init(state: BackupAttachmentDownloadProgressView.State) {
1027+
self.state = state
1028+
super.init(nibName: nil, bundle: nil)
1029+
}
1030+
1031+
required init?(coder: NSCoder) { fatalError() }
1032+
1033+
override func viewDidLoad() {
1034+
super.viewDidLoad()
1035+
1036+
let progressView = BackupAttachmentDownloadProgressView(
1037+
forPreview: (),
1038+
state: state
1039+
)
1040+
view.addSubview(progressView)
1041+
progressView.autoPinEdges(toSuperviewMarginsExcludingEdge: .bottom)
1042+
}
1043+
}
1044+
1045+
@available(iOS 17, *)
1046+
#Preview {
1047+
return BackupDownloadProgressPreviewViewController(state: .paused(reason: .lowPowerMode))
1048+
}
1049+
1050+
#endif

Signal/translations/en.lproj/Localizable.strings

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,9 @@
760760
/* Subtitle for a progress bar tracking downloads that are paused because of low battery. */
761761
"BACKUP_SETTINGS_DOWNLOAD_PROGRESS_SUBTITLE_PAUSED_LOW_BATTERY" = "Download paused: device has low battery";
762762

763+
/* Subtitle for a progress bar tracking downloads that are paused because of low power mode. */
764+
"BACKUP_SETTINGS_DOWNLOAD_PROGRESS_SUBTITLE_PAUSED_LOW_POWER_MODE" = "Download paused: low power mode";
765+
763766
/* Subtitle for a progress bar tracking downloads that are paused because they need more disk space available. Embeds {{ the amount of space needed as a file size, e.g. 100 MB }}. */
764767
"BACKUP_SETTINGS_DOWNLOAD_PROGRESS_SUBTITLE_PAUSED_NEEDS_DISK_SPACE" = "Not enough space to download your media. To continue free up %1$@ of space.";
765768

@@ -850,6 +853,9 @@
850853
/* Subtitle for a progress bar tracking uploads that are paused because of low battery. */
851854
"BACKUP_SETTINGS_UPLOAD_PROGRESS_SUBTITLE_PAUSED_LOW_BATTERY" = "Media upload paused: device has low battery";
852855

856+
/* Subtitle for a progress bar tracking uploads that are paused because of low power mode. */
857+
"BACKUP_SETTINGS_UPLOAD_PROGRESS_SUBTITLE_PAUSED_LOW_POWER_MODE" = "Media upload paused: low power mode";
858+
853859
/* Subtitle for a progress bar tracking uploads that are paused because they need an internet connection */
854860
"BACKUP_SETTINGS_UPLOAD_PROGRESS_SUBTITLE_PAUSED_NEEDS_INTERNET" = "Media upload paused: no internet…";
855861

@@ -7060,6 +7066,9 @@
70607066
/* Subtitle shown on chat list banner for restoring media from a backup when paused because the device has low battery */
70617067
"RESTORING_MEDIA_BANNER_PAUSED_BATTERY_SUBTITLE" = "Device has low battery";
70627068

7069+
/* Subtitle shown on chat list banner for restoring media from a backup when paused because the device is in low power mode */
7070+
"RESTORING_MEDIA_BANNER_PAUSED_LOW_POWER_MODE_SUBTITLE" = "Low power mode";
7071+
70637072
/* Subtitle shown on chat list banner for restoring media from a backup when paused because the device has no internet connection */
70647073
"RESTORING_MEDIA_BANNER_PAUSED_NOT_REACHABLE_SUBTITLE" = "No internet…";
70657074

SignalServiceKit/Backups/Attachments/BackupAttachmentDownloadManager.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,10 @@ public class BackupAttachmentDownloadManagerImpl: BackupAttachmentDownloadManage
238238
logger.info("Skipping \(logString) backup attachment downloads while low battery")
239239
try await taskQueue.stop()
240240
return
241+
case .lowPowerMode:
242+
logger.info("Skipping \(logString) backup attachment downloads while low power mode")
243+
try await taskQueue.stop()
244+
return
241245
case .lowDiskSpace:
242246
logger.info("Skipping \(logString) backup attachment downloads while low on disk space")
243247
try await taskQueue.stop()
@@ -402,7 +406,7 @@ public class BackupAttachmentDownloadManagerImpl: BackupAttachmentDownloadManage
402406
case .lowDiskSpace:
403407
try? await loader.stop()
404408
return .retryableError(NeedsDiskSpaceError())
405-
case .lowBattery:
409+
case .lowBattery, .lowPowerMode:
406410
try? await loader.stop()
407411
return .retryableError(NeedsBatteryError())
408412
case .appBackgrounded:
@@ -548,7 +552,7 @@ public class BackupAttachmentDownloadManagerImpl: BackupAttachmentDownloadManage
548552
case .empty:
549553
// The queue will stop on its own, finish this task.
550554
break
551-
case .suspended, .lowDiskSpace, .lowBattery, .noWifiReachability, .noReachability, .appBackgrounded, .notRegisteredAndReady:
555+
case .suspended, .lowDiskSpace, .lowBattery, .lowPowerMode, .noWifiReachability, .noReachability, .appBackgrounded, .notRegisteredAndReady:
552556
// Stop the queue now proactively.
553557
try? await loader.stop()
554558
}

SignalServiceKit/Backups/Attachments/BackupAttachmentDownloadQueueStatusManager.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ public enum BackupAttachmentDownloadQueueStatus: Equatable, Sendable {
2626
case noWifiReachability
2727
/// Internet access is required for downloads, but not available.
2828
case noReachability
29-
/// The device has low battery or is in low power mode.
29+
/// The device has low battery.
3030
case lowBattery
31+
/// The device is in low power mode.
32+
case lowPowerMode
3133
/// There is not enough disk space to finish downloading.
3234
/// Note that we require a minimum amount of space and will continue
3335
/// greedily downloading until this minimum is reached even if we know
@@ -402,7 +404,7 @@ public class BackupAttachmentDownloadQueueStatusManagerImpl: BackupAttachmentDow
402404
}
403405

404406
if isLowPowerMode == true {
405-
return .lowBattery
407+
return .lowPowerMode
406408
}
407409

408410
if !isMainAppAndActive && !isMainAppAndActiveOverride {
@@ -504,13 +506,13 @@ public class BackupAttachmentDownloadQueueStatusManagerImpl: BackupAttachmentDow
504506
let notificationsToObserve: [(Notification.Name, Selector)] = [
505507
(.registrationStateDidChange, #selector(registrationStateDidChange)),
506508
(.reachabilityChanged, #selector(reachabilityDidChange)),
507-
(UIDevice.batteryLevelDidChangeNotification, #selector(batteryLevelDidChange)),
508-
(Notification.Name.NSProcessInfoPowerStateDidChange, #selector(lowPowerModeDidChange)),
509+
(.batteryLevelChanged, #selector(batteryLevelDidChange)),
510+
(.batteryLowPowerModeChanged, #selector(lowPowerModeDidChange)),
509511
(.OWSApplicationWillEnterForeground, #selector(willEnterForeground)),
510512
(.backupAttachmentDownloadQueueSuspensionStatusDidChange, #selector(suspensionStatusDidChange)),
511513
(.shouldAllowBackupDownloadsOnCellularChanged, #selector(shouldAllowBackupDownloadsOnCellularDidChange)),
512-
(Notification.Name.OWSApplicationDidEnterBackground, #selector(isMainAppAndActiveDidChange)),
513-
(Notification.Name.OWSApplicationDidBecomeActive, #selector(isMainAppAndActiveDidChange)),
514+
(.OWSApplicationDidEnterBackground, #selector(isMainAppAndActiveDidChange)),
515+
(.OWSApplicationDidBecomeActive, #selector(isMainAppAndActiveDidChange)),
514516
]
515517
for (name, selector) in notificationsToObserve {
516518
NotificationCenter.default.addObserver(

SignalServiceKit/Backups/Attachments/BackupAttachmentUploadQueueRunner.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,9 @@ class BackupAttachmentUploadQueueRunnerImpl: BackupAttachmentUploadQueueRunner {
281281
case .lowBattery:
282282
logger.warn("Skipping \(logString) Backup uploads: low battery.")
283283
try await taskQueue.stop()
284+
case .lowPowerMode:
285+
logger.warn("Skipping \(logString) Backup uploads: low power mode.")
286+
try await taskQueue.stop()
284287
case .appBackgrounded:
285288
logger.warn("Skipping \(logString) Backup uploads: app backgrounded")
286289
try await taskQueue.stop()
@@ -394,7 +397,7 @@ class BackupAttachmentUploadQueueRunnerImpl: BackupAttachmentUploadQueueRunner {
394397
case .empty:
395398
// The queue will stop on its own, finish this task.
396399
break
397-
case .lowBattery:
400+
case .lowBattery, .lowPowerMode:
398401
try? await loader.stop()
399402
return .retryableError(NeedsBatteryError())
400403
case .noWifiReachability, .noReachability:
@@ -614,7 +617,7 @@ class BackupAttachmentUploadQueueRunnerImpl: BackupAttachmentUploadQueueRunner {
614617
// issue.
615618
return .retryableError(NetworkRetryError())
616619
case .noWifiReachability, .notRegisteredAndReady,
617-
.lowBattery, .appBackgrounded, .empty:
620+
.lowBattery, .lowPowerMode, .appBackgrounded, .empty:
618621
// These other states may be overriding reachability;
619622
// just allow the queue itself to retry and once the
620623
// other states are resolved reachability will kick in,

0 commit comments

Comments
 (0)