diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index d340779b7..22a328f57 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -57,6 +57,7 @@ 34386A54207D271D009F5D9C /* NeverClearView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34386A53207D271C009F5D9C /* NeverClearView.swift */; }; 343A65951FC47D5E000477A1 /* DebugUISyncMessages.m in Sources */ = {isa = PBXBuildFile; fileRef = 343A65941FC47D5E000477A1 /* DebugUISyncMessages.m */; }; 343A65981FC4CFE7000477A1 /* ConversationScrollButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 343A65961FC4CFE6000477A1 /* ConversationScrollButton.m */; }; + 3441FD9F21A3604F00BB9542 /* BackupRestoreViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3441FD9E21A3604F00BB9542 /* BackupRestoreViewController.swift */; }; 34480B361FD0929200BC14EF /* ShareAppExtensionContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 34480B351FD0929200BC14EF /* ShareAppExtensionContext.m */; }; 34480B491FD0A60200BC14EF /* OWSMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 34480B481FD0A60200BC14EF /* OWSMath.h */; settings = {ATTRIBUTES = (Public, ); }; }; 34480B551FD0A7A400BC14EF /* DebugLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 34480B4D1FD0A7A300BC14EF /* DebugLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -695,6 +696,7 @@ 343A65971FC4CFE7000477A1 /* ConversationScrollButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConversationScrollButton.h; sourceTree = ""; }; 343D3D991E9283F100165CA4 /* BlockListUIUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockListUIUtils.h; sourceTree = ""; }; 343D3D9A1E9283F100165CA4 /* BlockListUIUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BlockListUIUtils.m; sourceTree = ""; }; + 3441FD9E21A3604F00BB9542 /* BackupRestoreViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackupRestoreViewController.swift; sourceTree = ""; }; 34480B341FD0929200BC14EF /* ShareAppExtensionContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShareAppExtensionContext.h; sourceTree = ""; }; 34480B351FD0929200BC14EF /* ShareAppExtensionContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ShareAppExtensionContext.m; sourceTree = ""; }; 34480B371FD092A900BC14EF /* SignalShareExtension-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SignalShareExtension-Bridging-Header.h"; sourceTree = ""; }; @@ -1422,6 +1424,7 @@ 340FC875204DAC8C007AEB0F /* Registration */ = { isa = PBXGroup; children = ( + 3441FD9E21A3604F00BB9542 /* BackupRestoreViewController.swift */, 340FC879204DAC8C007AEB0F /* CodeVerificationViewController.h */, 340FC877204DAC8C007AEB0F /* CodeVerificationViewController.m */, 340FC878204DAC8C007AEB0F /* RegistrationViewController.h */, @@ -3496,6 +3499,7 @@ 45D308AD2049A439000189E4 /* PinEntryView.m in Sources */, 340FC8B1204DAC8D007AEB0F /* BlockListViewController.m in Sources */, 45B5360E206DD8BB00D61655 /* UIResponder+OWS.swift in Sources */, + 3441FD9F21A3604F00BB9542 /* BackupRestoreViewController.swift in Sources */, 45F659821E1BE77000444429 /* NonCallKitCallUIAdaptee.swift in Sources */, 45AE48511E0732D6004D96C2 /* TurnServerInfo.swift in Sources */, 34B3F8771E8DF1700035BE1A /* ContactsPicker.swift in Sources */, diff --git a/Signal/src/ViewControllers/AppSettings/OWSBackupSettingsViewController.m b/Signal/src/ViewControllers/AppSettings/OWSBackupSettingsViewController.m index 68139aa8a..a49910188 100644 --- a/Signal/src/ViewControllers/AppSettings/OWSBackupSettingsViewController.m +++ b/Signal/src/ViewControllers/AppSettings/OWSBackupSettingsViewController.m @@ -75,9 +75,10 @@ NS_ASSUME_NONNULL_BEGIN // Enabling backup will involve entering and registering a PIN. OWSTableSection *progressSection = [OWSTableSection new]; [progressSection - addItem:[OWSTableItem labelItemWithText:NSLocalizedString(@"SETTINGS_BACKUP_STATUS", - @"Label for status row in the in the backup settings view.") - accessoryText:[self backupExportStateLocalizedDescription]]]; + addItem:[OWSTableItem + labelItemWithText:NSLocalizedString(@"SETTINGS_BACKUP_STATUS", + @"Label for status row in the in the backup settings view.") + accessoryText:NSStringForBackupExportState(OWSBackup.sharedManager.backupExportState)]]; if (OWSBackup.sharedManager.backupExportState == OWSBackupState_InProgress) { if (OWSBackup.sharedManager.backupExportDescription) { [progressSection @@ -131,20 +132,6 @@ NS_ASSUME_NONNULL_BEGIN self.contents = contents; } -- (NSString *)backupExportStateLocalizedDescription -{ - switch (OWSBackup.sharedManager.backupExportState) { - case OWSBackupState_Idle: - return NSLocalizedString(@"SETTINGS_BACKUP_STATUS_IDLE", @"Indicates that app is not backing up."); - case OWSBackupState_InProgress: - return NSLocalizedString(@"SETTINGS_BACKUP_STATUS_IN_PROGRESS", @"Indicates that app is backing up."); - case OWSBackupState_Failed: - return NSLocalizedString(@"SETTINGS_BACKUP_STATUS_FAILED", @"Indicates that the last backup failed."); - case OWSBackupState_Succeeded: - return NSLocalizedString(@"SETTINGS_BACKUP_STATUS_SUCCEEDED", @"Indicates that the last backup succeeded."); - } -} - - (void)isBackupEnabledDidChange:(UISwitch *)sender { [OWSBackup.sharedManager setIsBackupEnabled:sender.isOn]; diff --git a/Signal/src/ViewControllers/ProfileViewController.m b/Signal/src/ViewControllers/ProfileViewController.m index f8a5cf315..38dd8f209 100644 --- a/Signal/src/ViewControllers/ProfileViewController.m +++ b/Signal/src/ViewControllers/ProfileViewController.m @@ -446,22 +446,16 @@ NSString *const kProfileView_LastPresentedDate = @"kProfileView_LastPresentedDat - (void)showHomeView { - HomeViewController *homeView = [HomeViewController new]; - SignalsNavigationController *navigationController = - [[SignalsNavigationController alloc] initWithRootViewController:homeView]; - AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; - appDelegate.window.rootViewController = navigationController; - OWSAssertDebug([navigationController.topViewController isKindOfClass:[HomeViewController class]]); + [SignalApp.sharedApp showHomeView]; } - (void)showBackupRestoreView { - HomeViewController *homeView = [HomeViewController new]; - SignalsNavigationController *navigationController = - [[SignalsNavigationController alloc] initWithRootViewController:homeView]; - AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; - appDelegate.window.rootViewController = navigationController; - OWSAssertDebug([navigationController.topViewController isKindOfClass:[HomeViewController class]]); + BackupRestoreViewController *restoreView = [BackupRestoreViewController new]; + [self.navigationController setViewControllers:@[ + restoreView, + ] + animated:YES]; } - (void)checkCanImportBackup diff --git a/Signal/src/ViewControllers/Registration/BackupRestoreViewController.swift b/Signal/src/ViewControllers/Registration/BackupRestoreViewController.swift new file mode 100644 index 000000000..dde82053a --- /dev/null +++ b/Signal/src/ViewControllers/Registration/BackupRestoreViewController.swift @@ -0,0 +1,91 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +import UIKit + +@objc +public class BackupRestoreViewController: OWSTableViewController { + + private var backup: OWSBackup { + return AppEnvironment.shared.backup + } + + override public func loadView() { + navigationItem.title = NSLocalizedString("REMINDER_2FA_NAV_TITLE", comment: "Navbar title for when user is periodically prompted to enter their registration lock PIN") + + navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(didPressCancelButton)) + } + + override public func viewDidLoad() { + super.viewDidLoad() + + NotificationCenter.default.addObserver(self, + selector: #selector(backupStateDidChange), + name: NSNotification.Name(NSNotificationNameBackupStateDidChange), + object: nil) + + backup.tryToImport() + + updateTableContents() + } + + private func updateTableContents() { + let contents = OWSTableContents() + + let section = OWSTableSection() + + section.add(OWSTableItem.label(withText: NSLocalizedString("BACKUP_RESTORE_STATUS", comment: "Label for the backup restore status."), accessoryText: NSStringForBackupImportState(backup.backupImportState))) + + if backup.backupImportState == .inProgress { + if let backupImportDescription = backup.backupImportDescription { + section.add(OWSTableItem.label(withText: NSLocalizedString("BACKUP_RESTORE_DESCRIPTION", comment: "Label for the backup restore description."), accessoryText: backupImportDescription)) + } + + if let backupImportProgress = backup.backupImportProgress { + let progressInt = backupImportProgress.floatValue * 100 + let numberFormatter = NumberFormatter() + numberFormatter.numberStyle = .percent + numberFormatter.maximumFractionDigits = 0 + numberFormatter.multiplier = 1 + if let progressString = numberFormatter.string(from: NSNumber(value: progressInt)) { + section.add(OWSTableItem.label(withText: NSLocalizedString("BACKUP_RESTORE_PROGRESS", comment: "Label for the backup restore progress."), accessoryText: progressString)) + } else { + owsFailDebug("Could not format progress: \(progressInt)") + } + } + } + + contents.addSection(section) + self.contents = contents + + // TODO: Add cancel button. + } + + // MARK: Helpers + + @objc + private func didPressCancelButton(sender: UIButton) { + Logger.info("") + + // TODO: Cancel import. + + self.dismiss(animated: true) + } + + private func showHomeView() { + SignalApp.shared().showHomeView() + } + + // MARK: - Notifications + + @objc func backupStateDidChange() { + AssertIsOnMainThread() + + if backup.backupImportState == .succeeded { + showHomeView() + } else { + updateTableContents() + } + } +} diff --git a/Signal/src/environment/SignalApp.h b/Signal/src/environment/SignalApp.h index b25dce838..ce8d4aec9 100644 --- a/Signal/src/environment/SignalApp.h +++ b/Signal/src/environment/SignalApp.h @@ -53,6 +53,8 @@ NS_ASSUME_NONNULL_BEGIN + (void)clearAllNotifications; +- (void)showHomeView; + @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/environment/SignalApp.m b/Signal/src/environment/SignalApp.m index 27159cfb0..90e86046d 100644 --- a/Signal/src/environment/SignalApp.m +++ b/Signal/src/environment/SignalApp.m @@ -3,9 +3,11 @@ // #import "SignalApp.h" +#import "AppDelegate.h" #import "ConversationViewController.h" #import "HomeViewController.h" #import "Signal-Swift.h" +#import "SignalsNavigationController.h" #import #import #import @@ -156,6 +158,16 @@ NS_ASSUME_NONNULL_BEGIN [UIApplication sharedApplication].applicationIconBadgeNumber = 0; } +- (void)showHomeView +{ + HomeViewController *homeView = [HomeViewController new]; + SignalsNavigationController *navigationController = + [[SignalsNavigationController alloc] initWithRootViewController:homeView]; + AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; + appDelegate.window.rootViewController = navigationController; + OWSAssertDebug([navigationController.topViewController isKindOfClass:[HomeViewController class]]); +} + @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/util/Backup/OWSBackup.h b/Signal/src/util/Backup/OWSBackup.h index 0f0823b0f..8d0dc9468 100644 --- a/Signal/src/util/Backup/OWSBackup.h +++ b/Signal/src/util/Backup/OWSBackup.h @@ -20,6 +20,9 @@ typedef NS_ENUM(NSUInteger, OWSBackupState) { OWSBackupState_Succeeded, }; +NSString *NSStringForBackupExportState(OWSBackupState state); +NSString *NSStringForBackupImportState(OWSBackupState state); + @class OWSBackupIO; @class TSAttachmentPointer; @class TSThread; diff --git a/Signal/src/util/Backup/OWSBackup.m b/Signal/src/util/Backup/OWSBackup.m index 8e3ea7a93..ebfa7d759 100644 --- a/Signal/src/util/Backup/OWSBackup.m +++ b/Signal/src/util/Backup/OWSBackup.m @@ -10,6 +10,8 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + NSString *const NSNotificationNameBackupStateDidChange = @"NSNotificationNameBackupStateDidChange"; NSString *const OWSPrimaryStorage_OWSBackupCollection = @"OWSPrimaryStorage_OWSBackupCollection"; @@ -17,7 +19,36 @@ NSString *const OWSBackup_IsBackupEnabledKey = @"OWSBackup_IsBackupEnabledKey"; NSString *const OWSBackup_LastExportSuccessDateKey = @"OWSBackup_LastExportSuccessDateKey"; NSString *const OWSBackup_LastExportFailureDateKey = @"OWSBackup_LastExportFailureDateKey"; -NS_ASSUME_NONNULL_BEGIN +NSString *NSStringForBackupExportState(OWSBackupState state) +{ + switch (state) { + case OWSBackupState_Idle: + return NSLocalizedString(@"SETTINGS_BACKUP_STATUS_IDLE", @"Indicates that app is not backing up."); + case OWSBackupState_InProgress: + return NSLocalizedString(@"SETTINGS_BACKUP_STATUS_IN_PROGRESS", @"Indicates that app is backing up."); + case OWSBackupState_Failed: + return NSLocalizedString(@"SETTINGS_BACKUP_STATUS_FAILED", @"Indicates that the last backup failed."); + case OWSBackupState_Succeeded: + return NSLocalizedString(@"SETTINGS_BACKUP_STATUS_SUCCEEDED", @"Indicates that the last backup succeeded."); + } +} + +NSString *NSStringForBackupImportState(OWSBackupState state) +{ + switch (state) { + case OWSBackupState_Idle: + return NSLocalizedString(@"SETTINGS_BACKUP_IMPORT_STATUS_IDLE", @"Indicates that app is not restoring up."); + case OWSBackupState_InProgress: + return NSLocalizedString( + @"SETTINGS_BACKUP_IMPORT_STATUS_IN_PROGRESS", @"Indicates that app is restoring up."); + case OWSBackupState_Failed: + return NSLocalizedString( + @"SETTINGS_BACKUP_IMPORT_STATUS_FAILED", @"Indicates that the last backup restore failed."); + case OWSBackupState_Succeeded: + return NSLocalizedString( + @"SETTINGS_BACKUP_IMPORT_STATUS_SUCCEEDED", @"Indicates that the last backup restore succeeded."); + } +} // TODO: Observe Reachability. @interface OWSBackup () diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 4aec8f915..d36c9cd16 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -1949,6 +1949,18 @@ /* Label for switch in settings that controls whether or not backup is enabled. */ "SETTINGS_BACKUP_ENABLING_SWITCH" = "Backup Enabled"; +/* Indicates that the last backup restore failed. */ +"SETTINGS_BACKUP_IMPORT_STATUS_FAILED" = "Backup Restore Failed"; + +/* Indicates that app is not restoring up. */ +"SETTINGS_BACKUP_IMPORT_STATUS_IDLE" = "Backup Restore Idle"; + +/* Indicates that app is restoring up. */ +"SETTINGS_BACKUP_IMPORT_STATUS_IN_PROGRESS" = "Backup Restore In Progress"; + +/* Indicates that the last backup restore succeeded. */ +"SETTINGS_BACKUP_IMPORT_STATUS_SUCCEEDED" = "Backup Restore Succeeded"; + /* Label for phase row in the in the backup settings view. */ "SETTINGS_BACKUP_PHASE" = "Phase";