diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 552d14f3d..c20ba411f 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -8,11 +8,32 @@ /* Begin PBXBuildFile section */ 2AE2882E4C2B96BFFF9EE27C /* Pods_SignalShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F94C85CB0B235DA37F68ED0 /* Pods_SignalShareExtension.framework */; }; - 34074F5B203D093B004596AE /* OWSSoundSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34074F59203D093A004596AE /* OWSSoundSettingsViewController.m */; }; 34074F61203D0CBE004596AE /* OWSSounds.m in Sources */ = {isa = PBXBuildFile; fileRef = 34074F5F203D0CBD004596AE /* OWSSounds.m */; }; 34074F62203D0CBE004596AE /* OWSSounds.h in Headers */ = {isa = PBXBuildFile; fileRef = 34074F60203D0CBE004596AE /* OWSSounds.h */; settings = {ATTRIBUTES = (Public, ); }; }; 340B02BA1FA0D6C700F9CFEC /* ConversationViewItemTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 340B02B91FA0D6C700F9CFEC /* ConversationViewItemTest.m */; }; - 340CB2271EAC25820001CAA1 /* UpdateGroupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340CB2261EAC25820001CAA1 /* UpdateGroupViewController.m */; }; + 340FC8A7204DAC8D007AEB0F /* RegistrationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC876204DAC8C007AEB0F /* RegistrationViewController.m */; }; + 340FC8A8204DAC8D007AEB0F /* CodeVerificationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC877204DAC8C007AEB0F /* CodeVerificationViewController.m */; }; + 340FC8A9204DAC8D007AEB0F /* NotificationSettingsOptionsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC87B204DAC8C007AEB0F /* NotificationSettingsOptionsViewController.m */; }; + 340FC8AA204DAC8D007AEB0F /* NotificationSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC87C204DAC8C007AEB0F /* NotificationSettingsViewController.m */; }; + 340FC8AB204DAC8D007AEB0F /* DomainFrontingCountryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC87D204DAC8C007AEB0F /* DomainFrontingCountryViewController.m */; }; + 340FC8AC204DAC8D007AEB0F /* PrivacySettingsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC87E204DAC8C007AEB0F /* PrivacySettingsTableViewController.m */; }; + 340FC8AD204DAC8D007AEB0F /* OWSLinkedDevicesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC882204DAC8C007AEB0F /* OWSLinkedDevicesTableViewController.m */; }; + 340FC8AE204DAC8D007AEB0F /* OWSSoundSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC883204DAC8C007AEB0F /* OWSSoundSettingsViewController.m */; }; + 340FC8AF204DAC8D007AEB0F /* OWSLinkDeviceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC885204DAC8C007AEB0F /* OWSLinkDeviceViewController.m */; }; + 340FC8B0204DAC8D007AEB0F /* AddToBlockListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC886204DAC8C007AEB0F /* AddToBlockListViewController.m */; }; + 340FC8B1204DAC8D007AEB0F /* BlockListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC887204DAC8C007AEB0F /* BlockListViewController.m */; }; + 340FC8B2204DAC8D007AEB0F /* AdvancedSettingsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC88C204DAC8C007AEB0F /* AdvancedSettingsTableViewController.m */; }; + 340FC8B3204DAC8D007AEB0F /* AppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC88D204DAC8C007AEB0F /* AppSettingsViewController.m */; }; + 340FC8B4204DAC8D007AEB0F /* OWSBackupExportViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC88E204DAC8C007AEB0F /* OWSBackupExportViewController.m */; }; + 340FC8B5204DAC8D007AEB0F /* AboutTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC893204DAC8C007AEB0F /* AboutTableViewController.m */; }; + 340FC8B6204DAC8D007AEB0F /* OWSQRCodeScanningViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC896204DAC8C007AEB0F /* OWSQRCodeScanningViewController.m */; }; + 340FC8B7204DAC8D007AEB0F /* OWSConversationSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC89A204DAC8D007AEB0F /* OWSConversationSettingsViewController.m */; }; + 340FC8B8204DAC8D007AEB0F /* AddToGroupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC89B204DAC8D007AEB0F /* AddToGroupViewController.m */; }; + 340FC8B9204DAC8D007AEB0F /* UpdateGroupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC89C204DAC8D007AEB0F /* UpdateGroupViewController.m */; }; + 340FC8BA204DAC8D007AEB0F /* FingerprintViewScanController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC89F204DAC8D007AEB0F /* FingerprintViewScanController.m */; }; + 340FC8BB204DAC8D007AEB0F /* OWSAddToContactViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC8A1204DAC8D007AEB0F /* OWSAddToContactViewController.m */; }; + 340FC8BC204DAC8D007AEB0F /* FingerprintViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC8A2204DAC8D007AEB0F /* FingerprintViewController.m */; }; + 340FC8BD204DAC8D007AEB0F /* ShowGroupMembersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC8A6204DAC8D007AEB0F /* ShowGroupMembersViewController.m */; }; 341F2C0F1F2B8AE700D07D6B /* DebugUIMisc.m in Sources */ = {isa = PBXBuildFile; fileRef = 341F2C0E1F2B8AE700D07D6B /* DebugUIMisc.m */; }; 3430FE181F7751D4000EC51B /* GiphyAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3430FE171F7751D4000EC51B /* GiphyAPI.swift */; }; 34330A5A1E7875FB00DF2FB9 /* fontawesome-webfont.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34330A591E7875FB00DF2FB9 /* fontawesome-webfont.ttf */; }; @@ -113,7 +134,6 @@ 34612A061FD7238600532771 /* OWSContactsSyncing.h in Headers */ = {isa = PBXBuildFile; fileRef = 34612A041FD7238500532771 /* OWSContactsSyncing.h */; settings = {ATTRIBUTES = (Public, ); }; }; 34612A071FD7238600532771 /* OWSContactsSyncing.m in Sources */ = {isa = PBXBuildFile; fileRef = 34612A051FD7238500532771 /* OWSContactsSyncing.m */; }; 346B66311F4E29B200E5122F /* CropScaleImageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346B66301F4E29B200E5122F /* CropScaleImageViewController.swift */; }; - 3472229F1EB22FFE00E53955 /* AddToGroupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3472229E1EB22FFE00E53955 /* AddToGroupViewController.m */; }; 347850311FD7494A007B8332 /* dripicons-v2.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34330A5B1E787A9800DF2FB9 /* dripicons-v2.ttf */; }; 347850321FD7494A007B8332 /* ElegantIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34330A5D1E787BD800DF2FB9 /* ElegantIcons.ttf */; }; 347850331FD7494A007B8332 /* fontawesome-webfont.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34330A591E7875FB00DF2FB9 /* fontawesome-webfont.ttf */; }; @@ -127,38 +147,20 @@ 3478506C1FD9B78A007B8332 /* NoopNotificationsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 347850681FD9B78A007B8332 /* NoopNotificationsManager.swift */; }; 347850711FDAEB17007B8332 /* OWSUserProfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 3478506F1FDAEB16007B8332 /* OWSUserProfile.m */; }; 347850721FDAEB17007B8332 /* OWSUserProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 347850701FDAEB16007B8332 /* OWSUserProfile.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 347E0B7A2003CD7500BC2F76 /* OWSBackupExportViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 347E0B762003CD7400BC2F76 /* OWSBackupExportViewController.m */; }; - 347E0B7B2003CD7500BC2F76 /* OWSBackupImportViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 347E0B782003CD7400BC2F76 /* OWSBackupImportViewController.m */; }; 3497DBEC1ECE257500DB2605 /* OWSCountryMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 3497DBEB1ECE257500DB2605 /* OWSCountryMetadata.m */; }; - 3497DBEF1ECE2E4700DB2605 /* DomainFrontingCountryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3497DBEE1ECE2E4700DB2605 /* DomainFrontingCountryViewController.m */; }; 34A55F3720485465002CC6DE /* OWS2FARegistrationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A55F3520485464002CC6DE /* OWS2FARegistrationViewController.m */; }; 34A910601FFEB114000C4745 /* OWSBackup.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A9105F1FFEB114000C4745 /* OWSBackup.m */; }; 34B0796D1FCF46B100E248C2 /* MainAppContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B0796B1FCF46B000E248C2 /* MainAppContext.m */; }; - 34B3F8711E8DF1700035BE1A /* AboutTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8351E8DF1700035BE1A /* AboutTableViewController.m */; }; - 34B3F8721E8DF1700035BE1A /* AdvancedSettingsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8371E8DF1700035BE1A /* AdvancedSettingsTableViewController.m */; }; 34B3F8751E8DF1700035BE1A /* CallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F83B1E8DF1700035BE1A /* CallViewController.swift */; }; - 34B3F8761E8DF1700035BE1A /* CodeVerificationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F83D1E8DF1700035BE1A /* CodeVerificationViewController.m */; }; 34B3F8771E8DF1700035BE1A /* ContactsPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F83E1E8DF1700035BE1A /* ContactsPicker.swift */; }; 34B3F8781E8DF1700035BE1A /* ContactsPicker.xib in Resources */ = {isa = PBXBuildFile; fileRef = 34B3F83F1E8DF1700035BE1A /* ContactsPicker.xib */; }; 34B3F87B1E8DF1700035BE1A /* ExperienceUpgradesPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8441E8DF1700035BE1A /* ExperienceUpgradesPageViewController.swift */; }; - 34B3F87C1E8DF1700035BE1A /* FingerprintViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8461E8DF1700035BE1A /* FingerprintViewController.m */; }; 34B3F87E1E8DF1700035BE1A /* InboxTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F84A1E8DF1700035BE1A /* InboxTableViewCell.m */; }; 34B3F8801E8DF1700035BE1A /* InviteFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F84C1E8DF1700035BE1A /* InviteFlow.swift */; }; 34B3F8821E8DF1700035BE1A /* NewContactThreadViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8501E8DF1700035BE1A /* NewContactThreadViewController.m */; }; 34B3F8851E8DF1700035BE1A /* NewGroupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8551E8DF1700035BE1A /* NewGroupViewController.m */; }; - 34B3F8861E8DF1700035BE1A /* NotificationSettingsOptionsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8571E8DF1700035BE1A /* NotificationSettingsOptionsViewController.m */; }; - 34B3F8871E8DF1700035BE1A /* NotificationSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8591E8DF1700035BE1A /* NotificationSettingsViewController.m */; }; - 34B3F8891E8DF1700035BE1A /* OWSConversationSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F85C1E8DF1700035BE1A /* OWSConversationSettingsViewController.m */; }; - 34B3F88A1E8DF1700035BE1A /* OWSLinkDeviceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F85E1E8DF1700035BE1A /* OWSLinkDeviceViewController.m */; }; - 34B3F88B1E8DF1700035BE1A /* OWSLinkedDevicesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8601E8DF1700035BE1A /* OWSLinkedDevicesTableViewController.m */; }; - 34B3F88D1E8DF1700035BE1A /* OWSQRCodeScanningViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8631E8DF1700035BE1A /* OWSQRCodeScanningViewController.m */; }; - 34B3F88E1E8DF1700035BE1A /* PrivacySettingsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8651E8DF1700035BE1A /* PrivacySettingsTableViewController.m */; }; - 34B3F88F1E8DF1710035BE1A /* RegistrationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8671E8DF1700035BE1A /* RegistrationViewController.m */; }; - 34B3F8901E8DF1710035BE1A /* AppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8691E8DF1700035BE1A /* AppSettingsViewController.m */; }; - 34B3F8911E8DF1710035BE1A /* ShowGroupMembersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F86B1E8DF1700035BE1A /* ShowGroupMembersViewController.m */; }; 34B3F8931E8DF1710035BE1A /* SignalsNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F86E1E8DF1700035BE1A /* SignalsNavigationController.m */; }; 34B3F8941E8DF1710035BE1A /* HomeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8701E8DF1700035BE1A /* HomeViewController.m */; }; - 34B3F89C1E8DF3270035BE1A /* BlockListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F89B1E8DF3270035BE1A /* BlockListViewController.m */; }; 34BECE2B1F74C12700D7438D /* DebugUIStress.m in Sources */ = {isa = PBXBuildFile; fileRef = 34BECE2A1F74C12700D7438D /* DebugUIStress.m */; }; 34BECE2E1F7ABCE000D7438D /* GifPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BECE2D1F7ABCE000D7438D /* GifPickerViewController.swift */; }; 34BECE301F7ABCF800D7438D /* GifPickerLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BECE2F1F7ABCF800D7438D /* GifPickerLayout.swift */; }; @@ -173,7 +175,6 @@ 34C6B0AE1FA0E4AA00D35993 /* test-jpg.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 34C6B0AD1FA0E4AA00D35993 /* test-jpg.jpg */; }; 34CA1C271F7156F300E51C51 /* MessageDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34CA1C261F7156F300E51C51 /* MessageDetailViewController.swift */; }; 34CCAF381F0C0599004084F4 /* AppUpdateNag.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CCAF371F0C0599004084F4 /* AppUpdateNag.m */; }; - 34CCAF3B1F0C2748004084F4 /* OWSAddToContactViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CCAF3A1F0C2748004084F4 /* OWSAddToContactViewController.m */; }; 34CE88E71F2FB9A10098030F /* ProfileViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CE88E61F2FB9A10098030F /* ProfileViewController.m */; }; 34CF0787203E6B78005C4D61 /* busy_tone_ansi.caf in Resources */ = {isa = PBXBuildFile; fileRef = 34CF0783203E6B77005C4D61 /* busy_tone_ansi.caf */; }; 34CF0788203E6B78005C4D61 /* ringback_tone_ansi.caf in Resources */ = {isa = PBXBuildFile; fileRef = 34CF0784203E6B77005C4D61 /* ringback_tone_ansi.caf */; }; @@ -203,11 +204,9 @@ 34D8C02B1ED3685800188D7C /* DebugUIContacts.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D8C02A1ED3685800188D7C /* DebugUIContacts.m */; }; 34D99C931F2937CC00D284D6 /* OWSAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D99C911F2937CC00D284D6 /* OWSAnalytics.swift */; }; 34DB0BED2011548B007B313F /* OWSDatabaseConverterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 34DB0BEC2011548B007B313F /* OWSDatabaseConverterTest.m */; }; - 34DFCB851E8E04B500053165 /* AddToBlockListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34DFCB841E8E04B500053165 /* AddToBlockListViewController.m */; }; 34E3E5681EC4B19400495BAC /* AudioProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E3E5671EC4B19400495BAC /* AudioProgressView.swift */; }; 34E3EF0D1EFC235B007F6822 /* DebugUIDiskUsage.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E3EF0C1EFC235B007F6822 /* DebugUIDiskUsage.m */; }; 34E3EF101EFC2684007F6822 /* DebugUIPage.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E3EF0F1EFC2684007F6822 /* DebugUIPage.m */; }; - 34E8BF381EE9E2FD00F5F4CA /* FingerprintViewScanController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E8BF371EE9E2FD00F5F4CA /* FingerprintViewScanController.m */; }; 34F308A21ECB469700BB7697 /* OWSBezierPathView.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F308A11ECB469700BB7697 /* OWSBezierPathView.m */; }; 34FD93701E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 34FD936F1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m */; }; 4503F1BE20470A5B00CEE724 /* classic-quiet.aifc in Resources */ = {isa = PBXBuildFile; fileRef = 4503F1BB20470A5B00CEE724 /* classic-quiet.aifc */; }; @@ -515,16 +514,59 @@ 3400C7951EAF99F4008A8584 /* SelectThreadViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SelectThreadViewController.m; sourceTree = ""; }; 3400C7971EAFB772008A8584 /* ThreadViewHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadViewHelper.h; sourceTree = ""; }; 3400C7981EAFB772008A8584 /* ThreadViewHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThreadViewHelper.m; sourceTree = ""; }; - 34074F59203D093A004596AE /* OWSSoundSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSSoundSettingsViewController.m; sourceTree = ""; }; - 34074F5A203D093B004596AE /* OWSSoundSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSSoundSettingsViewController.h; sourceTree = ""; }; 34074F5F203D0CBD004596AE /* OWSSounds.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSSounds.m; sourceTree = ""; }; 34074F60203D0CBE004596AE /* OWSSounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSSounds.h; sourceTree = ""; }; 340B02B61F9FD31800F9CFEC /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = translations/he.lproj/Localizable.strings; sourceTree = ""; }; 340B02B91FA0D6C700F9CFEC /* ConversationViewItemTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConversationViewItemTest.m; sourceTree = ""; }; 340CB2221EAC155C0001CAA1 /* ContactsViewHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactsViewHelper.h; sourceTree = ""; }; 340CB2231EAC155C0001CAA1 /* ContactsViewHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactsViewHelper.m; sourceTree = ""; }; - 340CB2251EAC25820001CAA1 /* UpdateGroupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UpdateGroupViewController.h; sourceTree = ""; }; - 340CB2261EAC25820001CAA1 /* UpdateGroupViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UpdateGroupViewController.m; sourceTree = ""; }; + 340FC876204DAC8C007AEB0F /* RegistrationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RegistrationViewController.m; sourceTree = ""; }; + 340FC877204DAC8C007AEB0F /* CodeVerificationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodeVerificationViewController.m; sourceTree = ""; }; + 340FC878204DAC8C007AEB0F /* RegistrationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegistrationViewController.h; sourceTree = ""; }; + 340FC879204DAC8C007AEB0F /* CodeVerificationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeVerificationViewController.h; sourceTree = ""; }; + 340FC87B204DAC8C007AEB0F /* NotificationSettingsOptionsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NotificationSettingsOptionsViewController.m; sourceTree = ""; }; + 340FC87C204DAC8C007AEB0F /* NotificationSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NotificationSettingsViewController.m; sourceTree = ""; }; + 340FC87D204DAC8C007AEB0F /* DomainFrontingCountryViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DomainFrontingCountryViewController.m; sourceTree = ""; }; + 340FC87E204DAC8C007AEB0F /* PrivacySettingsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PrivacySettingsTableViewController.m; sourceTree = ""; }; + 340FC87F204DAC8C007AEB0F /* OWSBackupSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBackupSettingsViewController.h; sourceTree = ""; }; + 340FC880204DAC8C007AEB0F /* AppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppSettingsViewController.h; sourceTree = ""; }; + 340FC881204DAC8C007AEB0F /* AdvancedSettingsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdvancedSettingsTableViewController.h; sourceTree = ""; }; + 340FC882204DAC8C007AEB0F /* OWSLinkedDevicesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSLinkedDevicesTableViewController.m; sourceTree = ""; }; + 340FC883204DAC8C007AEB0F /* OWSSoundSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSSoundSettingsViewController.m; sourceTree = ""; }; + 340FC884204DAC8C007AEB0F /* AboutTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AboutTableViewController.h; sourceTree = ""; }; + 340FC885204DAC8C007AEB0F /* OWSLinkDeviceViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSLinkDeviceViewController.m; sourceTree = ""; }; + 340FC886204DAC8C007AEB0F /* AddToBlockListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddToBlockListViewController.m; sourceTree = ""; }; + 340FC887204DAC8C007AEB0F /* BlockListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BlockListViewController.m; sourceTree = ""; }; + 340FC888204DAC8C007AEB0F /* OWSQRCodeScanningViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSQRCodeScanningViewController.h; sourceTree = ""; }; + 340FC889204DAC8C007AEB0F /* DomainFrontingCountryViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DomainFrontingCountryViewController.h; sourceTree = ""; }; + 340FC88A204DAC8C007AEB0F /* NotificationSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotificationSettingsViewController.h; sourceTree = ""; }; + 340FC88B204DAC8C007AEB0F /* NotificationSettingsOptionsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotificationSettingsOptionsViewController.h; sourceTree = ""; }; + 340FC88C204DAC8C007AEB0F /* AdvancedSettingsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AdvancedSettingsTableViewController.m; sourceTree = ""; }; + 340FC88D204DAC8C007AEB0F /* AppSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppSettingsViewController.m; sourceTree = ""; }; + 340FC88E204DAC8C007AEB0F /* OWSBackupExportViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSBackupExportViewController.m; sourceTree = ""; }; + 340FC88F204DAC8C007AEB0F /* PrivacySettingsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrivacySettingsTableViewController.h; sourceTree = ""; }; + 340FC890204DAC8C007AEB0F /* BlockListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockListViewController.h; sourceTree = ""; }; + 340FC891204DAC8C007AEB0F /* OWSLinkDeviceViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSLinkDeviceViewController.h; sourceTree = ""; }; + 340FC892204DAC8C007AEB0F /* AddToBlockListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddToBlockListViewController.h; sourceTree = ""; }; + 340FC893204DAC8C007AEB0F /* AboutTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AboutTableViewController.m; sourceTree = ""; }; + 340FC894204DAC8C007AEB0F /* OWSSoundSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSSoundSettingsViewController.h; sourceTree = ""; }; + 340FC895204DAC8C007AEB0F /* OWSLinkedDevicesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSLinkedDevicesTableViewController.h; sourceTree = ""; }; + 340FC896204DAC8C007AEB0F /* OWSQRCodeScanningViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSQRCodeScanningViewController.m; sourceTree = ""; }; + 340FC898204DAC8D007AEB0F /* OWSAddToContactViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSAddToContactViewController.h; sourceTree = ""; }; + 340FC899204DAC8D007AEB0F /* OWSConversationSettingsViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSConversationSettingsViewDelegate.h; sourceTree = ""; }; + 340FC89A204DAC8D007AEB0F /* OWSConversationSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSConversationSettingsViewController.m; sourceTree = ""; }; + 340FC89B204DAC8D007AEB0F /* AddToGroupViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddToGroupViewController.m; sourceTree = ""; }; + 340FC89C204DAC8D007AEB0F /* UpdateGroupViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UpdateGroupViewController.m; sourceTree = ""; }; + 340FC89D204DAC8D007AEB0F /* FingerprintViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FingerprintViewController.h; sourceTree = ""; }; + 340FC89E204DAC8D007AEB0F /* ShowGroupMembersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShowGroupMembersViewController.h; sourceTree = ""; }; + 340FC89F204DAC8D007AEB0F /* FingerprintViewScanController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FingerprintViewScanController.m; sourceTree = ""; }; + 340FC8A0204DAC8D007AEB0F /* OWSConversationSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSConversationSettingsViewController.h; sourceTree = ""; }; + 340FC8A1204DAC8D007AEB0F /* OWSAddToContactViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSAddToContactViewController.m; sourceTree = ""; }; + 340FC8A2204DAC8D007AEB0F /* FingerprintViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FingerprintViewController.m; sourceTree = ""; }; + 340FC8A3204DAC8D007AEB0F /* UpdateGroupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UpdateGroupViewController.h; sourceTree = ""; }; + 340FC8A4204DAC8D007AEB0F /* AddToGroupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddToGroupViewController.h; sourceTree = ""; }; + 340FC8A5204DAC8D007AEB0F /* FingerprintViewScanController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FingerprintViewScanController.h; sourceTree = ""; }; + 340FC8A6204DAC8D007AEB0F /* ShowGroupMembersViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ShowGroupMembersViewController.m; sourceTree = ""; }; 341458471FBE11C4005ABCF9 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = translations/fa.lproj/Localizable.strings; sourceTree = ""; }; 341F2C0D1F2B8AE700D07D6B /* DebugUIMisc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUIMisc.h; sourceTree = ""; }; 341F2C0E1F2B8AE700D07D6B /* DebugUIMisc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugUIMisc.m; sourceTree = ""; }; @@ -639,8 +681,6 @@ 34612A041FD7238500532771 /* OWSContactsSyncing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSContactsSyncing.h; sourceTree = ""; }; 34612A051FD7238500532771 /* OWSContactsSyncing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSContactsSyncing.m; sourceTree = ""; }; 346B66301F4E29B200E5122F /* CropScaleImageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CropScaleImageViewController.swift; sourceTree = ""; }; - 3472229D1EB22FFE00E53955 /* AddToGroupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddToGroupViewController.h; sourceTree = ""; }; - 3472229E1EB22FFE00E53955 /* AddToGroupViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddToGroupViewController.m; sourceTree = ""; }; 347850561FD86544007B8332 /* SAEFailedViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SAEFailedViewController.swift; sourceTree = ""; }; 347850581FD9972E007B8332 /* SwiftSingletons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftSingletons.swift; sourceTree = ""; }; 3478505A1FD999D5007B8332 /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = translations/et.lproj/Localizable.strings; sourceTree = ""; }; @@ -651,16 +691,10 @@ 347850681FD9B78A007B8332 /* NoopNotificationsManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoopNotificationsManager.swift; sourceTree = ""; }; 3478506F1FDAEB16007B8332 /* OWSUserProfile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSUserProfile.m; sourceTree = ""; }; 347850701FDAEB16007B8332 /* OWSUserProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSUserProfile.h; sourceTree = ""; }; - 347E0B762003CD7400BC2F76 /* OWSBackupExportViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSBackupExportViewController.m; sourceTree = ""; }; - 347E0B772003CD7400BC2F76 /* OWSBackupExportViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBackupExportViewController.h; sourceTree = ""; }; - 347E0B782003CD7400BC2F76 /* OWSBackupImportViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSBackupImportViewController.m; sourceTree = ""; }; - 347E0B792003CD7500BC2F76 /* OWSBackupImportViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBackupImportViewController.h; sourceTree = ""; }; 348F2EAD1F0D21BC00D4ECE0 /* DeviceSleepManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceSleepManager.swift; sourceTree = ""; }; 3495BC911F1426B800B478F5 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = translations/ar.lproj/Localizable.strings; sourceTree = ""; }; 3497DBEA1ECE257500DB2605 /* OWSCountryMetadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSCountryMetadata.h; sourceTree = ""; }; 3497DBEB1ECE257500DB2605 /* OWSCountryMetadata.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSCountryMetadata.m; sourceTree = ""; }; - 3497DBED1ECE2E4700DB2605 /* DomainFrontingCountryViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DomainFrontingCountryViewController.h; sourceTree = ""; }; - 3497DBEE1ECE2E4700DB2605 /* DomainFrontingCountryViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DomainFrontingCountryViewController.m; sourceTree = ""; }; 34A55F3520485464002CC6DE /* OWS2FARegistrationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWS2FARegistrationViewController.m; sourceTree = ""; }; 34A55F3620485464002CC6DE /* OWS2FARegistrationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWS2FARegistrationViewController.h; sourceTree = ""; }; 34A9105E1FFEB113000C4745 /* OWSBackup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBackup.h; sourceTree = ""; }; @@ -668,20 +702,12 @@ 34B0796B1FCF46B000E248C2 /* MainAppContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MainAppContext.m; sourceTree = ""; }; 34B0796C1FCF46B000E248C2 /* MainAppContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainAppContext.h; sourceTree = ""; }; 34B0796E1FD07B1E00E248C2 /* SignalShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SignalShareExtension.entitlements; sourceTree = ""; }; - 34B3F8341E8DF1700035BE1A /* AboutTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AboutTableViewController.h; sourceTree = ""; }; - 34B3F8351E8DF1700035BE1A /* AboutTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AboutTableViewController.m; sourceTree = ""; }; - 34B3F8361E8DF1700035BE1A /* AdvancedSettingsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdvancedSettingsTableViewController.h; sourceTree = ""; }; - 34B3F8371E8DF1700035BE1A /* AdvancedSettingsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AdvancedSettingsTableViewController.m; sourceTree = ""; }; 34B3F8391E8DF1700035BE1A /* AttachmentSharing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AttachmentSharing.h; sourceTree = ""; }; 34B3F83A1E8DF1700035BE1A /* AttachmentSharing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AttachmentSharing.m; sourceTree = ""; }; 34B3F83B1E8DF1700035BE1A /* CallViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallViewController.swift; sourceTree = ""; }; - 34B3F83C1E8DF1700035BE1A /* CodeVerificationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeVerificationViewController.h; sourceTree = ""; }; - 34B3F83D1E8DF1700035BE1A /* CodeVerificationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodeVerificationViewController.m; sourceTree = ""; }; 34B3F83E1E8DF1700035BE1A /* ContactsPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactsPicker.swift; sourceTree = ""; }; 34B3F83F1E8DF1700035BE1A /* ContactsPicker.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ContactsPicker.xib; sourceTree = ""; }; 34B3F8441E8DF1700035BE1A /* ExperienceUpgradesPageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExperienceUpgradesPageViewController.swift; sourceTree = ""; }; - 34B3F8451E8DF1700035BE1A /* FingerprintViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FingerprintViewController.h; sourceTree = ""; }; - 34B3F8461E8DF1700035BE1A /* FingerprintViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FingerprintViewController.m; sourceTree = ""; }; 34B3F8491E8DF1700035BE1A /* InboxTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InboxTableViewCell.h; sourceTree = ""; }; 34B3F84A1E8DF1700035BE1A /* InboxTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InboxTableViewCell.m; sourceTree = ""; }; 34B3F84C1E8DF1700035BE1A /* InviteFlow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InviteFlow.swift; sourceTree = ""; }; @@ -689,32 +715,10 @@ 34B3F8501E8DF1700035BE1A /* NewContactThreadViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NewContactThreadViewController.m; sourceTree = ""; }; 34B3F8541E8DF1700035BE1A /* NewGroupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewGroupViewController.h; sourceTree = ""; }; 34B3F8551E8DF1700035BE1A /* NewGroupViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NewGroupViewController.m; sourceTree = ""; }; - 34B3F8561E8DF1700035BE1A /* NotificationSettingsOptionsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotificationSettingsOptionsViewController.h; sourceTree = ""; }; - 34B3F8571E8DF1700035BE1A /* NotificationSettingsOptionsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NotificationSettingsOptionsViewController.m; sourceTree = ""; }; - 34B3F8581E8DF1700035BE1A /* NotificationSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotificationSettingsViewController.h; sourceTree = ""; }; - 34B3F8591E8DF1700035BE1A /* NotificationSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NotificationSettingsViewController.m; sourceTree = ""; }; - 34B3F85B1E8DF1700035BE1A /* OWSConversationSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSConversationSettingsViewController.h; sourceTree = ""; }; - 34B3F85C1E8DF1700035BE1A /* OWSConversationSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSConversationSettingsViewController.m; sourceTree = ""; }; - 34B3F85D1E8DF1700035BE1A /* OWSLinkDeviceViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSLinkDeviceViewController.h; sourceTree = ""; }; - 34B3F85E1E8DF1700035BE1A /* OWSLinkDeviceViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSLinkDeviceViewController.m; sourceTree = ""; }; - 34B3F85F1E8DF1700035BE1A /* OWSLinkedDevicesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSLinkedDevicesTableViewController.h; sourceTree = ""; }; - 34B3F8601E8DF1700035BE1A /* OWSLinkedDevicesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSLinkedDevicesTableViewController.m; sourceTree = ""; }; - 34B3F8621E8DF1700035BE1A /* OWSQRCodeScanningViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSQRCodeScanningViewController.h; sourceTree = ""; }; - 34B3F8631E8DF1700035BE1A /* OWSQRCodeScanningViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSQRCodeScanningViewController.m; sourceTree = ""; }; - 34B3F8641E8DF1700035BE1A /* PrivacySettingsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrivacySettingsTableViewController.h; sourceTree = ""; }; - 34B3F8651E8DF1700035BE1A /* PrivacySettingsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PrivacySettingsTableViewController.m; sourceTree = ""; }; - 34B3F8661E8DF1700035BE1A /* RegistrationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegistrationViewController.h; sourceTree = ""; }; - 34B3F8671E8DF1700035BE1A /* RegistrationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RegistrationViewController.m; sourceTree = ""; }; - 34B3F8681E8DF1700035BE1A /* AppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppSettingsViewController.h; sourceTree = ""; }; - 34B3F8691E8DF1700035BE1A /* AppSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppSettingsViewController.m; sourceTree = ""; }; - 34B3F86A1E8DF1700035BE1A /* ShowGroupMembersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShowGroupMembersViewController.h; sourceTree = ""; }; - 34B3F86B1E8DF1700035BE1A /* ShowGroupMembersViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ShowGroupMembersViewController.m; sourceTree = ""; }; 34B3F86D1E8DF1700035BE1A /* SignalsNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignalsNavigationController.h; sourceTree = ""; }; 34B3F86E1E8DF1700035BE1A /* SignalsNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalsNavigationController.m; sourceTree = ""; }; 34B3F86F1E8DF1700035BE1A /* HomeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HomeViewController.h; sourceTree = ""; }; 34B3F8701E8DF1700035BE1A /* HomeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HomeViewController.m; sourceTree = ""; }; - 34B3F89A1E8DF3270035BE1A /* BlockListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockListViewController.h; sourceTree = ""; }; - 34B3F89B1E8DF3270035BE1A /* BlockListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BlockListViewController.m; sourceTree = ""; }; 34B3F89D1E8DF5490035BE1A /* OWSTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSTableViewController.h; sourceTree = ""; }; 34B3F89E1E8DF5490035BE1A /* OWSTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSTableViewController.m; sourceTree = ""; }; 34BECE291F74C12700D7438D /* DebugUIStress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUIStress.h; sourceTree = ""; }; @@ -739,8 +743,6 @@ 34CA1C281F7164F700E51C51 /* MediaMessageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaMessageView.swift; sourceTree = ""; }; 34CCAF361F0C0599004084F4 /* AppUpdateNag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppUpdateNag.h; sourceTree = ""; }; 34CCAF371F0C0599004084F4 /* AppUpdateNag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppUpdateNag.m; sourceTree = ""; }; - 34CCAF391F0C2748004084F4 /* OWSAddToContactViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSAddToContactViewController.h; sourceTree = ""; }; - 34CCAF3A1F0C2748004084F4 /* OWSAddToContactViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSAddToContactViewController.m; sourceTree = ""; }; 34CE88E51F2FB9A10098030F /* ProfileViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProfileViewController.h; sourceTree = ""; }; 34CE88E61F2FB9A10098030F /* ProfileViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProfileViewController.m; sourceTree = ""; }; 34CF0783203E6B77005C4D61 /* busy_tone_ansi.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = busy_tone_ansi.caf; path = Signal/AudioFiles/busy_tone_ansi.caf; sourceTree = SOURCE_ROOT; }; @@ -784,7 +786,6 @@ 34D1F0BF1F8EC1760066283D /* MessageRecipientStatusUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageRecipientStatusUtils.swift; sourceTree = ""; }; 34D5CCA71EAE3D30005515DB /* AvatarViewHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AvatarViewHelper.h; sourceTree = ""; }; 34D5CCA81EAE3D30005515DB /* AvatarViewHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AvatarViewHelper.m; sourceTree = ""; }; - 34D5CCAB1EAE7136005515DB /* OWSConversationSettingsViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSConversationSettingsViewDelegate.h; sourceTree = ""; }; 34D8C0231ED3673300188D7C /* DebugUIMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUIMessages.h; sourceTree = ""; }; 34D8C0241ED3673300188D7C /* DebugUIMessages.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugUIMessages.m; sourceTree = ""; }; 34D8C0251ED3673300188D7C /* DebugUITableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUITableViewController.h; sourceTree = ""; }; @@ -797,15 +798,11 @@ 34D99C911F2937CC00D284D6 /* OWSAnalytics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSAnalytics.swift; sourceTree = ""; }; 34DB0BEB2011548A007B313F /* OWSDatabaseConverterTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSDatabaseConverterTest.h; sourceTree = ""; }; 34DB0BEC2011548B007B313F /* OWSDatabaseConverterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDatabaseConverterTest.m; sourceTree = ""; }; - 34DFCB831E8E04B400053165 /* AddToBlockListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddToBlockListViewController.h; sourceTree = ""; }; - 34DFCB841E8E04B500053165 /* AddToBlockListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddToBlockListViewController.m; sourceTree = ""; }; 34E3E5671EC4B19400495BAC /* AudioProgressView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioProgressView.swift; sourceTree = ""; }; 34E3EF0B1EFC235B007F6822 /* DebugUIDiskUsage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUIDiskUsage.h; sourceTree = ""; }; 34E3EF0C1EFC235B007F6822 /* DebugUIDiskUsage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugUIDiskUsage.m; sourceTree = ""; }; 34E3EF0E1EFC2684007F6822 /* DebugUIPage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUIPage.h; sourceTree = ""; }; 34E3EF0F1EFC2684007F6822 /* DebugUIPage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugUIPage.m; sourceTree = ""; }; - 34E8BF361EE9E2FD00F5F4CA /* FingerprintViewScanController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FingerprintViewScanController.h; sourceTree = ""; }; - 34E8BF371EE9E2FD00F5F4CA /* FingerprintViewScanController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FingerprintViewScanController.m; sourceTree = ""; }; 34F308A01ECB469700BB7697 /* OWSBezierPathView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBezierPathView.h; sourceTree = ""; }; 34F308A11ECB469700BB7697 /* OWSBezierPathView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSBezierPathView.m; sourceTree = ""; }; 34FD936E1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OWSAnyTouchGestureRecognizer.h; path = views/OWSAnyTouchGestureRecognizer.h; sourceTree = ""; }; @@ -1212,6 +1209,74 @@ path = Signal/AudioFiles/messageReceivedSounds; sourceTree = SOURCE_ROOT; }; + 340FC875204DAC8C007AEB0F /* Registration */ = { + isa = PBXGroup; + children = ( + 340FC879204DAC8C007AEB0F /* CodeVerificationViewController.h */, + 340FC877204DAC8C007AEB0F /* CodeVerificationViewController.m */, + 340FC878204DAC8C007AEB0F /* RegistrationViewController.h */, + 340FC876204DAC8C007AEB0F /* RegistrationViewController.m */, + ); + path = Registration; + sourceTree = ""; + }; + 340FC87A204DAC8C007AEB0F /* AppSettings */ = { + isa = PBXGroup; + children = ( + 340FC884204DAC8C007AEB0F /* AboutTableViewController.h */, + 340FC893204DAC8C007AEB0F /* AboutTableViewController.m */, + 340FC892204DAC8C007AEB0F /* AddToBlockListViewController.h */, + 340FC886204DAC8C007AEB0F /* AddToBlockListViewController.m */, + 340FC881204DAC8C007AEB0F /* AdvancedSettingsTableViewController.h */, + 340FC88C204DAC8C007AEB0F /* AdvancedSettingsTableViewController.m */, + 340FC880204DAC8C007AEB0F /* AppSettingsViewController.h */, + 340FC88D204DAC8C007AEB0F /* AppSettingsViewController.m */, + 340FC890204DAC8C007AEB0F /* BlockListViewController.h */, + 340FC887204DAC8C007AEB0F /* BlockListViewController.m */, + 340FC889204DAC8C007AEB0F /* DomainFrontingCountryViewController.h */, + 340FC87D204DAC8C007AEB0F /* DomainFrontingCountryViewController.m */, + 340FC88B204DAC8C007AEB0F /* NotificationSettingsOptionsViewController.h */, + 340FC87B204DAC8C007AEB0F /* NotificationSettingsOptionsViewController.m */, + 340FC88A204DAC8C007AEB0F /* NotificationSettingsViewController.h */, + 340FC87C204DAC8C007AEB0F /* NotificationSettingsViewController.m */, + 340FC87F204DAC8C007AEB0F /* OWSBackupSettingsViewController.h */, + 340FC88E204DAC8C007AEB0F /* OWSBackupExportViewController.m */, + 340FC891204DAC8C007AEB0F /* OWSLinkDeviceViewController.h */, + 340FC885204DAC8C007AEB0F /* OWSLinkDeviceViewController.m */, + 340FC895204DAC8C007AEB0F /* OWSLinkedDevicesTableViewController.h */, + 340FC882204DAC8C007AEB0F /* OWSLinkedDevicesTableViewController.m */, + 340FC888204DAC8C007AEB0F /* OWSQRCodeScanningViewController.h */, + 340FC896204DAC8C007AEB0F /* OWSQRCodeScanningViewController.m */, + 340FC894204DAC8C007AEB0F /* OWSSoundSettingsViewController.h */, + 340FC883204DAC8C007AEB0F /* OWSSoundSettingsViewController.m */, + 340FC88F204DAC8C007AEB0F /* PrivacySettingsTableViewController.h */, + 340FC87E204DAC8C007AEB0F /* PrivacySettingsTableViewController.m */, + ); + path = AppSettings; + sourceTree = ""; + }; + 340FC897204DAC8D007AEB0F /* ThreadSettings */ = { + isa = PBXGroup; + children = ( + 340FC8A4204DAC8D007AEB0F /* AddToGroupViewController.h */, + 340FC89B204DAC8D007AEB0F /* AddToGroupViewController.m */, + 340FC89D204DAC8D007AEB0F /* FingerprintViewController.h */, + 340FC8A2204DAC8D007AEB0F /* FingerprintViewController.m */, + 340FC8A5204DAC8D007AEB0F /* FingerprintViewScanController.h */, + 340FC89F204DAC8D007AEB0F /* FingerprintViewScanController.m */, + 340FC898204DAC8D007AEB0F /* OWSAddToContactViewController.h */, + 340FC8A1204DAC8D007AEB0F /* OWSAddToContactViewController.m */, + 340FC8A0204DAC8D007AEB0F /* OWSConversationSettingsViewController.h */, + 340FC89A204DAC8D007AEB0F /* OWSConversationSettingsViewController.m */, + 340FC899204DAC8D007AEB0F /* OWSConversationSettingsViewDelegate.h */, + 340FC89E204DAC8D007AEB0F /* ShowGroupMembersViewController.h */, + 340FC8A6204DAC8D007AEB0F /* ShowGroupMembersViewController.m */, + 340FC8A3204DAC8D007AEB0F /* UpdateGroupViewController.h */, + 340FC89C204DAC8D007AEB0F /* UpdateGroupViewController.m */, + ); + path = ThreadSettings; + sourceTree = ""; + }; 34330A581E7875FB00DF2FB9 /* Fonts */ = { isa = PBXGroup; children = ( @@ -1440,35 +1505,16 @@ 34B3F8331E8DF1700035BE1A /* ViewControllers */ = { isa = PBXGroup; children = ( - 34B3F8341E8DF1700035BE1A /* AboutTableViewController.h */, - 34B3F8351E8DF1700035BE1A /* AboutTableViewController.m */, - 34DFCB831E8E04B400053165 /* AddToBlockListViewController.h */, - 34DFCB841E8E04B500053165 /* AddToBlockListViewController.m */, - 3472229D1EB22FFE00E53955 /* AddToGroupViewController.h */, - 3472229E1EB22FFE00E53955 /* AddToGroupViewController.m */, - 34B3F8361E8DF1700035BE1A /* AdvancedSettingsTableViewController.h */, - 34B3F8371E8DF1700035BE1A /* AdvancedSettingsTableViewController.m */, - 34B3F8681E8DF1700035BE1A /* AppSettingsViewController.h */, - 34B3F8691E8DF1700035BE1A /* AppSettingsViewController.m */, + 340FC87A204DAC8C007AEB0F /* AppSettings */, 34D5CCA71EAE3D30005515DB /* AvatarViewHelper.h */, 34D5CCA81EAE3D30005515DB /* AvatarViewHelper.m */, - 34B3F89A1E8DF3270035BE1A /* BlockListViewController.h */, - 34B3F89B1E8DF3270035BE1A /* BlockListViewController.m */, 34B3F83B1E8DF1700035BE1A /* CallViewController.swift */, - 34B3F83C1E8DF1700035BE1A /* CodeVerificationViewController.h */, - 34B3F83D1E8DF1700035BE1A /* CodeVerificationViewController.m */, 34B3F83E1E8DF1700035BE1A /* ContactsPicker.swift */, 34B3F83F1E8DF1700035BE1A /* ContactsPicker.xib */, 3448BFC01EDF0EA7005B2D69 /* ConversationView */, 346B66301F4E29B200E5122F /* CropScaleImageViewController.swift */, 34D8C0221ED3673300188D7C /* DebugUI */, - 3497DBED1ECE2E4700DB2605 /* DomainFrontingCountryViewController.h */, - 3497DBEE1ECE2E4700DB2605 /* DomainFrontingCountryViewController.m */, 34B3F8441E8DF1700035BE1A /* ExperienceUpgradesPageViewController.swift */, - 34B3F8451E8DF1700035BE1A /* FingerprintViewController.h */, - 34B3F8461E8DF1700035BE1A /* FingerprintViewController.m */, - 34E8BF361EE9E2FD00F5F4CA /* FingerprintViewScanController.h */, - 34E8BF371EE9E2FD00F5F4CA /* FingerprintViewScanController.m */, 34BECE2C1F7ABCE000D7438D /* GifPicker */, 34B3F86F1E8DF1700035BE1A /* HomeViewController.h */, 34B3F8701E8DF1700035BE1A /* HomeViewController.m */, @@ -1482,48 +1528,21 @@ 34B3F8501E8DF1700035BE1A /* NewContactThreadViewController.m */, 34B3F8541E8DF1700035BE1A /* NewGroupViewController.h */, 34B3F8551E8DF1700035BE1A /* NewGroupViewController.m */, - 34B3F8561E8DF1700035BE1A /* NotificationSettingsOptionsViewController.h */, - 34B3F8571E8DF1700035BE1A /* NotificationSettingsOptionsViewController.m */, - 34B3F8581E8DF1700035BE1A /* NotificationSettingsViewController.h */, - 34B3F8591E8DF1700035BE1A /* NotificationSettingsViewController.m */, 34A55F3620485464002CC6DE /* OWS2FARegistrationViewController.h */, 34A55F3520485464002CC6DE /* OWS2FARegistrationViewController.m */, 345BC30A2047030600257B7C /* OWS2FASettingsViewController.h */, 345BC30B2047030600257B7C /* OWS2FASettingsViewController.m */, - 34CCAF391F0C2748004084F4 /* OWSAddToContactViewController.h */, - 34CCAF3A1F0C2748004084F4 /* OWSAddToContactViewController.m */, - 347E0B772003CD7400BC2F76 /* OWSBackupExportViewController.h */, - 347E0B762003CD7400BC2F76 /* OWSBackupExportViewController.m */, - 347E0B792003CD7500BC2F76 /* OWSBackupImportViewController.h */, - 347E0B782003CD7400BC2F76 /* OWSBackupImportViewController.m */, - 34B3F85B1E8DF1700035BE1A /* OWSConversationSettingsViewController.h */, - 34B3F85C1E8DF1700035BE1A /* OWSConversationSettingsViewController.m */, - 34D5CCAB1EAE7136005515DB /* OWSConversationSettingsViewDelegate.h */, 3497DBEA1ECE257500DB2605 /* OWSCountryMetadata.h */, 3497DBEB1ECE257500DB2605 /* OWSCountryMetadata.m */, - 34B3F85D1E8DF1700035BE1A /* OWSLinkDeviceViewController.h */, - 34B3F85E1E8DF1700035BE1A /* OWSLinkDeviceViewController.m */, - 34B3F85F1E8DF1700035BE1A /* OWSLinkedDevicesTableViewController.h */, - 34B3F8601E8DF1700035BE1A /* OWSLinkedDevicesTableViewController.m */, 34C42D591F45F7A80072EC04 /* OWSNavigationController.h */, 34C42D5A1F45F7A80072EC04 /* OWSNavigationController.m */, - 34B3F8621E8DF1700035BE1A /* OWSQRCodeScanningViewController.h */, - 34B3F8631E8DF1700035BE1A /* OWSQRCodeScanningViewController.m */, - 34074F5A203D093B004596AE /* OWSSoundSettingsViewController.h */, - 34074F59203D093A004596AE /* OWSSoundSettingsViewController.m */, - 34B3F8641E8DF1700035BE1A /* PrivacySettingsTableViewController.h */, - 34B3F8651E8DF1700035BE1A /* PrivacySettingsTableViewController.m */, 34CE88E51F2FB9A10098030F /* ProfileViewController.h */, 34CE88E61F2FB9A10098030F /* ProfileViewController.m */, - 34B3F8661E8DF1700035BE1A /* RegistrationViewController.h */, - 34B3F8671E8DF1700035BE1A /* RegistrationViewController.m */, + 340FC875204DAC8C007AEB0F /* Registration */, 4585C4671ED8F8D200896AEA /* SafetyNumberConfirmationAlert.swift */, - 34B3F86A1E8DF1700035BE1A /* ShowGroupMembersViewController.h */, - 34B3F86B1E8DF1700035BE1A /* ShowGroupMembersViewController.m */, 34B3F86D1E8DF1700035BE1A /* SignalsNavigationController.h */, 34B3F86E1E8DF1700035BE1A /* SignalsNavigationController.m */, - 340CB2251EAC25820001CAA1 /* UpdateGroupViewController.h */, - 340CB2261EAC25820001CAA1 /* UpdateGroupViewController.m */, + 340FC897204DAC8D007AEB0F /* ThreadSettings */, 34D1F0BE1F8EC1760066283D /* Utils */, 45D2AC01204885170033C692 /* OWS2FAReminderViewController.swift */, ); @@ -1646,9 +1665,9 @@ 450DF2071E0DD29E003D14BE /* Notifications */, 34FD936E1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.h */, 34FD936F1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m */, + 4523149D1F7E916B003A428C /* SlideOffAnimatedTransition.swift */, 34B3F8331E8DF1700035BE1A /* ViewControllers */, 76EB052B18170B33006006FC /* Views */, - 4523149D1F7E916B003A428C /* SlideOffAnimatedTransition.swift */, ); name = UserInterface; sourceTree = ""; @@ -3029,7 +3048,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 34B3F8761E8DF1700035BE1A /* CodeVerificationViewController.m in Sources */, 3461293E1FD1D72B00532771 /* ExperienceUpgradeFinder.swift in Sources */, 34D1F0BD1F8D108C0066283D /* AttachmentUploadView.m in Sources */, 34D1F0BA1F8800D90066283D /* OWSAudioMessageView.m in Sources */, @@ -3037,9 +3055,11 @@ 45C9DEB81DF4E35A0065CA84 /* WebRTCCallMessageHandler.swift in Sources */, 34D1F0501F7D45A60066283D /* GifPickerCell.swift in Sources */, 34D99C931F2937CC00D284D6 /* OWSAnalytics.swift in Sources */, - 34B3F88E1E8DF1700035BE1A /* PrivacySettingsTableViewController.m in Sources */, + 340FC8B8204DAC8D007AEB0F /* AddToGroupViewController.m in Sources */, 341F2C0F1F2B8AE700D07D6B /* DebugUIMisc.m in Sources */, + 340FC8AF204DAC8D007AEB0F /* OWSLinkDeviceViewController.m in Sources */, 34E3EF0D1EFC235B007F6822 /* DebugUIDiskUsage.m in Sources */, + 340FC8B4204DAC8D007AEB0F /* OWSBackupExportViewController.m in Sources */, 34D1F0871F8678AA0066283D /* ConversationViewItem.m in Sources */, B6DA6B071B8A2F9A00CA6F98 /* AppStoreRating.m in Sources */, 451A13B11E13DED2000A50FD /* CallNotificationsAdapter.swift in Sources */, @@ -3053,17 +3073,18 @@ EF764C351DB67CC5000D9A87 /* UIViewController+Permissions.m in Sources */, 45CD81EF1DC030E7004C9430 /* SyncPushTokensJob.swift in Sources */, 45794E861E00620000066731 /* CallUIAdapter.swift in Sources */, + 340FC8BA204DAC8D007AEB0F /* FingerprintViewScanController.m in Sources */, 4585C4681ED8F8D200896AEA /* SafetyNumberConfirmationAlert.swift in Sources */, 450D19131F85236600970622 /* RemoteVideoView.m in Sources */, B6B9ECFC198B31BA00C620D3 /* PushManager.m in Sources */, 45DF5DF21DDB843F00C936C7 /* CompareSafetyNumbersActivity.swift in Sources */, 458DE9D91DEE7B360071BB03 /* OWSWebRTCDataProtos.pb.m in Sources */, 76EB063C18170B33006006FC /* NumberUtil.m in Sources */, - 34B3F88F1E8DF1710035BE1A /* RegistrationViewController.m in Sources */, 451166C01FD86B98000739BA /* AccountManager.swift in Sources */, 3430FE181F7751D4000EC51B /* GiphyAPI.swift in Sources */, 34A55F3720485465002CC6DE /* OWS2FARegistrationViewController.m in Sources */, - 34B3F8901E8DF1710035BE1A /* AppSettingsViewController.m in Sources */, + 340FC8AD204DAC8D007AEB0F /* OWSLinkedDevicesTableViewController.m in Sources */, + 340FC8AA204DAC8D007AEB0F /* NotificationSettingsViewController.m in Sources */, 34FD93701E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m in Sources */, 34B3F8931E8DF1710035BE1A /* SignalsNavigationController.m in Sources */, 34D1F0AC1F867BFC0066283D /* OWSExpirationTimerView.m in Sources */, @@ -3076,29 +3097,26 @@ 34D1F0AE1F867BFC0066283D /* OWSMessageCell.m in Sources */, 451686AB1F520CDA00AC3D4B /* MultiDeviceProfileKeyUpdateJob.swift in Sources */, 45D231771DC7E8F10034FA89 /* SessionResetJob.swift in Sources */, + 340FC8A9204DAC8D007AEB0F /* NotificationSettingsOptionsViewController.m in Sources */, 452037D11EE84975004E4CDF /* DebugUISessionState.m in Sources */, D221A09A169C9E5E00537ABF /* main.m in Sources */, 34B3F87B1E8DF1700035BE1A /* ExperienceUpgradesPageViewController.swift in Sources */, 452EA09E1EA7ABE00078744B /* AttachmentPointerView.swift in Sources */, - 34B3F87C1E8DF1700035BE1A /* FingerprintViewController.m in Sources */, 45638BDC1F3DD0D400128435 /* DebugUICalling.swift in Sources */, 45464DBC1DFA041F001D3FD6 /* DataChannelMessage.swift in Sources */, 34E3E5681EC4B19400495BAC /* AudioProgressView.swift in Sources */, 34D1F0521F7E8EA30066283D /* GiphyDownloader.swift in Sources */, + 340FC8BC204DAC8D007AEB0F /* FingerprintViewController.m in Sources */, 450DF2051E0D74AC003D14BE /* Platform.swift in Sources */, + 340FC8B2204DAC8D007AEB0F /* AdvancedSettingsTableViewController.m in Sources */, 346129991FD1E4DA00532771 /* SignalApp.m in Sources */, 34BECE301F7ABCF800D7438D /* GifPickerLayout.swift in Sources */, - 3472229F1EB22FFE00E53955 /* AddToGroupViewController.m in Sources */, 343A65951FC47D5E000477A1 /* DebugUISyncMessages.m in Sources */, 45C0DC1E1E69011F00E04C47 /* UIStoryboard+OWS.swift in Sources */, - 34B3F8861E8DF1700035BE1A /* NotificationSettingsOptionsViewController.m in Sources */, 452ECA4D1E087E7200E2F016 /* MessageFetcherJob.swift in Sources */, 4556FA681F54AA9500AF40DD /* DebugUIProfile.swift in Sources */, - 34DFCB851E8E04B500053165 /* AddToBlockListViewController.m in Sources */, 45A6DAD61EBBF85500893231 /* ReminderView.swift in Sources */, - 34B3F88A1E8DF1700035BE1A /* OWSLinkDeviceViewController.m in Sources */, 34D1F0881F8678AA0066283D /* ConversationViewLayout.m in Sources */, - 3497DBEF1ECE2E4700DB2605 /* DomainFrontingCountryViewController.m in Sources */, 452314A01F7E9E18003A428C /* DirectionalPanGestureRecognizer.swift in Sources */, 34330AA31E79686200DF2FB9 /* OWSProgressView.m in Sources */, 34CA1C271F7156F300E51C51 /* MessageDetailViewController.swift in Sources */, @@ -3107,10 +3125,9 @@ 34D1F0B71F87F8850066283D /* OWSGenericAttachmentView.m in Sources */, 34B3F8801E8DF1700035BE1A /* InviteFlow.swift in Sources */, 457C87B82032645C008D52D6 /* DebugUINotifications.swift in Sources */, - 34B3F8871E8DF1700035BE1A /* NotificationSettingsViewController.m in Sources */, - 347E0B7B2003CD7500BC2F76 /* OWSBackupImportViewController.m in Sources */, 458E38371D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m in Sources */, 4517642B1DE939FD00EDB8B9 /* ContactCell.swift in Sources */, + 340FC8AB204DAC8D007AEB0F /* DomainFrontingCountryViewController.m in Sources */, 34B3F8751E8DF1700035BE1A /* CallViewController.swift in Sources */, 34D8C0281ED3673300188D7C /* DebugUITableViewController.m in Sources */, 3497DBEC1ECE257500DB2605 /* OWSCountryMetadata.m in Sources */, @@ -3119,50 +3136,50 @@ 34D1F0B41F86D31D0066283D /* ConversationCollectionView.m in Sources */, 34B3F8821E8DF1700035BE1A /* NewContactThreadViewController.m in Sources */, 45D308AD2049A439000189E4 /* PinEntryView.m in Sources */, + 340FC8B1204DAC8D007AEB0F /* BlockListViewController.m in Sources */, 45F659821E1BE77000444429 /* NonCallKitCallUIAdaptee.swift in Sources */, 45AE48511E0732D6004D96C2 /* TurnServerInfo.swift in Sources */, 34B3F8771E8DF1700035BE1A /* ContactsPicker.swift in Sources */, 45C0DC1B1E68FE9000E04C47 /* UIApplication+OWS.swift in Sources */, 45638BDF1F3DDB2200128435 /* MessageSender+Promise.swift in Sources */, 45FBC5C81DF8575700E9B410 /* CallKitCallManager.swift in Sources */, - 34B3F8911E8DF1710035BE1A /* ShowGroupMembersViewController.m in Sources */, 4539B5861F79348F007141FF /* PushRegistrationManager.swift in Sources */, 45FBC5D11DF8592E00E9B410 /* SignalCall.swift in Sources */, + 340FC8BB204DAC8D007AEB0F /* OWSAddToContactViewController.m in Sources */, 4523149E1F7E916B003A428C /* SlideOffAnimatedTransition.swift in Sources */, + 340FC8A7204DAC8D007AEB0F /* RegistrationViewController.m in Sources */, 452C468F1E427E200087B011 /* OutboundCallInitiator.swift in Sources */, 45F170BB1E2FC5D3003FC1F2 /* CallAudioService.swift in Sources */, 345BC30C2047030700257B7C /* OWS2FASettingsViewController.m in Sources */, - 34B3F8711E8DF1700035BE1A /* AboutTableViewController.m in Sources */, - 34B3F88D1E8DF1700035BE1A /* OWSQRCodeScanningViewController.m in Sources */, + 340FC8B7204DAC8D007AEB0F /* OWSConversationSettingsViewController.m in Sources */, 34BECE2E1F7ABCE000D7438D /* GifPickerViewController.swift in Sources */, - 34CCAF3B1F0C2748004084F4 /* OWSAddToContactViewController.m in Sources */, 34D1F0C01F8EC1760066283D /* MessageRecipientStatusUtils.swift in Sources */, 45F659731E1BD99C00444429 /* CallKitCallUIAdaptee.swift in Sources */, 45BB93381E688E14001E3939 /* UIDevice+featureSupport.swift in Sources */, 45B9EE9C200E91FB005D2F2D /* MediaDetailViewController.m in Sources */, 458DE9D61DEE3FD00071BB03 /* PeerConnectionClient.swift in Sources */, 34D1F0841F8678AA0066283D /* ConversationInputToolbar.m in Sources */, - 340CB2271EAC25820001CAA1 /* UpdateGroupViewController.m in Sources */, FCC81A981A44558300DFEC7D /* UIDevice+TSHardwareVersion.m in Sources */, 76EB054018170B33006006FC /* AppDelegate.m in Sources */, 34D1F0831F8678AA0066283D /* ConversationInputTextView.m in Sources */, - 347E0B7A2003CD7500BC2F76 /* OWSBackupExportViewController.m in Sources */, + 340FC8B6204DAC8D007AEB0F /* OWSQRCodeScanningViewController.m in Sources */, 34D1F0B11F867BFC0066283D /* OWSUnreadIndicatorCell.m in Sources */, - 34B3F89C1E8DF3270035BE1A /* BlockListViewController.m in Sources */, + 340FC8B5204DAC8D007AEB0F /* AboutTableViewController.m in Sources */, 34BECE2B1F74C12700D7438D /* DebugUIStress.m in Sources */, - 34074F5B203D093B004596AE /* OWSSoundSettingsViewController.m in Sources */, 34C42D5B1F45F7A80072EC04 /* OWSNavigationController.m in Sources */, + 340FC8B9204DAC8D007AEB0F /* UpdateGroupViewController.m in Sources */, B609597C1C2C0FC6004E8797 /* iRate.m in Sources */, 4574A5D61DD6704700C6B692 /* CallService.swift in Sources */, - 34B3F8721E8DF1700035BE1A /* AdvancedSettingsTableViewController.m in Sources */, + 340FC8A8204DAC8D007AEB0F /* CodeVerificationViewController.m in Sources */, 3461299C1FD1EA9E00532771 /* NotificationsManager.m in Sources */, 4521C3C01F59F3BA00B4C582 /* TextFieldHelper.swift in Sources */, - 34B3F8891E8DF1700035BE1A /* OWSConversationSettingsViewController.m in Sources */, 34B3F87E1E8DF1700035BE1A /* InboxTableViewCell.m in Sources */, - 34B3F88B1E8DF1700035BE1A /* OWSLinkedDevicesTableViewController.m in Sources */, + 340FC8AC204DAC8D007AEB0F /* PrivacySettingsTableViewController.m in Sources */, + 340FC8AE204DAC8D007AEB0F /* OWSSoundSettingsViewController.m in Sources */, 4579431E1E7C8CE9008ED0C0 /* Pastelog.m in Sources */, 34B3F8941E8DF1710035BE1A /* HomeViewController.m in Sources */, - 34E8BF381EE9E2FD00F5F4CA /* FingerprintViewScanController.m in Sources */, + 340FC8B0204DAC8D007AEB0F /* AddToBlockListViewController.m in Sources */, + 340FC8B3204DAC8D007AEB0F /* AppSettingsViewController.m in Sources */, 346B66311F4E29B200E5122F /* CropScaleImageViewController.swift in Sources */, 45E5A6991F61E6DE001E4A8A /* MarqueeLabel.swift in Sources */, 34A910601FFEB114000C4745 /* OWSBackup.m in Sources */, @@ -3170,6 +3187,7 @@ 45A663C51F92EC760027B59E /* GroupTableViewCell.swift in Sources */, 34D1F0861F8678AA0066283D /* ConversationViewController.m in Sources */, B90418E6183E9DD40038554A /* DateUtil.m in Sources */, + 340FC8BD204DAC8D007AEB0F /* ShowGroupMembersViewController.m in Sources */, 459311FC1D75C948008DD4F0 /* OWSDeviceTableViewCell.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 08dbc7515..2dc8fca1a 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -10,7 +10,6 @@ #import "MainAppContext.h" #import "NotificationsManager.h" #import "OWS2FASettingsViewController.h" -#import "OWSBackup.h" #import "OWSNavigationController.h" #import "Pastelog.h" #import "PushManager.h" @@ -149,10 +148,6 @@ static NSString *const kURLHostVerifyPrefix = @"verify"; [self startupLogging]; - // If a backup restore is in progress, try to complete it. - // Otherwise, cleanup backup state. - [OWSBackup applicationDidFinishLaunching]; - // Prevent the device from sleeping during database view async registration // (e.g. long database upgrades). // diff --git a/Signal/src/ViewControllers/AboutTableViewController.h b/Signal/src/ViewControllers/AppSettings/AboutTableViewController.h similarity index 63% rename from Signal/src/ViewControllers/AboutTableViewController.h rename to Signal/src/ViewControllers/AppSettings/AboutTableViewController.h index f0cb0a2c7..ee8bbf74c 100644 --- a/Signal/src/ViewControllers/AboutTableViewController.h +++ b/Signal/src/ViewControllers/AppSettings/AboutTableViewController.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSTableViewController.h" diff --git a/Signal/src/ViewControllers/AboutTableViewController.m b/Signal/src/ViewControllers/AppSettings/AboutTableViewController.m similarity index 93% rename from Signal/src/ViewControllers/AboutTableViewController.m rename to Signal/src/ViewControllers/AppSettings/AboutTableViewController.m index 88de4003d..4652b6294 100644 --- a/Signal/src/ViewControllers/AboutTableViewController.m +++ b/Signal/src/ViewControllers/AppSettings/AboutTableViewController.m @@ -13,7 +13,8 @@ @implementation AboutTableViewController -- (void)dealloc { +- (void)dealloc +{ [[NSNotificationCenter defaultCenter] removeObserver:self]; } @@ -88,8 +89,10 @@ OWSPreferences *preferences = [Environment preferences]; NSString *_Nullable pushToken = [preferences getPushToken]; NSString *_Nullable voipToken = [preferences getVoipToken]; - [debugSection addItem:[OWSTableItem labelItemWithText:[NSString stringWithFormat:@"Push Token: %@", pushToken ?: @"None" ]]]; - [debugSection addItem:[OWSTableItem labelItemWithText:[NSString stringWithFormat:@"VOIP Token: %@", voipToken ?: @"None" ]]]; + [debugSection + addItem:[OWSTableItem labelItemWithText:[NSString stringWithFormat:@"Push Token: %@", pushToken ?: @"None"]]]; + [debugSection + addItem:[OWSTableItem labelItemWithText:[NSString stringWithFormat:@"VOIP Token: %@", voipToken ?: @"None"]]]; // Strip prefix from category, otherwise it's too long to fit into cell on a small device. NSString *audioCategory = diff --git a/Signal/src/ViewControllers/AddToBlockListViewController.h b/Signal/src/ViewControllers/AppSettings/AddToBlockListViewController.h similarity index 67% rename from Signal/src/ViewControllers/AddToBlockListViewController.h rename to Signal/src/ViewControllers/AppSettings/AddToBlockListViewController.h index 17f5628ec..e48943c08 100644 --- a/Signal/src/ViewControllers/AddToBlockListViewController.h +++ b/Signal/src/ViewControllers/AppSettings/AddToBlockListViewController.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "SelectRecipientViewController.h" diff --git a/Signal/src/ViewControllers/AddToBlockListViewController.m b/Signal/src/ViewControllers/AppSettings/AddToBlockListViewController.m similarity index 98% rename from Signal/src/ViewControllers/AddToBlockListViewController.m rename to Signal/src/ViewControllers/AppSettings/AddToBlockListViewController.m index f0469b474..b12a63c4c 100644 --- a/Signal/src/ViewControllers/AddToBlockListViewController.m +++ b/Signal/src/ViewControllers/AppSettings/AddToBlockListViewController.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "AddToBlockListViewController.h" @@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN self.delegate = self; [super loadView]; - + self.title = NSLocalizedString(@"SETTINGS_ADD_TO_BLOCK_LIST_TITLE", @"Title for the 'add to block list' view."); } diff --git a/Signal/src/ViewControllers/AdvancedSettingsTableViewController.h b/Signal/src/ViewControllers/AppSettings/AdvancedSettingsTableViewController.h similarity index 65% rename from Signal/src/ViewControllers/AdvancedSettingsTableViewController.h rename to Signal/src/ViewControllers/AppSettings/AdvancedSettingsTableViewController.h index 46c9b0ba4..f52659d84 100644 --- a/Signal/src/ViewControllers/AdvancedSettingsTableViewController.h +++ b/Signal/src/ViewControllers/AppSettings/AdvancedSettingsTableViewController.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSTableViewController.h" diff --git a/Signal/src/ViewControllers/AdvancedSettingsTableViewController.m b/Signal/src/ViewControllers/AppSettings/AdvancedSettingsTableViewController.m similarity index 98% rename from Signal/src/ViewControllers/AdvancedSettingsTableViewController.m rename to Signal/src/ViewControllers/AppSettings/AdvancedSettingsTableViewController.m index 7bc0553e3..76ddba6a9 100644 --- a/Signal/src/ViewControllers/AdvancedSettingsTableViewController.m +++ b/Signal/src/ViewControllers/AppSettings/AdvancedSettingsTableViewController.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "AdvancedSettingsTableViewController.h" @@ -254,7 +254,8 @@ NS_ASSUME_NONNULL_BEGIN }); } -- (void)didToggleEnableLogSwitch:(UISwitch *)sender { +- (void)didToggleEnableLogSwitch:(UISwitch *)sender +{ if (!sender.isOn) { [[DebugLogger sharedLogger] wipeLogs]; [[DebugLogger sharedLogger] disableFileLogging]; diff --git a/Signal/src/ViewControllers/AppSettingsViewController.h b/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.h similarity index 81% rename from Signal/src/ViewControllers/AppSettingsViewController.h rename to Signal/src/ViewControllers/AppSettings/AppSettingsViewController.h index cff8085b4..a1d96e446 100644 --- a/Signal/src/ViewControllers/AppSettingsViewController.h +++ b/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSTableViewController.h" diff --git a/Signal/src/ViewControllers/AppSettingsViewController.m b/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.m similarity index 95% rename from Signal/src/ViewControllers/AppSettingsViewController.m rename to Signal/src/ViewControllers/AppSettings/AppSettingsViewController.m index b7fee9fa2..36dfa756a 100644 --- a/Signal/src/ViewControllers/AppSettingsViewController.m +++ b/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.m @@ -7,6 +7,7 @@ #import "AdvancedSettingsTableViewController.h" #import "DebugUITableViewController.h" #import "NotificationSettingsViewController.h" +#import "OWSBackupSettingsViewController.h" #import "OWSLinkedDevicesTableViewController.h" #import "OWSNavigationController.h" #import "PrivacySettingsTableViewController.h" @@ -187,6 +188,13 @@ actionBlock:^{ [weakSelf showAdvanced]; }]]; +#ifdef DEBUG + [section addItem:[OWSTableItem disclosureItemWithText:NSLocalizedString(@"SETTINGS_BACKUP", + @"Label for the backup view in app settings.") + actionBlock:^{ + [weakSelf showBackup]; + }]]; +#endif [section addItem:[OWSTableItem disclosureItemWithText:NSLocalizedString(@"SETTINGS_ABOUT", @"") actionBlock:^{ [weakSelf showAbout]; @@ -304,7 +312,8 @@ [disclosureButton autoVCenterInSuperview]; [disclosureButton autoPinTrailingToSuperview]; [disclosureButton autoPinLeadingToTrailingOfView:nameView margin:16.f]; - [disclosureButton setContentCompressionResistancePriority:(UILayoutPriorityDefaultHigh + 1) forAxis:UILayoutConstraintAxisHorizontal]; + [disclosureButton setContentCompressionResistancePriority:(UILayoutPriorityDefaultHigh + 1) + forAxis:UILayoutConstraintAxisHorizontal]; return cell; } @@ -352,6 +361,13 @@ [self.navigationController pushViewController:vc animated:YES]; } +- (void)showBackup +{ + OWSBackupSettingsViewController *vc = [OWSBackupSettingsViewController new]; + [self.navigationController pushViewController:vc animated:YES]; +}]]; +} + - (void)showDebugUI { [DebugUITableViewController presentDebugUIFromViewController:self]; diff --git a/Signal/src/ViewControllers/BlockListViewController.h b/Signal/src/ViewControllers/AppSettings/BlockListViewController.h similarity index 100% rename from Signal/src/ViewControllers/BlockListViewController.h rename to Signal/src/ViewControllers/AppSettings/BlockListViewController.h diff --git a/Signal/src/ViewControllers/BlockListViewController.m b/Signal/src/ViewControllers/AppSettings/BlockListViewController.m similarity index 98% rename from Signal/src/ViewControllers/BlockListViewController.m rename to Signal/src/ViewControllers/AppSettings/BlockListViewController.m index b745ead90..f943644f2 100644 --- a/Signal/src/ViewControllers/BlockListViewController.m +++ b/Signal/src/ViewControllers/AppSettings/BlockListViewController.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "BlockListViewController.h" diff --git a/Signal/src/ViewControllers/DomainFrontingCountryViewController.h b/Signal/src/ViewControllers/AppSettings/DomainFrontingCountryViewController.h similarity index 100% rename from Signal/src/ViewControllers/DomainFrontingCountryViewController.h rename to Signal/src/ViewControllers/AppSettings/DomainFrontingCountryViewController.h diff --git a/Signal/src/ViewControllers/DomainFrontingCountryViewController.m b/Signal/src/ViewControllers/AppSettings/DomainFrontingCountryViewController.m similarity index 97% rename from Signal/src/ViewControllers/DomainFrontingCountryViewController.m rename to Signal/src/ViewControllers/AppSettings/DomainFrontingCountryViewController.m index cdd603f35..b2f22a7a5 100644 --- a/Signal/src/ViewControllers/DomainFrontingCountryViewController.m +++ b/Signal/src/ViewControllers/AppSettings/DomainFrontingCountryViewController.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "DomainFrontingCountryViewController.h" diff --git a/Signal/src/ViewControllers/NotificationSettingsOptionsViewController.h b/Signal/src/ViewControllers/AppSettings/NotificationSettingsOptionsViewController.h similarity index 66% rename from Signal/src/ViewControllers/NotificationSettingsOptionsViewController.h rename to Signal/src/ViewControllers/AppSettings/NotificationSettingsOptionsViewController.h index c79105d69..450655b91 100644 --- a/Signal/src/ViewControllers/NotificationSettingsOptionsViewController.h +++ b/Signal/src/ViewControllers/AppSettings/NotificationSettingsOptionsViewController.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSTableViewController.h" diff --git a/Signal/src/ViewControllers/NotificationSettingsOptionsViewController.m b/Signal/src/ViewControllers/AppSettings/NotificationSettingsOptionsViewController.m similarity index 98% rename from Signal/src/ViewControllers/NotificationSettingsOptionsViewController.m rename to Signal/src/ViewControllers/AppSettings/NotificationSettingsOptionsViewController.m index 04a83c3e2..5944955a0 100644 --- a/Signal/src/ViewControllers/NotificationSettingsOptionsViewController.m +++ b/Signal/src/ViewControllers/AppSettings/NotificationSettingsOptionsViewController.m @@ -9,7 +9,8 @@ @implementation NotificationSettingsOptionsViewController -- (void)viewDidLoad { +- (void)viewDidLoad +{ [self updateTableContents]; } diff --git a/Signal/src/ViewControllers/NotificationSettingsViewController.h b/Signal/src/ViewControllers/AppSettings/NotificationSettingsViewController.h similarity index 65% rename from Signal/src/ViewControllers/NotificationSettingsViewController.h rename to Signal/src/ViewControllers/AppSettings/NotificationSettingsViewController.h index 56ff55d1b..4ed3f2f81 100644 --- a/Signal/src/ViewControllers/NotificationSettingsViewController.h +++ b/Signal/src/ViewControllers/AppSettings/NotificationSettingsViewController.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSTableViewController.h" diff --git a/Signal/src/ViewControllers/NotificationSettingsViewController.m b/Signal/src/ViewControllers/AppSettings/NotificationSettingsViewController.m similarity index 96% rename from Signal/src/ViewControllers/NotificationSettingsViewController.m rename to Signal/src/ViewControllers/AppSettings/NotificationSettingsViewController.m index 0c0a8eaa4..62fd0b92c 100644 --- a/Signal/src/ViewControllers/NotificationSettingsViewController.m +++ b/Signal/src/ViewControllers/AppSettings/NotificationSettingsViewController.m @@ -11,7 +11,8 @@ @implementation NotificationSettingsViewController -- (void)viewDidLoad { +- (void)viewDidLoad +{ [super viewDidLoad]; [self setTitle:NSLocalizedString(@"SETTINGS_NOTIFICATIONS", nil)]; @@ -19,7 +20,8 @@ [self updateTableContents]; } -- (void)viewDidAppear:(BOOL)animated { +- (void)viewDidAppear:(BOOL)animated +{ [self updateTableContents]; } @@ -32,9 +34,9 @@ __weak NotificationSettingsViewController *weakSelf = self; OWSPreferences *prefs = [Environment preferences]; - + // Sounds section. - + OWSTableSection *soundsSection = [OWSTableSection new]; soundsSection.headerTitle = NSLocalizedString(@"SETTINGS_SECTION_SOUNDS", @"Header Label for the sounds section of settings views."); @@ -56,7 +58,7 @@ target:weakSelf selector:@selector(didToggleSoundNotificationsSwitch:)]]; [contents addSection:soundsSection]; - + OWSTableSection *backgroundSection = [OWSTableSection new]; backgroundSection.headerTitle = NSLocalizedString(@"SETTINGS_NOTIFICATION_CONTENT_TITLE", @"table section header"); [backgroundSection @@ -77,7 +79,8 @@ #pragma mark - Events -- (void)didToggleSoundNotificationsSwitch:(UISwitch *)sender { +- (void)didToggleSoundNotificationsSwitch:(UISwitch *)sender +{ [Environment.preferences setSoundInForeground:sender.on]; } diff --git a/Signal/src/ViewControllers/AppSettings/OWSBackupExportViewController.m b/Signal/src/ViewControllers/AppSettings/OWSBackupExportViewController.m new file mode 100644 index 000000000..ff05792e3 --- /dev/null +++ b/Signal/src/ViewControllers/AppSettings/OWSBackupExportViewController.m @@ -0,0 +1,316 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +#import "OWSBackup.h" +#import "OWSBackupSettingsViewController.h" +#import "OWSProgressView.h" +#import "Signal-Swift.h" +#import "ThreadUtil.h" +#import +#import +#import +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface OWSBackupSettingsViewController () +// + +//@property (nonatomic) OWSBackup *backup; +// +//@property (nonatomic, nullable) OWSProgressView *progressView; + +@end + +#pragma mark - + +@implementation OWSBackupSettingsViewController + +//- (void)loadView +//{ +// [super loadView]; +// +// self.view.backgroundColor = [UIColor whiteColor]; +// +// self.navigationItem.title = NSLocalizedString(@"BACKUP_EXPORT_VIEW_TITLE", @"Title for the 'backup export' +// view."); self.navigationItem.leftBarButtonItem = +// [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop +// target:self +// action:@selector(dismissWasPressed:)]; +// +// self.backup.delegate = self; +// +// [self updateUI]; +//} +// +//- (void)exportBackup:(TSThread *_Nullable)currentThread skipPassword:(BOOL)skipPassword +//{ +// OWSAssertIsOnMainThread(); +// +// // We set ourselves as the delegate of the backup later, +// // after we've loaded our view. +// self.backup = [OWSBackup new]; +// [self.backup exportBackup:currentThread skipPassword:skipPassword]; +//} +// +//- (void)updateUI +//{ +// for (UIView *subview in self.view.subviews) { +// [subview removeFromSuperview]; +// } +// self.progressView = nil; +// +// switch (self.backup.backupState) { +// case OWSBackupState_InProgress: +// [self showInProgressUI]; +// break; +// case OWSBackupState_Cancelled: +// [self showCancelledUI]; +// break; +// case OWSBackupState_Complete: +// [self showCompleteUI]; +// break; +// case OWSBackupState_Failed: +// [self showFailedUI]; +// break; +// } +//} +// +//- (void)showInProgressUI +//{ +// self.progressView = [OWSProgressView new]; +// self.progressView.color = [UIColor ows_materialBlueColor]; +// self.progressView.progress = self.backup.backupProgress; +// [self.progressView autoSetDimension:ALDimensionWidth toSize:300]; +// [self.progressView autoSetDimension:ALDimensionHeight toSize:20]; +// +// UILabel *label = [UILabel new]; +// label.text = NSLocalizedString( +// @"BACKUP_EXPORT_IN_PROGRESS_MESSAGE", @"Message indicating that backup export is in progress."); +// label.textColor = [UIColor blackColor]; +// label.font = [UIFont ows_regularFontWithSize:18.f]; +// label.textAlignment = NSTextAlignmentCenter; +// label.numberOfLines = 0; +// label.lineBreakMode = NSLineBreakByWordWrapping; +// +// UIView *container = [UIView verticalStackWithSubviews:@[ +// label, +// self.progressView, +// ] +// spacing:10]; +// [self.view addSubview:container]; +// [container autoVCenterInSuperview]; +// [container autoPinWidthToSuperviewWithMargin:25.f]; +//} +// +//- (void)showCancelledUI +//{ +// // Show nothing. +//} +// +//- (void)showCompleteUI +//{ +// NSMutableArray *subviews = [NSMutableArray new]; +// +// { +// NSString *message = NSLocalizedString( +// @"BACKUP_EXPORT_COMPLETE_MESSAGE", @"Message indicating that backup export is complete."); +// +// UILabel *label = [UILabel new]; +// label.text = message; +// label.textColor = [UIColor blackColor]; +// label.font = [UIFont ows_regularFontWithSize:18.f]; +// label.textAlignment = NSTextAlignmentCenter; +// label.numberOfLines = 0; +// label.lineBreakMode = NSLineBreakByWordWrapping; +// [subviews addObject:label]; +// } +// +// if (self.backup.backupPassword) { +// NSString *message = [NSString stringWithFormat:NSLocalizedString(@"BACKUP_EXPORT_PASSWORD_MESSAGE_FORMAT", +// @"Format for message indicating that backup export " +// @"is complete. Embeds: {{the backup password}}."), +// self.backup.backupPassword]; +// +// UILabel *label = [UILabel new]; +// label.text = message; +// label.textColor = [UIColor blackColor]; +// label.font = [UIFont ows_regularFontWithSize:14.f]; +// label.textAlignment = NSTextAlignmentCenter; +// label.numberOfLines = 0; +// label.lineBreakMode = NSLineBreakByWordWrapping; +// [subviews addObject:label]; +// } +// +// [subviews addObject:[UIView new]]; +// +// if (self.backup.backupPassword) { +// [subviews +// addObject:[self makeButtonWithTitle:NSLocalizedString(@"BACKUP_EXPORT_COPY_PASSWORD_BUTTON", +// @"Label for button that copies backup password to the +// pasteboard.") +// selector:@selector(copyPassword)]]; +// } +// +// [subviews addObject:[self makeButtonWithTitle:NSLocalizedString(@"BACKUP_EXPORT_SHARE_BACKUP_BUTTON", +// @"Label for button that opens share UI for backup.") +// selector:@selector(shareBackup)]]; +// +// if (self.backup.currentThread) { +// [subviews +// addObject:[self makeButtonWithTitle:NSLocalizedString(@"BACKUP_EXPORT_SEND_BACKUP_BUTTON", +// @"Label for button that 'send backup' in the current +// conversation.") +// selector:@selector(sendBackup)]]; +// } +// +// // TODO: We should offer the option to save the backup to "Files", iCloud, Dropbox, etc. +// +// UIView *container = [UIView verticalStackWithSubviews:subviews spacing:10]; +// [self.view addSubview:container]; +// [container autoVCenterInSuperview]; +// [container autoPinWidthToSuperviewWithMargin:25.f]; +//} +// +//- (void)showFailedUI +//{ +// NSMutableArray *subviews = [NSMutableArray new]; +// +// { +// NSString *message +// = NSLocalizedString(@"BACKUP_EXPORT_FAILED_MESSAGE", @"Message indicating that backup export failed."); +// +// UILabel *label = [UILabel new]; +// label.text = message; +// label.textColor = [UIColor blackColor]; +// label.font = [UIFont ows_regularFontWithSize:18.f]; +// label.textAlignment = NSTextAlignmentCenter; +// label.numberOfLines = 0; +// label.lineBreakMode = NSLineBreakByWordWrapping; +// [subviews addObject:label]; +// } +// +// // TODO: We should offer the option to save the backup to "Files", iCloud, Dropbox, etc. +// +// UIView *container = [UIView verticalStackWithSubviews:subviews spacing:10]; +// [self.view addSubview:container]; +// [container autoVCenterInSuperview]; +// [container autoPinWidthToSuperviewWithMargin:25.f]; +//} +// +//- (UIView *)makeButtonWithTitle:(NSString *)title selector:(SEL)selector +//{ +// const CGFloat kButtonHeight = 40; +// OWSFlatButton *button = [OWSFlatButton buttonWithTitle:title +// font:[OWSFlatButton fontForHeight:kButtonHeight] +// titleColor:[UIColor whiteColor] +// backgroundColor:[UIColor ows_materialBlueColor] +// target:self +// selector:selector]; +// [button autoSetDimension:ALDimensionWidth toSize:140]; +// [button autoSetDimension:ALDimensionHeight toSize:kButtonHeight]; +// return button; +//} +// +//- (void)copyPassword +//{ +// OWSAssert(self.backup.backupPassword.length > 0); +// +// // TODO: We could consider clearing the password from the pasteboard after a certain delay. +// [UIPasteboard.generalPasteboard setString:self.backup.backupPassword]; +//} +// +//- (void)shareBackup +//{ +// OWSAssertIsOnMainThread(); +// OWSAssert(self.backup.backupZipPath.length > 0); +// +// [AttachmentSharing showShareUIForURL:[NSURL fileURLWithPath:self.backup.backupZipPath]]; +//} +// +//- (void)sendBackup +//{ +// OWSAssertIsOnMainThread(); +// OWSAssert(self.backup.backupZipPath.length > 0); +// OWSAssert(self.backup.currentThread); +// +// [ModalActivityIndicatorViewController +// presentFromViewController:self +// canCancel:NO +// backgroundBlock:^(ModalActivityIndicatorViewController *modalActivityIndicator) { +// NSString *fileName = [self.backup.backupZipPath lastPathComponent]; +// +// OWSMessageSender *messageSender = [Environment current].messageSender; +// NSString *utiType = [MIMETypeUtil utiTypeForFileExtension:fileName.pathExtension]; +// DataSource *_Nullable dataSource = +// [DataSourcePath dataSourceWithFilePath:self.backup.backupZipPath]; +// [dataSource setSourceFilename:fileName]; +// SignalAttachment *attachment = +// [SignalAttachment attachmentWithDataSource:dataSource dataUTI:utiType]; +// if (!attachment || [attachment hasError]) { +// OWSFail(@"%@ attachment[%@]: %@", +// self.logTag, +// [attachment sourceFilename], +// [attachment errorName]); +// return; +// } +// dispatch_async(dispatch_get_main_queue(), ^{ +// [ThreadUtil +// sendMessageWithAttachment:attachment +// inThread:self.backup.currentThread +// messageSender:messageSender +// completion:^(NSError *_Nullable error) { +// +// OWSAssertIsOnMainThread(); +// [modalActivityIndicator dismissWithCompletion:^{ +// if (error) { +// DDLogError(@"%@ send backup failed: %@", self.logTag, error); +// [OWSAlerts +// showAlertWithTitle:NSLocalizedString( +// @"BACKUP_EXPORT_SEND_BACKUP_FAILED", +// @"Message indicating that sending +// " +// @"the backup failed.")]; +// } else { +// [OWSAlerts +// showAlertWithTitle: +// NSLocalizedString(@"BACKUP_EXPORT_SEND_BACKUP_SUCCESS", +// @"Message indicating that sending the backup " +// @"succeeded.")]; +// } +// }]; +// }]; +// }); +// }]; +//} +// +//- (void)dismissWasPressed:(id)sender +//{ +// [self.backup cancel]; +// +// [self.navigationController popViewControllerAnimated:YES]; +//} +// +//#pragma mark - OWSBackupDelegate +// +//- (void)backupStateDidChange +//{ +// DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); +// +// [self updateUI]; +//} +// +//- (void)backupProgressDidChange +//{ +// DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); +// +// self.progressView.progress = self.backup.backupProgress; +//} + +@end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/AppSettings/OWSBackupSettingsViewController.h b/Signal/src/ViewControllers/AppSettings/OWSBackupSettingsViewController.h new file mode 100644 index 000000000..2224d9aeb --- /dev/null +++ b/Signal/src/ViewControllers/AppSettings/OWSBackupSettingsViewController.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +//@class TSThread; + +@interface OWSBackupSettingsViewController : OWSViewController + +//// If currentThread is non-nil, we should offer to let users send the +//// backup in that thread. +//- (void)exportBackup:(TSThread *_Nullable)currentThread skipPassword:(BOOL)skipPassword; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/OWSLinkDeviceViewController.h b/Signal/src/ViewControllers/AppSettings/OWSLinkDeviceViewController.h similarity index 100% rename from Signal/src/ViewControllers/OWSLinkDeviceViewController.h rename to Signal/src/ViewControllers/AppSettings/OWSLinkDeviceViewController.h diff --git a/Signal/src/ViewControllers/OWSLinkDeviceViewController.m b/Signal/src/ViewControllers/AppSettings/OWSLinkDeviceViewController.m similarity index 90% rename from Signal/src/ViewControllers/OWSLinkDeviceViewController.m rename to Signal/src/ViewControllers/AppSettings/OWSLinkDeviceViewController.m index 455d9c48f..48a9fc327 100644 --- a/Signal/src/ViewControllers/OWSLinkDeviceViewController.m +++ b/Signal/src/ViewControllers/AppSettings/OWSLinkDeviceViewController.m @@ -85,13 +85,12 @@ NS_ASSUME_NONNULL_BEGIN OWSDeviceProvisioningURLParser *parser = [[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:string]; if (!parser.isValid) { DDLogError(@"Unable to parse provisioning params from QRCode: %@", string); - - NSString* title = NSLocalizedString(@"LINK_DEVICE_INVALID_CODE_TITLE", @"report an invalid linking code"); - NSString* body = NSLocalizedString(@"LINK_DEVICE_INVALID_CODE_BODY", @"report an invalid linking code"); - - UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title - message:body - preferredStyle:UIAlertControllerStyleAlert]; + + NSString *title = NSLocalizedString(@"LINK_DEVICE_INVALID_CODE_TITLE", @"report an invalid linking code"); + NSString *body = NSLocalizedString(@"LINK_DEVICE_INVALID_CODE_BODY", @"report an invalid linking code"); + + UIAlertController *alertController = + [UIAlertController alertControllerWithTitle:title message:body preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:CommonStrings.cancelButton @@ -102,19 +101,19 @@ NS_ASSUME_NONNULL_BEGIN }); }]; [alertController addAction:cancelAction]; - + UIAlertAction *proceedAction = - [UIAlertAction actionWithTitle:NSLocalizedString(@"LINK_DEVICE_RESTART", @"attempt another linking") - style:UIAlertActionStyleDefault - handler:^(UIAlertAction *action) { - [self.qrScanningController startCapture]; - }]; + [UIAlertAction actionWithTitle:NSLocalizedString(@"LINK_DEVICE_RESTART", @"attempt another linking") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action) { + [self.qrScanningController startCapture]; + }]; [alertController addAction:proceedAction]; [self presentViewController:alertController animated:YES completion:nil]; } else { - NSString *title - = NSLocalizedString(@"LINK_DEVICE_PERMISSION_ALERT_TITLE", @"confirm the users intent to link a new device"); + NSString *title = NSLocalizedString( + @"LINK_DEVICE_PERMISSION_ALERT_TITLE", @"confirm the users intent to link a new device"); NSString *linkingDescription = NSLocalizedString(@"LINK_DEVICE_PERMISSION_ALERT_BODY", @"confirm the users intent to link a new device"); diff --git a/Signal/src/ViewControllers/OWSLinkedDevicesTableViewController.h b/Signal/src/ViewControllers/AppSettings/OWSLinkedDevicesTableViewController.h similarity index 78% rename from Signal/src/ViewControllers/OWSLinkedDevicesTableViewController.h rename to Signal/src/ViewControllers/AppSettings/OWSLinkedDevicesTableViewController.h index 5373b0db6..cb8352ec4 100644 --- a/Signal/src/ViewControllers/OWSLinkedDevicesTableViewController.h +++ b/Signal/src/ViewControllers/AppSettings/OWSLinkedDevicesTableViewController.h @@ -1,4 +1,6 @@ -// Copyright © 2016 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// #import diff --git a/Signal/src/ViewControllers/OWSLinkedDevicesTableViewController.m b/Signal/src/ViewControllers/AppSettings/OWSLinkedDevicesTableViewController.m similarity index 97% rename from Signal/src/ViewControllers/OWSLinkedDevicesTableViewController.m rename to Signal/src/ViewControllers/AppSettings/OWSLinkedDevicesTableViewController.m index f1224fa50..c002b6fdb 100644 --- a/Signal/src/ViewControllers/OWSLinkedDevicesTableViewController.m +++ b/Signal/src/ViewControllers/AppSettings/OWSLinkedDevicesTableViewController.m @@ -288,12 +288,11 @@ int const OWSLinkedDevicesTableViewControllerSectionAddDevice = 1; } } --(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES]; - if (indexPath.section == OWSLinkedDevicesTableViewControllerSectionAddDevice) - { + if (indexPath.section == OWSLinkedDevicesTableViewControllerSectionAddDevice) { [self ows_askForCameraPermissions:^(BOOL granted) { if (!granted) { return; @@ -358,11 +357,12 @@ int const OWSLinkedDevicesTableViewControllerSectionAddDevice = 1; { if (editingStyle == UITableViewCellEditingStyleDelete) { OWSDevice *device = [self deviceForRowAtIndexPath:indexPath]; - [self touchedUnlinkControlForDevice:device - success:^{ - DDLogInfo(@"Removing unlinked device with deviceId: %ld", (long)device.deviceId); - [device remove]; - }]; + [self + touchedUnlinkControlForDevice:device + success:^{ + DDLogInfo(@"Removing unlinked device with deviceId: %ld", (long)device.deviceId); + [device remove]; + }]; } } diff --git a/Signal/src/ViewControllers/OWSQRCodeScanningViewController.h b/Signal/src/ViewControllers/AppSettings/OWSQRCodeScanningViewController.h similarity index 100% rename from Signal/src/ViewControllers/OWSQRCodeScanningViewController.h rename to Signal/src/ViewControllers/AppSettings/OWSQRCodeScanningViewController.h diff --git a/Signal/src/ViewControllers/OWSQRCodeScanningViewController.m b/Signal/src/ViewControllers/AppSettings/OWSQRCodeScanningViewController.m similarity index 100% rename from Signal/src/ViewControllers/OWSQRCodeScanningViewController.m rename to Signal/src/ViewControllers/AppSettings/OWSQRCodeScanningViewController.m diff --git a/Signal/src/ViewControllers/OWSSoundSettingsViewController.h b/Signal/src/ViewControllers/AppSettings/OWSSoundSettingsViewController.h similarity index 100% rename from Signal/src/ViewControllers/OWSSoundSettingsViewController.h rename to Signal/src/ViewControllers/AppSettings/OWSSoundSettingsViewController.h diff --git a/Signal/src/ViewControllers/OWSSoundSettingsViewController.m b/Signal/src/ViewControllers/AppSettings/OWSSoundSettingsViewController.m similarity index 94% rename from Signal/src/ViewControllers/OWSSoundSettingsViewController.m rename to Signal/src/ViewControllers/AppSettings/OWSSoundSettingsViewController.m index 82a9025d9..1a65c77af 100644 --- a/Signal/src/ViewControllers/OWSSoundSettingsViewController.m +++ b/Signal/src/ViewControllers/AppSettings/OWSSoundSettingsViewController.m @@ -28,9 +28,9 @@ NS_ASSUME_NONNULL_BEGIN [super viewDidLoad]; [self setTitle:NSLocalizedString(@"SETTINGS_ITEM_NOTIFICATION_SOUND", - @"Label for settings view that allows user to change the notification sound.")]; + @"Label for settings view that allows user to change the notification sound.")]; self.currentSound - = (self.thread ? [OWSSounds notificationSoundForThread:self.thread] : [OWSSounds globalNotificationSound]); + = (self.thread ? [OWSSounds notificationSoundForThread:self.thread] : [OWSSounds globalNotificationSound]); [self updateTableContents]; [self updateNavigationItems]; @@ -69,7 +69,7 @@ NS_ASSUME_NONNULL_BEGIN OWSTableSection *soundsSection = [OWSTableSection new]; soundsSection.headerTitle = NSLocalizedString( @"NOTIFICATIONS_SECTION_SOUNDS", @"Label for settings UI that allows user to change the notification sound."); - + NSArray *allSounds = [OWSSounds allNotificationSounds]; for (NSNumber *nsValue in allSounds) { OWSSound sound = (OWSSound)nsValue.intValue; diff --git a/Signal/src/ViewControllers/PrivacySettingsTableViewController.h b/Signal/src/ViewControllers/AppSettings/PrivacySettingsTableViewController.h similarity index 100% rename from Signal/src/ViewControllers/PrivacySettingsTableViewController.h rename to Signal/src/ViewControllers/AppSettings/PrivacySettingsTableViewController.h diff --git a/Signal/src/ViewControllers/PrivacySettingsTableViewController.m b/Signal/src/ViewControllers/AppSettings/PrivacySettingsTableViewController.m similarity index 98% rename from Signal/src/ViewControllers/PrivacySettingsTableViewController.m rename to Signal/src/ViewControllers/AppSettings/PrivacySettingsTableViewController.m index a9ebb6f94..c4f68e9ee 100644 --- a/Signal/src/ViewControllers/PrivacySettingsTableViewController.m +++ b/Signal/src/ViewControllers/AppSettings/PrivacySettingsTableViewController.m @@ -15,7 +15,8 @@ NS_ASSUME_NONNULL_BEGIN @implementation PrivacySettingsTableViewController -- (void)viewDidLoad { +- (void)viewDidLoad +{ [super viewDidLoad]; self.title = NSLocalizedString(@"SETTINGS_PRIVACY_TITLE", @""); @@ -231,7 +232,8 @@ NS_ASSUME_NONNULL_BEGIN [SignalApp.sharedApp.callService createCallUIAdapter]; } -- (void)didToggleEnableCallKitSwitch:(UISwitch *)sender { +- (void)didToggleEnableCallKitSwitch:(UISwitch *)sender +{ DDLogInfo(@"%@ user toggled call kit preference: %@", self.logTag, (sender.isOn ? @"ON" : @"OFF")); [[Environment current].preferences setIsCallKitEnabled:sender.isOn]; @@ -242,7 +244,8 @@ NS_ASSUME_NONNULL_BEGIN [self updateTableContents]; } -- (void)didToggleEnableCallKitPrivacySwitch:(UISwitch *)sender { +- (void)didToggleEnableCallKitPrivacySwitch:(UISwitch *)sender +{ DDLogInfo(@"%@ user toggled call kit privacy preference: %@", self.logTag, (sender.isOn ? @"ON" : @"OFF")); [[Environment current].preferences setIsCallKitPrivacyEnabled:!sender.isOn]; diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m index ef0330f6e..9946d632d 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m @@ -8,8 +8,6 @@ #import "ConversationViewItem.h" #import "NSAttributedString+OWS.h" #import "OWSAudioMessageView.h" -#import "OWSBackup.h" -#import "OWSBackupImportViewController.h" #import "OWSExpirationTimerView.h" #import "OWSGenericAttachmentView.h" #import "Signal-Swift.h" @@ -1321,16 +1319,7 @@ const CGFloat OWSMessageCellCornerRadius = 17; imageView:self.stillImageView]; return; case OWSMessageCellType_GenericAttachment: -#ifdef DEBUG - if ([self.attachmentStream.filePath.lastPathComponent hasSuffix:OWSBackup_FileExtension]) { - [self showBackupImportConfirmAlert:self.attachmentStream.filePath]; - } else { - [AttachmentSharing showShareUIForAttachment:self.attachmentStream]; - } -#else [AttachmentSharing showShareUIForAttachment:self.attachmentStream]; -#endif - break; case OWSMessageCellType_DownloadingAttachment: { OWSAssert(self.attachmentPointer); @@ -1342,42 +1331,6 @@ const CGFloat OWSMessageCellCornerRadius = 17; } } -- (void)showBackupImportConfirmAlert:(NSString *)backupZipPath -{ - OWSAssert(backupZipPath.length > 0); - - UIAlertController *controller = - [UIAlertController alertControllerWithTitle:NSLocalizedString(@"BACKUP_IMPORT_CONFIRM_ALERT_TITLE", - @"Title for alert confirming backup import.") - message:NSLocalizedString(@"BACKUP_IMPORT_CONFIRM_ALERT_MESSAGE", - @"Message for alert confirming backup import.") - preferredStyle:UIAlertControllerStyleAlert]; - - [controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"BACKUP_IMPORT_CONFIRM_ALERT_BUTTON", - @"Label for button confirming backup import.") - style:UIAlertActionStyleDefault - handler:^(UIAlertAction *_Nonnull action) { - [self showBackupImportUI:backupZipPath]; - }]]; - [controller addAction:OWSAlerts.cancelAction]; - - UIViewController *fromViewController = [[UIApplication sharedApplication] frontmostViewController]; - [fromViewController presentViewController:controller animated:YES completion:nil]; -} - -- (void)showBackupImportUI:(NSString *)backupZipPath -{ - OWSAssert(backupZipPath.length > 0); - - OWSBackupImportViewController *backupViewController = [OWSBackupImportViewController new]; - // There currently isn't any support for restoring password-protected backups. - [backupViewController importBackup:backupZipPath password:nil]; - UINavigationController *navigationController = - [[UINavigationController alloc] initWithRootViewController:backupViewController]; - UIViewController *fromViewController = [[UIApplication sharedApplication] frontmostViewController]; - [fromViewController presentViewController:navigationController animated:YES completion:nil]; -} - - (void)handleTextLongPressGesture:(UILongPressGestureRecognizer *)sender { OWSAssert(self.delegate); diff --git a/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m b/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m index 5eb39600b..4cd9b1511 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m @@ -4,7 +4,6 @@ #import "DebugUIMisc.h" #import "OWSBackup.h" -#import "OWSBackupExportViewController.h" #import "OWSCountryMetadata.h" #import "OWSTableViewController.h" #import "RegistrationViewController.h" @@ -96,15 +95,6 @@ NS_ASSUME_NONNULL_BEGIN [DebugUIMisc sendUnencryptedDatabase:thread]; }]]; } - [items addObject:[OWSTableItem subPageItemWithText:@"Export Backup w/o Password" - actionBlock:^(UIViewController *viewController) { - OWSBackupExportViewController *backupViewController = - [OWSBackupExportViewController new]; - [backupViewController exportBackup:thread skipPassword:YES]; - [viewController.navigationController - pushViewController:backupViewController - animated:YES]; - }]]; [items addObject:[OWSTableItem itemWithTitle:@"Show 2FA Reminder" actionBlock:^() { diff --git a/Signal/src/ViewControllers/OWSBackupExportViewController.h b/Signal/src/ViewControllers/OWSBackupExportViewController.h deleted file mode 100644 index ef5586dcd..000000000 --- a/Signal/src/ViewControllers/OWSBackupExportViewController.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class TSThread; - -@interface OWSBackupExportViewController : OWSViewController - -// If currentThread is non-nil, we should offer to let users send the -// backup in that thread. -- (void)exportBackup:(TSThread *_Nullable)currentThread skipPassword:(BOOL)skipPassword; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/OWSBackupExportViewController.m b/Signal/src/ViewControllers/OWSBackupExportViewController.m deleted file mode 100644 index bebd6165f..000000000 --- a/Signal/src/ViewControllers/OWSBackupExportViewController.m +++ /dev/null @@ -1,312 +0,0 @@ -// -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. -// - -#import "OWSBackupExportViewController.h" -#import "OWSBackup.h" -#import "OWSProgressView.h" -#import "Signal-Swift.h" -#import "ThreadUtil.h" -#import -#import -#import -#import -#import -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface OWSBackupExportViewController () - -@property (nonatomic) OWSBackup *backup; - -@property (nonatomic, nullable) OWSProgressView *progressView; - -@end - -#pragma mark - - -@implementation OWSBackupExportViewController - -- (void)loadView -{ - [super loadView]; - - self.view.backgroundColor = [UIColor whiteColor]; - - self.navigationItem.title = NSLocalizedString(@"BACKUP_EXPORT_VIEW_TITLE", @"Title for the 'backup export' view."); - self.navigationItem.leftBarButtonItem = - [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop - target:self - action:@selector(dismissWasPressed:)]; - - self.backup.delegate = self; - - [self updateUI]; -} - -- (void)exportBackup:(TSThread *_Nullable)currentThread skipPassword:(BOOL)skipPassword -{ - OWSAssertIsOnMainThread(); - - // We set ourselves as the delegate of the backup later, - // after we've loaded our view. - self.backup = [OWSBackup new]; - [self.backup exportBackup:currentThread skipPassword:skipPassword]; -} - -- (void)updateUI -{ - for (UIView *subview in self.view.subviews) { - [subview removeFromSuperview]; - } - self.progressView = nil; - - switch (self.backup.backupState) { - case OWSBackupState_InProgress: - [self showInProgressUI]; - break; - case OWSBackupState_Cancelled: - [self showCancelledUI]; - break; - case OWSBackupState_Complete: - [self showCompleteUI]; - break; - case OWSBackupState_Failed: - [self showFailedUI]; - break; - } -} - -- (void)showInProgressUI -{ - self.progressView = [OWSProgressView new]; - self.progressView.color = [UIColor ows_materialBlueColor]; - self.progressView.progress = self.backup.backupProgress; - [self.progressView autoSetDimension:ALDimensionWidth toSize:300]; - [self.progressView autoSetDimension:ALDimensionHeight toSize:20]; - - UILabel *label = [UILabel new]; - label.text = NSLocalizedString( - @"BACKUP_EXPORT_IN_PROGRESS_MESSAGE", @"Message indicating that backup export is in progress."); - label.textColor = [UIColor blackColor]; - label.font = [UIFont ows_regularFontWithSize:18.f]; - label.textAlignment = NSTextAlignmentCenter; - label.numberOfLines = 0; - label.lineBreakMode = NSLineBreakByWordWrapping; - - UIView *container = [UIView verticalStackWithSubviews:@[ - label, - self.progressView, - ] - spacing:10]; - [self.view addSubview:container]; - [container autoVCenterInSuperview]; - [container autoPinWidthToSuperviewWithMargin:25.f]; -} - -- (void)showCancelledUI -{ - // Show nothing. -} - -- (void)showCompleteUI -{ - NSMutableArray *subviews = [NSMutableArray new]; - - { - NSString *message = NSLocalizedString( - @"BACKUP_EXPORT_COMPLETE_MESSAGE", @"Message indicating that backup export is complete."); - - UILabel *label = [UILabel new]; - label.text = message; - label.textColor = [UIColor blackColor]; - label.font = [UIFont ows_regularFontWithSize:18.f]; - label.textAlignment = NSTextAlignmentCenter; - label.numberOfLines = 0; - label.lineBreakMode = NSLineBreakByWordWrapping; - [subviews addObject:label]; - } - - if (self.backup.backupPassword) { - NSString *message = [NSString stringWithFormat:NSLocalizedString(@"BACKUP_EXPORT_PASSWORD_MESSAGE_FORMAT", - @"Format for message indicating that backup export " - @"is complete. Embeds: {{the backup password}}."), - self.backup.backupPassword]; - - UILabel *label = [UILabel new]; - label.text = message; - label.textColor = [UIColor blackColor]; - label.font = [UIFont ows_regularFontWithSize:14.f]; - label.textAlignment = NSTextAlignmentCenter; - label.numberOfLines = 0; - label.lineBreakMode = NSLineBreakByWordWrapping; - [subviews addObject:label]; - } - - [subviews addObject:[UIView new]]; - - if (self.backup.backupPassword) { - [subviews - addObject:[self makeButtonWithTitle:NSLocalizedString(@"BACKUP_EXPORT_COPY_PASSWORD_BUTTON", - @"Label for button that copies backup password to the pasteboard.") - selector:@selector(copyPassword)]]; - } - - [subviews addObject:[self makeButtonWithTitle:NSLocalizedString(@"BACKUP_EXPORT_SHARE_BACKUP_BUTTON", - @"Label for button that opens share UI for backup.") - selector:@selector(shareBackup)]]; - - if (self.backup.currentThread) { - [subviews - addObject:[self makeButtonWithTitle:NSLocalizedString(@"BACKUP_EXPORT_SEND_BACKUP_BUTTON", - @"Label for button that 'send backup' in the current conversation.") - selector:@selector(sendBackup)]]; - } - - // TODO: We should offer the option to save the backup to "Files", iCloud, Dropbox, etc. - - UIView *container = [UIView verticalStackWithSubviews:subviews spacing:10]; - [self.view addSubview:container]; - [container autoVCenterInSuperview]; - [container autoPinWidthToSuperviewWithMargin:25.f]; -} - -- (void)showFailedUI -{ - NSMutableArray *subviews = [NSMutableArray new]; - - { - NSString *message - = NSLocalizedString(@"BACKUP_EXPORT_FAILED_MESSAGE", @"Message indicating that backup export failed."); - - UILabel *label = [UILabel new]; - label.text = message; - label.textColor = [UIColor blackColor]; - label.font = [UIFont ows_regularFontWithSize:18.f]; - label.textAlignment = NSTextAlignmentCenter; - label.numberOfLines = 0; - label.lineBreakMode = NSLineBreakByWordWrapping; - [subviews addObject:label]; - } - - // TODO: We should offer the option to save the backup to "Files", iCloud, Dropbox, etc. - - UIView *container = [UIView verticalStackWithSubviews:subviews spacing:10]; - [self.view addSubview:container]; - [container autoVCenterInSuperview]; - [container autoPinWidthToSuperviewWithMargin:25.f]; -} - -- (UIView *)makeButtonWithTitle:(NSString *)title selector:(SEL)selector -{ - const CGFloat kButtonHeight = 40; - OWSFlatButton *button = [OWSFlatButton buttonWithTitle:title - font:[OWSFlatButton fontForHeight:kButtonHeight] - titleColor:[UIColor whiteColor] - backgroundColor:[UIColor ows_materialBlueColor] - target:self - selector:selector]; - [button autoSetDimension:ALDimensionWidth toSize:140]; - [button autoSetDimension:ALDimensionHeight toSize:kButtonHeight]; - return button; -} - -- (void)copyPassword -{ - OWSAssert(self.backup.backupPassword.length > 0); - - // TODO: We could consider clearing the password from the pasteboard after a certain delay. - [UIPasteboard.generalPasteboard setString:self.backup.backupPassword]; -} - -- (void)shareBackup -{ - OWSAssertIsOnMainThread(); - OWSAssert(self.backup.backupZipPath.length > 0); - - [AttachmentSharing showShareUIForURL:[NSURL fileURLWithPath:self.backup.backupZipPath]]; -} - -- (void)sendBackup -{ - OWSAssertIsOnMainThread(); - OWSAssert(self.backup.backupZipPath.length > 0); - OWSAssert(self.backup.currentThread); - - [ModalActivityIndicatorViewController - presentFromViewController:self - canCancel:NO - backgroundBlock:^(ModalActivityIndicatorViewController *modalActivityIndicator) { - NSString *fileName = [self.backup.backupZipPath lastPathComponent]; - - OWSMessageSender *messageSender = [Environment current].messageSender; - NSString *utiType = [MIMETypeUtil utiTypeForFileExtension:fileName.pathExtension]; - DataSource *_Nullable dataSource = - [DataSourcePath dataSourceWithFilePath:self.backup.backupZipPath]; - [dataSource setSourceFilename:fileName]; - SignalAttachment *attachment = - [SignalAttachment attachmentWithDataSource:dataSource dataUTI:utiType]; - if (!attachment || [attachment hasError]) { - OWSFail(@"%@ attachment[%@]: %@", - self.logTag, - [attachment sourceFilename], - [attachment errorName]); - return; - } - dispatch_async(dispatch_get_main_queue(), ^{ - [ThreadUtil - sendMessageWithAttachment:attachment - inThread:self.backup.currentThread - messageSender:messageSender - completion:^(NSError *_Nullable error) { - - OWSAssertIsOnMainThread(); - [modalActivityIndicator dismissWithCompletion:^{ - if (error) { - DDLogError(@"%@ send backup failed: %@", self.logTag, error); - [OWSAlerts - showAlertWithTitle:NSLocalizedString( - @"BACKUP_EXPORT_SEND_BACKUP_FAILED", - @"Message indicating that sending " - @"the backup failed.")]; - } else { - [OWSAlerts - showAlertWithTitle: - NSLocalizedString(@"BACKUP_EXPORT_SEND_BACKUP_SUCCESS", - @"Message indicating that sending the backup " - @"succeeded.")]; - } - }]; - }]; - }); - }]; -} - -- (void)dismissWasPressed:(id)sender -{ - [self.backup cancel]; - - [self.navigationController popViewControllerAnimated:YES]; -} - -#pragma mark - OWSBackupDelegate - -- (void)backupStateDidChange -{ - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - [self updateUI]; -} - -- (void)backupProgressDidChange -{ - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - self.progressView.progress = self.backup.backupProgress; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/OWSBackupImportViewController.h b/Signal/src/ViewControllers/OWSBackupImportViewController.h deleted file mode 100644 index b62502c8f..000000000 --- a/Signal/src/ViewControllers/OWSBackupImportViewController.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class TSThread; - -@interface OWSBackupImportViewController : OWSViewController - -- (void)importBackup:(NSString *)backupZipPath password:(NSString *_Nullable)password; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/OWSBackupImportViewController.m b/Signal/src/ViewControllers/OWSBackupImportViewController.m deleted file mode 100644 index 992692c4d..000000000 --- a/Signal/src/ViewControllers/OWSBackupImportViewController.m +++ /dev/null @@ -1,217 +0,0 @@ -// -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. -// - -#import "OWSBackupImportViewController.h" -#import "OWSBackup.h" -#import "OWSProgressView.h" -#import "Signal-Swift.h" -#import "ThreadUtil.h" -#import -#import -#import -#import -#import -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface OWSBackupImportViewController () - -@property (nonatomic) OWSBackup *backup; - -@property (nonatomic, nullable) OWSProgressView *progressView; - -@end - -#pragma mark - - -@implementation OWSBackupImportViewController - -- (void)loadView -{ - [super loadView]; - - self.view.backgroundColor = [UIColor whiteColor]; - - self.navigationItem.title = NSLocalizedString(@"BACKUP_IMPORT_VIEW_TITLE", @"Title for the 'backup import' view."); - self.navigationItem.leftBarButtonItem = - [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop - target:self - action:@selector(dismissWasPressed:)]; - - self.backup.delegate = self; - - [self updateUI]; -} - -- (void)importBackup:(NSString *)backupZipPath password:(NSString *_Nullable)password -{ - OWSAssertIsOnMainThread(); - OWSAssert(backupZipPath.length > 0); - - // We set ourselves as the delegate of the backup later, - // after we've loaded our view. - self.backup = [OWSBackup new]; - [self.backup importBackup:backupZipPath password:password]; -} - -- (void)updateUI -{ - for (UIView *subview in self.view.subviews) { - [subview removeFromSuperview]; - } - self.progressView = nil; - - switch (self.backup.backupState) { - case OWSBackupState_InProgress: - [self showInProgressUI]; - break; - case OWSBackupState_Cancelled: - [self showCancelledUI]; - break; - case OWSBackupState_Complete: - [self showCompleteUI]; - break; - case OWSBackupState_Failed: - [self showFailedUI]; - break; - } -} - -- (void)showInProgressUI -{ - self.progressView = [OWSProgressView new]; - self.progressView.color = [UIColor ows_materialBlueColor]; - self.progressView.progress = self.backup.backupProgress; - [self.progressView autoSetDimension:ALDimensionWidth toSize:300]; - [self.progressView autoSetDimension:ALDimensionHeight toSize:20]; - - UILabel *label = [UILabel new]; - label.text = NSLocalizedString( - @"BACKUP_IMPORT_IN_PROGRESS_MESSAGE", @"Message indicating that backup import is in progress."); - label.textColor = [UIColor blackColor]; - label.font = [UIFont ows_regularFontWithSize:18.f]; - label.textAlignment = NSTextAlignmentCenter; - label.numberOfLines = 0; - label.lineBreakMode = NSLineBreakByWordWrapping; - - UIView *container = [UIView verticalStackWithSubviews:@[ - label, - self.progressView, - ] - spacing:10]; - [self.view addSubview:container]; - [container autoVCenterInSuperview]; - [container autoPinWidthToSuperviewWithMargin:25.f]; -} - -- (void)showCancelledUI -{ - // Show nothing. -} - -- (void)showCompleteUI -{ - NSMutableArray *subviews = [NSMutableArray new]; - - { - NSString *message = NSLocalizedString( - @"BACKUP_IMPORT_COMPLETE_MESSAGE", @"Message indicating that backup import is complete."); - - UILabel *label = [UILabel new]; - label.text = message; - label.textColor = [UIColor blackColor]; - label.font = [UIFont ows_regularFontWithSize:18.f]; - label.textAlignment = NSTextAlignmentCenter; - label.numberOfLines = 0; - label.lineBreakMode = NSLineBreakByWordWrapping; - [subviews addObject:label]; - } - - [subviews addObject:[UIView new]]; - - [subviews addObject:[self makeButtonWithTitle:NSLocalizedString(@"BACKUP_IMPORT_RESTART_BUTTON", - @"Label for button that restarts app to complete restore.") - selector:@selector(restartApp)]]; - - UIView *container = [UIView verticalStackWithSubviews:subviews spacing:10]; - [self.view addSubview:container]; - [container autoVCenterInSuperview]; - [container autoPinWidthToSuperviewWithMargin:25.f]; -} - -- (void)showFailedUI -{ - NSMutableArray *subviews = [NSMutableArray new]; - - { - NSString *message - = NSLocalizedString(@"BACKUP_IMPORT_FAILED_MESSAGE", @"Message indicating that backup import failed."); - - UILabel *label = [UILabel new]; - label.text = message; - label.textColor = [UIColor blackColor]; - label.font = [UIFont ows_regularFontWithSize:18.f]; - label.textAlignment = NSTextAlignmentCenter; - label.numberOfLines = 0; - label.lineBreakMode = NSLineBreakByWordWrapping; - [subviews addObject:label]; - } - - // TODO: We should offer the option to save the backup to "Files", iCloud, Dropbox, etc. - - UIView *container = [UIView verticalStackWithSubviews:subviews spacing:10]; - [self.view addSubview:container]; - [container autoVCenterInSuperview]; - [container autoPinWidthToSuperviewWithMargin:25.f]; -} - -- (UIView *)makeButtonWithTitle:(NSString *)title selector:(SEL)selector -{ - const CGFloat kButtonHeight = 40; - OWSFlatButton *button = [OWSFlatButton buttonWithTitle:title - font:[OWSFlatButton fontForHeight:kButtonHeight] - titleColor:[UIColor whiteColor] - backgroundColor:[UIColor ows_materialBlueColor] - target:self - selector:selector]; - [button autoSetDimension:ALDimensionWidth toSize:140]; - [button autoSetDimension:ALDimensionHeight toSize:kButtonHeight]; - return button; -} - -- (void)dismissWasPressed:(id)sender -{ - [self.backup cancel]; - - [self.navigationController dismissViewControllerAnimated:YES completion:nil]; -} - -- (void)restartApp -{ - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - OWSRaiseException(@"OWSBackup_RestartAppToCompleteBackupRestore", @"Killing app to complete backup restore"); -} - -#pragma mark - OWSBackupDelegate - -- (void)backupStateDidChange -{ - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - [self updateUI]; -} - -- (void)backupProgressDidChange -{ - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - self.progressView.progress = self.backup.backupProgress; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/CodeVerificationViewController.h b/Signal/src/ViewControllers/Registration/CodeVerificationViewController.h similarity index 100% rename from Signal/src/ViewControllers/CodeVerificationViewController.h rename to Signal/src/ViewControllers/Registration/CodeVerificationViewController.h diff --git a/Signal/src/ViewControllers/CodeVerificationViewController.m b/Signal/src/ViewControllers/Registration/CodeVerificationViewController.m similarity index 83% rename from Signal/src/ViewControllers/CodeVerificationViewController.m rename to Signal/src/ViewControllers/Registration/CodeVerificationViewController.m index adaacd8e1..1143b8edf 100644 --- a/Signal/src/ViewControllers/CodeVerificationViewController.m +++ b/Signal/src/ViewControllers/Registration/CodeVerificationViewController.m @@ -64,28 +64,32 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - View Lifecycle -- (void)viewDidLoad { +- (void)viewDidLoad +{ [super viewDidLoad]; [self createViews]; - + [self initializeKeyboardHandlers]; } -- (void)viewWillAppear:(BOOL)animated { +- (void)viewWillAppear:(BOOL)animated +{ [super viewWillAppear:animated]; [self enableServerActions:YES]; [self updatePhoneNumberLabel]; } -- (void)viewDidAppear:(BOOL)animated { +- (void)viewDidAppear:(BOOL)animated +{ [super viewDidAppear:animated]; [_challengeTextField becomeFirstResponder]; } -#pragma mark - +#pragma mark - -- (void)createViews { +- (void)createViews +{ self.view.backgroundColor = [UIColor whiteColor]; self.view.opaque = YES; @@ -109,16 +113,16 @@ NS_ASSUME_NONNULL_BEGIN [titleLabel autoHCenterInSuperview]; UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom]; - [backButton setTitle:NSLocalizedString(@"VERIFICATION_BACK_BUTTON", @"button text for back button on verification view") - forState:UIControlStateNormal]; - [backButton setTitleColor:[UIColor whiteColor] - forState:UIControlStateNormal]; + [backButton + setTitle:NSLocalizedString(@"VERIFICATION_BACK_BUTTON", @"button text for back button on verification view") + forState:UIControlStateNormal]; + [backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; backButton.titleLabel.font = [UIFont ows_mediumFontWithSize:14.f]; [header addSubview:backButton]; [backButton autoPinLeadingToSuperviewWithMargin:10.f]; [backButton autoAlignAxis:ALAxisHorizontal toSameAxisOfView:titleLabel]; [backButton addTarget:self action:@selector(backButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; - + _phoneNumberLabel = [UILabel new]; _phoneNumberLabel.textColor = [UIColor ows_darkGrayColor]; _phoneNumberLabel.font = [UIFont ows_regularFontWithSize:20.f]; @@ -133,25 +137,23 @@ NS_ASSUME_NONNULL_BEGIN withOffset:ScaleFromIPhone5To7Plus(30, 100)]; const CGFloat kHMargin = 36; - + _challengeTextField = [UITextField new]; _challengeTextField.textColor = [UIColor blackColor]; _challengeTextField.placeholder = NSLocalizedString(@"VERIFICATION_CHALLENGE_DEFAULT_TEXT", - @"Text field placeholder for SMS verification code during registration"); + @"Text field placeholder for SMS verification code during registration"); _challengeTextField.font = [UIFont ows_lightFontWithSize:21.f]; _challengeTextField.textAlignment = NSTextAlignmentCenter; _challengeTextField.keyboardType = UIKeyboardTypeNumberPad; - _challengeTextField.delegate = self; + _challengeTextField.delegate = self; [self.view addSubview:_challengeTextField]; [_challengeTextField autoPinWidthToSuperviewWithMargin:kHMargin]; - [_challengeTextField autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:_phoneNumberLabel - withOffset:25]; - + [_challengeTextField autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:_phoneNumberLabel withOffset:25]; + UIView *underscoreView = [UIView new]; underscoreView.backgroundColor = [UIColor colorWithWhite:0.5 alpha:1.f]; [self.view addSubview:underscoreView]; - [underscoreView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:_challengeTextField - withOffset:3]; + [underscoreView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:_challengeTextField withOffset:3]; [underscoreView autoPinWidthToSuperviewWithMargin:kHMargin]; [underscoreView autoSetDimension:ALDimensionHeight toSize:1.f]; @@ -175,7 +177,8 @@ NS_ASSUME_NONNULL_BEGIN const CGFloat kSpinnerSize = 20; const CGFloat kSpinnerSpacing = ScaleFromIPhone5To7Plus(5, 15); - _submitCodeSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; + _submitCodeSpinner = + [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; [_submitButton addSubview:_submitCodeSpinner]; [_submitCodeSpinner autoSetDimension:ALDimensionWidth toSize:kSpinnerSize]; [_submitCodeSpinner autoSetDimension:ALDimensionHeight toSize:kSpinnerSize]; @@ -184,10 +187,10 @@ NS_ASSUME_NONNULL_BEGIN _sendCodeViaSMSAgainButton = [UIButton buttonWithType:UIButtonTypeCustom]; _sendCodeViaSMSAgainButton.backgroundColor = [UIColor whiteColor]; - [_sendCodeViaSMSAgainButton setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_AGAIN", @"button text during registration to request another SMS code be sent") - forState:UIControlStateNormal]; - [_sendCodeViaSMSAgainButton setTitleColor:signalBlueColor - forState:UIControlStateNormal]; + [_sendCodeViaSMSAgainButton setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_AGAIN", + @"button text during registration to request another SMS code be sent") + forState:UIControlStateNormal]; + [_sendCodeViaSMSAgainButton setTitleColor:signalBlueColor forState:UIControlStateNormal]; _sendCodeViaSMSAgainButton.titleLabel.font = [UIFont ows_mediumFontWithSize:14.f]; [_sendCodeViaSMSAgainButton addTarget:self action:@selector(sendCodeViaSMSAction:) @@ -196,8 +199,9 @@ NS_ASSUME_NONNULL_BEGIN [_sendCodeViaSMSAgainButton autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:_submitButton withOffset:10]; [_sendCodeViaSMSAgainButton autoPinWidthToSuperviewWithMargin:kHMargin]; [_sendCodeViaSMSAgainButton autoSetDimension:ALDimensionHeight toSize:35]; - - _requestCodeAgainSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; + + _requestCodeAgainSpinner = + [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; [_sendCodeViaSMSAgainButton addSubview:_requestCodeAgainSpinner]; [_requestCodeAgainSpinner autoSetDimension:ALDimensionWidth toSize:kSpinnerSize]; [_requestCodeAgainSpinner autoSetDimension:ALDimensionHeight toSize:kSpinnerSize]; @@ -206,11 +210,11 @@ NS_ASSUME_NONNULL_BEGIN _sendCodeViaVoiceButton = [UIButton buttonWithType:UIButtonTypeCustom]; _sendCodeViaVoiceButton.backgroundColor = [UIColor whiteColor]; - [_sendCodeViaVoiceButton setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SEND_VIA_VOICE", - @"button text during registration to request phone number verification be done via phone call") - forState:UIControlStateNormal]; - [_sendCodeViaVoiceButton setTitleColor:signalBlueColor - forState:UIControlStateNormal]; + [_sendCodeViaVoiceButton + setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SEND_VIA_VOICE", + @"button text during registration to request phone number verification be done via phone call") + forState:UIControlStateNormal]; + [_sendCodeViaVoiceButton setTitleColor:signalBlueColor forState:UIControlStateNormal]; _sendCodeViaVoiceButton.titleLabel.font = [UIFont ows_mediumFontWithSize:14.f]; [_sendCodeViaVoiceButton addTarget:self action:@selector(sendCodeViaVoiceAction:) @@ -219,8 +223,9 @@ NS_ASSUME_NONNULL_BEGIN [_sendCodeViaVoiceButton autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:_sendCodeViaSMSAgainButton]; [_sendCodeViaVoiceButton autoPinWidthToSuperviewWithMargin:kHMargin]; [_sendCodeViaVoiceButton autoSetDimension:ALDimensionHeight toSize:35]; - - _requestCallSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; + + _requestCallSpinner = + [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; [_sendCodeViaVoiceButton addSubview:_requestCallSpinner]; [_requestCallSpinner autoSetDimension:ALDimensionWidth toSize:kSpinnerSize]; [_requestCallSpinner autoSetDimension:ALDimensionHeight toSize:kSpinnerSize]; @@ -316,13 +321,15 @@ NS_ASSUME_NONNULL_BEGIN [self presentViewController:alert animated:YES completion:nil]; } -- (NSString *)validationCodeFromTextField { +- (NSString *)validationCodeFromTextField +{ return [self.challengeTextField.text stringByReplacingOccurrencesOfString:@"-" withString:@""]; } #pragma mark - Actions -- (void)sendCodeViaSMSAction:(id)sender { +- (void)sendCodeViaSMSAction:(id)sender +{ OWSProdInfo([OWSAnalyticsEvents registrationRegisteringRequestedNewCodeBySms]); [self enableServerActions:NO]; @@ -343,7 +350,8 @@ NS_ASSUME_NONNULL_BEGIN }]; } -- (void)sendCodeViaVoiceAction:(id)sender { +- (void)sendCodeViaVoiceAction:(id)sender +{ OWSProdInfo([OWSAnalyticsEvents registrationRegisteringRequestedNewCodeByVoice]); [self enableServerActions:NO]; @@ -365,18 +373,21 @@ NS_ASSUME_NONNULL_BEGIN }]; } -- (void)showRegistrationErrorMessage:(NSError *)registrationError { +- (void)showRegistrationErrorMessage:(NSError *)registrationError +{ [OWSAlerts showAlertWithTitle:registrationError.localizedDescription message:registrationError.localizedRecoverySuggestion]; } -- (void)enableServerActions:(BOOL)enabled { +- (void)enableServerActions:(BOOL)enabled +{ [_submitButton setEnabled:enabled]; [_sendCodeViaSMSAgainButton setEnabled:enabled]; [_sendCodeViaVoiceButton setEnabled:enabled]; } -- (void)backButtonPressed:(id)sender { +- (void)backButtonPressed:(id)sender +{ OWSProdInfo([OWSAnalyticsEvents registrationVerificationBack]); [self.navigationController popViewControllerAnimated:YES]; @@ -384,20 +395,23 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Keyboard notifications -- (void)initializeKeyboardHandlers { +- (void)initializeKeyboardHandlers +{ UITapGestureRecognizer *outsideTabRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)]; [self.view addGestureRecognizer:outsideTabRecognizer]; self.view.userInteractionEnabled = YES; } -- (void)dismissKeyboardFromAppropriateSubView { +- (void)dismissKeyboardFromAppropriateSubView +{ [self.view endEditing:NO]; } - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range - replacementString:(NSString *)insertionText { + replacementString:(NSString *)insertionText +{ // Verification codes take this form: "123-456". // @@ -412,7 +426,7 @@ NS_ASSUME_NONNULL_BEGIN // * Always accept deletes. // * Ignore invalid input. // * Take partial input if possible. - + NSString *oldText = textField.text; // Construct the new contents of the text field by: // 1. Determining the "left" substring: the contents of the old text _before_ the deletion range. @@ -424,21 +438,18 @@ NS_ASSUME_NONNULL_BEGIN NSString *center = insertionText.digitsOnly; // 3a. Trim the tail of the "center" substring to ensure that we don't end up // with more than 6 decimal digits. - while (center.length > 0 && - left.length + center.length + right.length > 6) { + while (center.length > 0 && left.length + center.length + right.length > 6) { center = [center substringToIndex:center.length - 1]; } // 4. Construct the "raw" new text by concatenating left, center and right. - NSString *rawNewText = [[left stringByAppendingString:center] - stringByAppendingString:right]; + NSString *rawNewText = [[left stringByAppendingString:center] stringByAppendingString:right]; // 5. Construct the "formatted" new text by inserting a hyphen if necessary. - NSString *formattedNewText = (rawNewText.length <= 3 - ? rawNewText - : [[[rawNewText substringToIndex:3] - stringByAppendingString:@"-"] - stringByAppendingString:[rawNewText substringFromIndex:3]]); + NSString *formattedNewText + = (rawNewText.length <= 3 ? rawNewText + : [[[rawNewText substringToIndex:3] stringByAppendingString:@"-"] + stringByAppendingString:[rawNewText substringFromIndex:3]]); textField.text = formattedNewText; - + // Move the cursor after the newly inserted text. NSUInteger newInsertionPoint = left.length + center.length; if (newInsertionPoint > 3) { @@ -446,32 +457,32 @@ NS_ASSUME_NONNULL_BEGIN // if necessary. newInsertionPoint++; } - UITextPosition *newPosition = [textField positionFromPosition:textField.beginningOfDocument - offset:(NSInteger) newInsertionPoint]; - textField.selectedTextRange = [textField textRangeFromPosition:newPosition - toPosition:newPosition]; - + UITextPosition *newPosition = + [textField positionFromPosition:textField.beginningOfDocument offset:(NSInteger)newInsertionPoint]; + textField.selectedTextRange = [textField textRangeFromPosition:newPosition toPosition:newPosition]; + return NO; } -- (BOOL)textFieldShouldReturn:(UITextField *)textField { +- (BOOL)textFieldShouldReturn:(UITextField *)textField +{ [self submitVerificationCode]; [textField resignFirstResponder]; return NO; } -- (void)setVerificationCodeAndTryToVerify:(NSString *)verificationCode { +- (void)setVerificationCodeAndTryToVerify:(NSString *)verificationCode +{ NSString *rawNewText = verificationCode.digitsOnly; - NSString *formattedNewText = (rawNewText.length <= 3 - ? rawNewText - : [[[rawNewText substringToIndex:3] - stringByAppendingString:@"-"] - stringByAppendingString:[rawNewText substringFromIndex:3]]); + NSString *formattedNewText + = (rawNewText.length <= 3 ? rawNewText + : [[[rawNewText substringToIndex:3] stringByAppendingString:@"-"] + stringByAppendingString:[rawNewText substringFromIndex:3]]); self.challengeTextField.text = formattedNewText; // Move the cursor after the newly inserted text. UITextPosition *newPosition = [self.challengeTextField endOfDocument]; - self.challengeTextField.selectedTextRange = [self.challengeTextField textRangeFromPosition:newPosition - toPosition:newPosition]; + self.challengeTextField.selectedTextRange = + [self.challengeTextField textRangeFromPosition:newPosition toPosition:newPosition]; [self submitVerificationCode]; } diff --git a/Signal/src/ViewControllers/RegistrationViewController.h b/Signal/src/ViewControllers/Registration/RegistrationViewController.h similarity index 100% rename from Signal/src/ViewControllers/RegistrationViewController.h rename to Signal/src/ViewControllers/Registration/RegistrationViewController.h diff --git a/Signal/src/ViewControllers/RegistrationViewController.m b/Signal/src/ViewControllers/Registration/RegistrationViewController.m similarity index 96% rename from Signal/src/ViewControllers/RegistrationViewController.m rename to Signal/src/ViewControllers/Registration/RegistrationViewController.m index 69b2b310f..5ba1ee687 100644 --- a/Signal/src/ViewControllers/RegistrationViewController.m +++ b/Signal/src/ViewControllers/Registration/RegistrationViewController.m @@ -53,7 +53,8 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi [SignalApp.sharedApp setSignUpFlowNavigationController:self.navigationController]; } -- (void)viewDidLoad { +- (void)viewDidLoad +{ [super viewDidLoad]; OWSProdInfo([OWSAnalyticsEvents registrationBegan]); @@ -69,7 +70,7 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi UIView *headerWrapper = [UIView containerView]; [self.view addSubview:headerWrapper]; headerWrapper.backgroundColor = UIColor.ows_signalBrandBlueColor; - + UIView *headerContent = [UIView new]; [headerWrapper addSubview:headerContent]; [headerWrapper autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero excludingEdge:ALEdgeBottom]; @@ -230,7 +231,8 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi [spinnerView stopAnimating]; } -- (void)viewDidAppear:(BOOL)animated { +- (void)viewDidAppear:(BOOL)animated +{ [super viewDidAppear:animated]; [self.activateButton setEnabled:YES]; @@ -240,7 +242,8 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi #pragma mark - Country -- (void)populateDefaultCountryNameAndCode { +- (void)populateDefaultCountryNameAndCode +{ NSString *countryCode = [PhoneNumber defaultCountryCode]; #ifdef DEBUG @@ -253,15 +256,14 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi NSNumber *callingCode = [[PhoneNumberUtil sharedUtil].nbPhoneNumberUtil getCountryCodeForRegion:countryCode]; NSString *countryName = [PhoneNumberUtil countryNameFromCountryCode:countryCode]; [self updateCountryWithName:countryName - callingCode:[NSString stringWithFormat:@"%@%@", - COUNTRY_CODE_PREFIX, - callingCode] + callingCode:[NSString stringWithFormat:@"%@%@", COUNTRY_CODE_PREFIX, callingCode] countryCode:countryCode]; } - (void)updateCountryWithName:(NSString *)countryName callingCode:(NSString *)callingCode - countryCode:(NSString *)countryCode { + countryCode:(NSString *)countryCode +{ OWSAssertIsOnMainThread(); OWSAssert(countryName.length > 0); OWSAssert(callingCode.length > 0); @@ -270,9 +272,7 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi _countryCode = countryCode; _callingCode = callingCode; - NSString *title = [NSString stringWithFormat:@"%@ (%@)", - callingCode, - countryCode.uppercaseString]; + NSString *title = [NSString stringWithFormat:@"%@ (%@)", callingCode, countryCode.uppercaseString]; self.countryCodeLabel.text = title; [self.countryCodeLabel setNeedsLayout]; @@ -385,13 +385,15 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi #pragma mark - Keyboard notifications -- (void)initializeKeyboardHandlers { +- (void)initializeKeyboardHandlers +{ UITapGestureRecognizer *outsideTabRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)]; [self.view addGestureRecognizer:outsideTabRecognizer]; } -- (void)dismissKeyboardFromAppropriateSubView { +- (void)dismissKeyboardFromAppropriateSubView +{ [self.view endEditing:NO]; } @@ -399,7 +401,8 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range - replacementString:(NSString *)insertionText { + replacementString:(NSString *)insertionText +{ [ViewControllerUtils phoneNumberTextField:textField shouldChangeCharactersInRange:range @@ -409,7 +412,8 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi return NO; // inform our caller that we took care of performing the change } -- (BOOL)textFieldShouldReturn:(UITextField *)textField { +- (BOOL)textFieldShouldReturn:(UITextField *)textField +{ [self sendCodeAction]; [textField resignFirstResponder]; return NO; diff --git a/Signal/src/ViewControllers/AddToGroupViewController.h b/Signal/src/ViewControllers/ThreadSettings/AddToGroupViewController.h similarity index 88% rename from Signal/src/ViewControllers/AddToGroupViewController.h rename to Signal/src/ViewControllers/ThreadSettings/AddToGroupViewController.h index 071318d67..dae373b41 100644 --- a/Signal/src/ViewControllers/AddToGroupViewController.h +++ b/Signal/src/ViewControllers/ThreadSettings/AddToGroupViewController.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "SelectRecipientViewController.h" diff --git a/Signal/src/ViewControllers/AddToGroupViewController.m b/Signal/src/ViewControllers/ThreadSettings/AddToGroupViewController.m similarity index 98% rename from Signal/src/ViewControllers/AddToGroupViewController.m rename to Signal/src/ViewControllers/ThreadSettings/AddToGroupViewController.m index 6c164ab1c..0c4052708 100644 --- a/Signal/src/ViewControllers/AddToGroupViewController.m +++ b/Signal/src/ViewControllers/ThreadSettings/AddToGroupViewController.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "AddToGroupViewController.h" diff --git a/Signal/src/ViewControllers/FingerprintViewController.h b/Signal/src/ViewControllers/ThreadSettings/FingerprintViewController.h similarity index 100% rename from Signal/src/ViewControllers/FingerprintViewController.h rename to Signal/src/ViewControllers/ThreadSettings/FingerprintViewController.h diff --git a/Signal/src/ViewControllers/FingerprintViewController.m b/Signal/src/ViewControllers/ThreadSettings/FingerprintViewController.m similarity index 92% rename from Signal/src/ViewControllers/FingerprintViewController.m rename to Signal/src/ViewControllers/ThreadSettings/FingerprintViewController.m index a5f9c961e..e33a6362a 100644 --- a/Signal/src/ViewControllers/FingerprintViewController.m +++ b/Signal/src/ViewControllers/ThreadSettings/FingerprintViewController.m @@ -263,13 +263,19 @@ typedef void (^CustomLayoutBlock)(void); fingerprintLabel.userInteractionEnabled = YES; [self.view addSubview:fingerprintLabel]; [fingerprintLabel autoPinWidthToSuperviewWithMargin:ScaleFromIPhone5To7Plus(50.f, 60.f)]; - [fingerprintLabel autoPinEdge:ALEdgeBottom toEdge:ALEdgeTop ofView:instructionsLabel withOffset:-ScaleFromIPhone5To7Plus(8.f, 15.f)]; + [fingerprintLabel autoPinEdge:ALEdgeBottom + toEdge:ALEdgeTop + ofView:instructionsLabel + withOffset:-ScaleFromIPhone5To7Plus(8.f, 15.f)]; // Fingerprint Image CustomLayoutView *fingerprintView = [CustomLayoutView new]; [self.view addSubview:fingerprintView]; [fingerprintView autoPinWidthToSuperview]; - [fingerprintView autoPinEdge:ALEdgeBottom toEdge:ALEdgeTop ofView:fingerprintLabel withOffset:-ScaleFromIPhone5To7Plus(10.f, 15.f)]; + [fingerprintView autoPinEdge:ALEdgeBottom + toEdge:ALEdgeTop + ofView:fingerprintLabel + withOffset:-ScaleFromIPhone5To7Plus(10.f, 15.f)]; [fingerprintView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(fingerprintViewTapped:)]]; @@ -406,14 +412,18 @@ typedef void (^CustomLayoutBlock)(void); OWSCompareSafetyNumbersActivity *compareActivity = [[OWSCompareSafetyNumbersActivity alloc] initWithDelegate:self]; - NSString *shareFormat = NSLocalizedString(@"SAFETY_NUMBER_SHARE_FORMAT", @"Snippet to share {{safety number}} with a friend. sent e.g. via SMS"); + NSString *shareFormat = NSLocalizedString( + @"SAFETY_NUMBER_SHARE_FORMAT", @"Snippet to share {{safety number}} with a friend. sent e.g. via SMS"); NSString *shareString = [NSString stringWithFormat:shareFormat, self.fingerprint.displayableText]; UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:@[ shareString ] applicationActivities:@[ compareActivity ]]; - activityController.completionWithItemsHandler = ^void(UIActivityType __nullable activityType, BOOL completed, NSArray * __nullable returnedItems, NSError * __nullable activityError){ + activityController.completionWithItemsHandler = ^void(UIActivityType __nullable activityType, + BOOL completed, + NSArray *__nullable returnedItems, + NSError *__nullable activityError) { if (completionHandler) { completionHandler(); } @@ -512,20 +522,20 @@ typedef void (^CustomLayoutBlock)(void); - (void)verifyUnverifyButtonTapped:(UIGestureRecognizer *)gestureRecognizer { if (gestureRecognizer.state == UIGestureRecognizerStateRecognized) { - [OWSPrimaryStorage.sharedManager.newDatabaseConnection readWriteWithBlock:^( - YapDatabaseReadWriteTransaction *transaction) { - BOOL isVerified = [[OWSIdentityManager sharedManager] verificationStateForRecipientId:self.recipientId - transaction:transaction] - == OWSVerificationStateVerified; + [OWSPrimaryStorage.sharedManager.newDatabaseConnection + readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + BOOL isVerified = [[OWSIdentityManager sharedManager] verificationStateForRecipientId:self.recipientId + transaction:transaction] + == OWSVerificationStateVerified; - OWSVerificationState newVerificationState - = (isVerified ? OWSVerificationStateDefault : OWSVerificationStateVerified); - [[OWSIdentityManager sharedManager] setVerificationState:newVerificationState - identityKey:self.identityKey - recipientId:self.recipientId - isUserInitiatedChange:YES - transaction:transaction]; - }]; + OWSVerificationState newVerificationState + = (isVerified ? OWSVerificationStateDefault : OWSVerificationStateVerified); + [[OWSIdentityManager sharedManager] setVerificationState:newVerificationState + identityKey:self.identityKey + recipientId:self.recipientId + isUserInitiatedChange:YES + transaction:transaction]; + }]; [self dismissViewControllerAnimated:YES completion:nil]; } diff --git a/Signal/src/ViewControllers/FingerprintViewScanController.h b/Signal/src/ViewControllers/ThreadSettings/FingerprintViewScanController.h similarity index 100% rename from Signal/src/ViewControllers/FingerprintViewScanController.h rename to Signal/src/ViewControllers/ThreadSettings/FingerprintViewScanController.h diff --git a/Signal/src/ViewControllers/FingerprintViewScanController.m b/Signal/src/ViewControllers/ThreadSettings/FingerprintViewScanController.m similarity index 100% rename from Signal/src/ViewControllers/FingerprintViewScanController.m rename to Signal/src/ViewControllers/ThreadSettings/FingerprintViewScanController.m diff --git a/Signal/src/ViewControllers/OWSAddToContactViewController.h b/Signal/src/ViewControllers/ThreadSettings/OWSAddToContactViewController.h similarity index 77% rename from Signal/src/ViewControllers/OWSAddToContactViewController.h rename to Signal/src/ViewControllers/ThreadSettings/OWSAddToContactViewController.h index 505dc4317..80d652900 100644 --- a/Signal/src/ViewControllers/OWSAddToContactViewController.h +++ b/Signal/src/ViewControllers/ThreadSettings/OWSAddToContactViewController.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSTableViewController.h" diff --git a/Signal/src/ViewControllers/OWSAddToContactViewController.m b/Signal/src/ViewControllers/ThreadSettings/OWSAddToContactViewController.m similarity index 98% rename from Signal/src/ViewControllers/OWSAddToContactViewController.m rename to Signal/src/ViewControllers/ThreadSettings/OWSAddToContactViewController.m index 783cd0bb4..5f86d391d 100644 --- a/Signal/src/ViewControllers/OWSAddToContactViewController.m +++ b/Signal/src/ViewControllers/ThreadSettings/OWSAddToContactViewController.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSAddToContactViewController.h" diff --git a/Signal/src/ViewControllers/OWSConversationSettingsViewController.h b/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.h similarity index 87% rename from Signal/src/ViewControllers/OWSConversationSettingsViewController.h rename to Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.h index 0ac0bb5fe..85f0e507f 100644 --- a/Signal/src/ViewControllers/OWSConversationSettingsViewController.h +++ b/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSConversationSettingsViewDelegate.h" diff --git a/Signal/src/ViewControllers/OWSConversationSettingsViewController.m b/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.m similarity index 100% rename from Signal/src/ViewControllers/OWSConversationSettingsViewController.m rename to Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.m diff --git a/Signal/src/ViewControllers/OWSConversationSettingsViewDelegate.h b/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewDelegate.h similarity index 78% rename from Signal/src/ViewControllers/OWSConversationSettingsViewDelegate.h rename to Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewDelegate.h index 98dd67b11..6cfccb721 100644 --- a/Signal/src/ViewControllers/OWSConversationSettingsViewDelegate.h +++ b/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewDelegate.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // NS_ASSUME_NONNULL_BEGIN diff --git a/Signal/src/ViewControllers/ShowGroupMembersViewController.h b/Signal/src/ViewControllers/ThreadSettings/ShowGroupMembersViewController.h similarity index 75% rename from Signal/src/ViewControllers/ShowGroupMembersViewController.h rename to Signal/src/ViewControllers/ThreadSettings/ShowGroupMembersViewController.h index ec76e12f4..de4c64267 100644 --- a/Signal/src/ViewControllers/ShowGroupMembersViewController.h +++ b/Signal/src/ViewControllers/ThreadSettings/ShowGroupMembersViewController.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSTableViewController.h" diff --git a/Signal/src/ViewControllers/ShowGroupMembersViewController.m b/Signal/src/ViewControllers/ThreadSettings/ShowGroupMembersViewController.m similarity index 97% rename from Signal/src/ViewControllers/ShowGroupMembersViewController.m rename to Signal/src/ViewControllers/ThreadSettings/ShowGroupMembersViewController.m index a4dcb74f1..66c8addec 100644 --- a/Signal/src/ViewControllers/ShowGroupMembersViewController.m +++ b/Signal/src/ViewControllers/ThreadSettings/ShowGroupMembersViewController.m @@ -93,7 +93,8 @@ NS_ASSUME_NONNULL_BEGIN self.memberRecipientIds = [NSSet setWithArray:self.thread.groupModel.groupMemberIds]; } -- (void)viewDidLoad { +- (void)viewDidLoad +{ [super viewDidLoad]; OWSAssert([self.navigationController isKindOfClass:[OWSNavigationController class]]); @@ -225,12 +226,11 @@ NS_ASSUME_NONNULL_BEGIN preferredStyle:UIAlertControllerStyleAlert]; __weak ShowGroupMembersViewController *weakSelf = self; - UIAlertAction *verifyAction = [UIAlertAction - actionWithTitle:NSLocalizedString(@"OK", nil) - style:UIAlertActionStyleDestructive - handler:^(UIAlertAction *_Nonnull action) { - [weakSelf resetAllNoLongerVerified]; - }]; + UIAlertAction *verifyAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) + style:UIAlertActionStyleDestructive + handler:^(UIAlertAction *_Nonnull action) { + [weakSelf resetAllNoLongerVerified]; + }]; [actionSheetController addAction:verifyAction]; [actionSheetController addAction:[OWSAlerts cancelAction]]; diff --git a/Signal/src/ViewControllers/UpdateGroupViewController.h b/Signal/src/ViewControllers/ThreadSettings/UpdateGroupViewController.h similarity index 100% rename from Signal/src/ViewControllers/UpdateGroupViewController.h rename to Signal/src/ViewControllers/ThreadSettings/UpdateGroupViewController.h diff --git a/Signal/src/ViewControllers/UpdateGroupViewController.m b/Signal/src/ViewControllers/ThreadSettings/UpdateGroupViewController.m similarity index 100% rename from Signal/src/ViewControllers/UpdateGroupViewController.m rename to Signal/src/ViewControllers/ThreadSettings/UpdateGroupViewController.m diff --git a/Signal/src/util/OWSBackup.h b/Signal/src/util/OWSBackup.h index 48574c770..e516be3fe 100644 --- a/Signal/src/util/OWSBackup.h +++ b/Signal/src/util/OWSBackup.h @@ -4,71 +4,55 @@ NS_ASSUME_NONNULL_BEGIN -extern NSString *const OWSBackup_FileExtension; +// extern NSString *const OWSBackup_FileExtension; -@protocol OWSBackupDelegate +extern NSString *const NSNotificationNameBackupStateDidChange; -- (void)backupStateDidChange; - -- (void)backupProgressDidChange; - -@end - -#pragma mark - +//@protocol OWSBackupDelegate +// +//- (void)backupStateDidChange; +// +//- (void)backupProgressDidChange; +// +//@end +// +//#pragma mark - typedef NS_ENUM(NSUInteger, OWSBackupState) { + OWSBackupState_AtRest = 0, OWSBackupState_InProgress, - OWSBackupState_Cancelled, - OWSBackupState_Complete, + // OWSBackupState_Cancelled, OWSBackupState_Failed, }; @class TSThread; -// We restore backups as part of the app launch process. -// -// applicationDidFinishLaunching must complete quickly even for -// large backups, to prevent the app from being killed on launch. -// Therefore, we break up backup import/restoration into two parts: -// -// * Preparation (which includes the costly decryption/unzip of the -// backup file) -// * Completion (file moves, NSUserDefaults writes, keychain writes). -// -// To protect data during backup and restore, we: -// -// * Optionally encrypt backup files with a password. -// * Separately encrypt files containing keychain & NSUserDefaults data. -// * Delete data from disk ASAP. @interface OWSBackup : NSObject -@property (nonatomic, weak) id delegate; +@property (nonatomic, readonly) OWSBackupState backupExportState; -// An instance of `OWSBackup` is used for three separate tasks: +//@property (nonatomic, readonly) CGFloat backupProgress; // -// * Backup export -// * Backup import preparation -// * Backup import completion +//// If non-nil, backup is encrypted. +//@property (nonatomic, nullable, readonly) NSString *backupPassword; +// +//// Only applies to "backup export" task. +//@property (nonatomic, nullable, readonly) TSThread *currentThread; +// +//@property (nonatomic, readonly) NSString *backupZipPath; // -// The "backup state" and "progress" apply to all three tasks. -@property (nonatomic, readonly) OWSBackupState backupState; -@property (nonatomic, readonly) CGFloat backupProgress; -// If non-nil, backup is encrypted. -@property (nonatomic, nullable, readonly) NSString *backupPassword; +- (instancetype)init NS_UNAVAILABLE; -// Only applies to "backup export" task. -@property (nonatomic, nullable, readonly) TSThread *currentThread; ++ (instancetype)sharedManager; -@property (nonatomic, readonly) NSString *backupZipPath; - -- (void)exportBackup:(nullable TSThread *)currentThread skipPassword:(BOOL)skipPassword; - -- (void)importBackup:(NSString *)backupZipPath password:(NSString *_Nullable)password; - -- (void)cancel; - -+ (void)applicationDidFinishLaunching; +//- (void)exportBackup:(nullable TSThread *)currentThread skipPassword:(BOOL)skipPassword; +// +//- (void)importBackup:(NSString *)backupZipPath password:(NSString *_Nullable)password; +// +//- (void)cancel; +// +//+ (void)applicationDidFinishLaunching; @end diff --git a/Signal/src/util/OWSBackup.m b/Signal/src/util/OWSBackup.m index 3c461966f..73688f4c6 100644 --- a/Signal/src/util/OWSBackup.m +++ b/Signal/src/util/OWSBackup.m @@ -3,42 +3,50 @@ // #import "OWSBackup.h" -#import "NSUserDefaults+OWS.h" -#import "Signal-Swift.h" + +//#import "NSUserDefaults+OWS.h" +//#import "Signal-Swift.h" #import "zlib.h" -#import + +//#import #import -#import -#import + +//#import +//#import #import -#import + +//#import +#import "NSNotificationCenter+OWS.h" +#import + +NSString *const NSNotificationNameBackupStateDidChange = @"NSNotificationNameBackupStateDidChange"; NS_ASSUME_NONNULL_BEGIN -// Hide the "import" directories from exports, etc. by prefixing their name with a period. +//// Hide the "import" directories from exports, etc. by prefixing their name with a period. +//// +//// OWSBackup backs up files and directories in the "app documents" and "shared data container", +//// but ignores any top-level files or directories in those locations whose names start with a +//// period ".". +// NSString *const OWSBackup_DirNamePrefix = @".SignalBackup."; +// NSString *const OWSBackup_FileExtension = @".signalbackup"; +// NSString *const OWSBackup_EncryptionKeyFilename = @".encryptionKey"; +// NSString *const OWSBackup_DatabasePasswordFilename = @".databasePassword"; +// NSString *const OWSBackup_StandardUserDefaultsFilename = @".standardUserDefaults"; +// NSString *const OWSBackup_AppUserDefaultsFilename = @".appUserDefaults"; +// NSString *const OWSBackup_AppDocumentDirName = @"appDocumentDirectoryPath"; +// NSString *const OWSBackup_AppSharedDataDirName = @"appSharedDataDirectoryPath"; // -// OWSBackup backs up files and directories in the "app documents" and "shared data container", -// but ignores any top-level files or directories in those locations whose names start with a -// period ".". -NSString *const OWSBackup_DirNamePrefix = @".SignalBackup."; -NSString *const OWSBackup_FileExtension = @".signalbackup"; -NSString *const OWSBackup_EncryptionKeyFilename = @".encryptionKey"; -NSString *const OWSBackup_DatabasePasswordFilename = @".databasePassword"; -NSString *const OWSBackup_StandardUserDefaultsFilename = @".standardUserDefaults"; -NSString *const OWSBackup_AppUserDefaultsFilename = @".appUserDefaults"; -NSString *const OWSBackup_AppDocumentDirName = @"appDocumentDirectoryPath"; -NSString *const OWSBackup_AppSharedDataDirName = @"appSharedDataDirectoryPath"; - -NSString *const NSUserDefaults_QueuedBackupPath = @"NSUserDefaults_QueuedBackupPath"; - -NSString *const Keychain_ImportBackupService = @"OWSKeychainService"; -NSString *const Keychain_ImportBackupKey = @"ImportBackupKey"; +// NSString *const NSUserDefaults_QueuedBackupPath = @"NSUserDefaults_QueuedBackupPath"; +// +// NSString *const Keychain_ImportBackupService = @"OWSKeychainService"; +// NSString *const Keychain_ImportBackupKey = @"ImportBackupKey"; @interface OWSStorage (OWSBackup) -- (NSData *)databasePassword; - -+ (void)storeDatabasePassword:(NSString *)password; +//- (NSData *)databasePassword; +// +//+ (void)storeDatabasePassword:(NSString *)password; @end @@ -46,18 +54,18 @@ NSString *const Keychain_ImportBackupKey = @"ImportBackupKey"; @interface OWSBackup () -@property (nonatomic) OWSBackupState backupState; - -@property (nonatomic) CGFloat backupProgress; - -@property (nonatomic, nullable) TSThread *currentThread; - -@property (nonatomic, nullable) NSString *backupPassword; - -@property (nonatomic) NSString *backupDirPath; -@property (nonatomic) NSString *backupZipPath; - -@property (nonatomic) OWSAES256Key *encryptionKey; +//@property (nonatomic) OWSBackupState backupState; +// +//@property (nonatomic) CGFloat backupProgress; +// +//@property (nonatomic, nullable) TSThread *currentThread; +// +//@property (nonatomic, nullable) NSString *backupPassword; +// +//@property (nonatomic) NSString *backupDirPath; +//@property (nonatomic) NSString *backupZipPath; +// +//@property (nonatomic) OWSAES256Key *encryptionKey; @end @@ -65,903 +73,958 @@ NSString *const Keychain_ImportBackupKey = @"ImportBackupKey"; @implementation OWSBackup ++ (instancetype)sharedManager +{ + static OWSBackup *sharedMyManager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedMyManager = [[self alloc] initDefault]; + }); + return sharedMyManager; +} + +- (instancetype)initDefault +{ + // OWSPrimaryStorage *primaryStorage = [OWSPrimaryStorage sharedManager]; + // OWSMessageSender *messageSender = [TextSecureKitEnv sharedEnv].messageSender; + // + // return [self initWithPrimaryStorage:primaryStorage messageSender:messageSender]; + //} + // + //- (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage + // messageSender:(OWSMessageSender *)messageSender + //{ + self = [super init]; + + if (!self) { + return self; + } + + // OWSAssert(primaryStorage); + // OWSAssert(messageSender); + // + // _dbConnection = primaryStorage.newDatabaseConnection; + // _messageSender = messageSender; + + _backupExportState = OWSBackupState_AtRest; + + OWSSingletonAssert(); + + return self; +} + - (void)dealloc { - DDLogInfo(@"%@ Cleaning up: %@", self.logTag, self.backupDirPath); - [OWSFileSystem deleteFileIfExists:self.backupDirPath]; - - dispatch_async(dispatch_get_main_queue(), ^{ - [OWSBackup cleanupBackupState]; - }); + [[NSNotificationCenter defaultCenter] removeObserver:self]; } -- (void)setBackupState:(OWSBackupState)backupState +//- (void)observeNotifications +//{ +// [[NSNotificationCenter defaultCenter] addObserver:self +// selector:@selector(applicationDidBecomeActive:) +// name:OWSApplicationDidBecomeActiveNotification +// object:nil]; +//} + +//- (void)dealloc +//{ +// DDLogInfo(@"%@ Cleaning up: %@", self.logTag, self.backupDirPath); +// [OWSFileSystem deleteFileIfExists:self.backupDirPath]; +// +// dispatch_async(dispatch_get_main_queue(), ^{ +// [OWSBackup cleanupBackupState]; +// }); +//} + +- (void)setBackupExportState:(OWSBackupState)backupExportState { - _backupState = backupState; + _backupExportState = backupExportState; - dispatch_async(dispatch_get_main_queue(), ^{ - [self.delegate backupStateDidChange]; - }); + [[NSNotificationCenter defaultCenter] postNotificationNameAsync:NSNotificationNameBackupStateDidChange + object:nil + userInfo:nil]; } -- (void)setBackupProgress:(CGFloat)backupProgress -{ - _backupProgress = backupProgress; - - dispatch_async(dispatch_get_main_queue(), ^{ - [self.delegate backupProgressDidChange]; - }); -} - -- (void)fail -{ - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - if (!self.isCancelledOrFailed) { - self.backupState = OWSBackupState_Failed; - } - - dispatch_async(dispatch_get_main_queue(), ^{ - [OWSBackup cleanupBackupState]; - }); -} - -- (void)cancel -{ - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - if (!self.isCancelledOrFailed) { - self.backupState = OWSBackupState_Cancelled; - } - - dispatch_async(dispatch_get_main_queue(), ^{ - [OWSBackup cleanupBackupState]; - }); -} - -- (void)complete -{ - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - if (!self.isCancelledOrFailed) { - self.backupState = OWSBackupState_Complete; - } -} - -- (BOOL)isCancelledOrFailed -{ - return (self.backupState == OWSBackupState_Cancelled || self.backupState == OWSBackupState_Failed); -} - -#pragma mark - Export Backup - -- (void)exportBackup:(nullable TSThread *)currentThread skipPassword:(BOOL)skipPassword -{ - OWSAssertIsOnMainThread(); - OWSAssert(CurrentAppContext().isMainApp); - - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - self.currentThread = currentThread; - self.backupState = OWSBackupState_InProgress; - - if (skipPassword) { - DDLogInfo(@"%@ backup export without password", self.logTag); - } else { - // TODO: Should the user pick a password? - // If not, should probably generate something more user-friendly, - // e.g. case-insensitive set of hexadecimal? - NSString *backupPassword = [NSUUID UUID].UUIDString; - self.backupPassword = backupPassword; - DDLogInfo(@"%@ backup export with password: %@", self.logTag, backupPassword); - } - - [self startExport]; -} - -- (void)startExport -{ - OWSAssertIsOnMainThread(); - - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - [self exportToFilesAndZip]; - - dispatch_async(dispatch_get_main_queue(), ^{ - [self complete]; - }); - }); -} - -- (void)exportToFilesAndZip -{ - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - // First, clean up any existing backup import/export state. - [OWSBackup cleanupBackupState]; - - NSString *temporaryDirectory = NSTemporaryDirectory(); - NSString *rootDirName = [OWSBackup_DirNamePrefix stringByAppendingString:[NSUUID UUID].UUIDString]; - NSString *rootDirPath = [temporaryDirectory stringByAppendingPathComponent:rootDirName]; - NSString *backupDirPath = [rootDirPath stringByAppendingPathComponent:@"Contents"]; - - NSDateFormatter *dateFormatter = [NSDateFormatter new]; - [dateFormatter setLocale:[NSLocale currentLocale]]; - [dateFormatter setDateFormat:@"yyyy.MM.dd hh.mm.ss"]; - NSString *backupDateTime = [dateFormatter stringFromDate:[NSDate new]]; - NSString *backupName = - [NSString stringWithFormat:NSLocalizedString(@"BACKUP_FILENAME_FORMAT", - @"Format for backup filenames. Embeds: {{the date and time of the backup}}. " - @"Should not include characters like slash (/ or \\) or colon (:)."), - backupDateTime]; - NSString *backupZipPath = - [rootDirPath stringByAppendingPathComponent:[backupName stringByAppendingString:OWSBackup_FileExtension]]; - self.backupDirPath = backupDirPath; - self.backupZipPath = backupZipPath; - DDLogInfo(@"%@ rootDirPath: %@", self.logTag, rootDirPath); - DDLogInfo(@"%@ backupDirPath: %@", self.logTag, backupDirPath); - DDLogInfo(@"%@ backupZipPath: %@", self.logTag, backupZipPath); - - [OWSFileSystem ensureDirectoryExists:rootDirPath]; - [OWSFileSystem protectFileOrFolderAtPath:rootDirPath]; - [OWSFileSystem ensureDirectoryExists:backupDirPath]; - - if (self.isCancelledOrFailed) { - return; - } - - OWSAES256Key *encryptionKey = [OWSAES256Key generateRandomKey]; - self.encryptionKey = encryptionKey; - - NSData *databasePassword = [OWSPrimaryStorage sharedManager].databasePassword; - - // TODO: We don't want this to reside unencrypted on disk even temporarily. - // We need to encrypt this with a key that we hide in the keychain. - if (![self writeData:databasePassword - fileName:OWSBackup_DatabasePasswordFilename - backupDirPath:backupDirPath - encryptionKey:encryptionKey]) { - return [self fail]; - } - if (self.isCancelledOrFailed) { - return; - } - if (![self writeUserDefaults:NSUserDefaults.standardUserDefaults - fileName:OWSBackup_StandardUserDefaultsFilename - backupDirPath:backupDirPath - encryptionKey:encryptionKey]) { - return [self fail]; - } - if (self.isCancelledOrFailed) { - return; - } - if (![self writeUserDefaults:NSUserDefaults.appUserDefaults - fileName:OWSBackup_AppUserDefaultsFilename - backupDirPath:backupDirPath - encryptionKey:encryptionKey]) { - return [self fail]; - } - if (self.isCancelledOrFailed) { - return; - } - // Use a read/write transaction to acquire a file lock on the database files. - // - // TODO: If we use multiple database files, lock them too. - [OWSPrimaryStorage.sharedManager.newDatabaseConnection - readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { - if (![self copyDirectory:OWSFileSystem.appDocumentDirectoryPath - dstDirName:OWSBackup_AppDocumentDirName - backupDirPath:backupDirPath]) { - [self fail]; - return; - } - if (self.isCancelledOrFailed) { - return; - } - if (![self copyDirectory:OWSFileSystem.appSharedDataDirectoryPath - dstDirName:OWSBackup_AppSharedDataDirName - backupDirPath:backupDirPath]) { - [self fail]; - return; - } - }]; - if (self.isCancelledOrFailed) { - return; - } - if (![self zipDirectory:backupDirPath dstFilePath:backupZipPath encryptionKey:encryptionKey]) { - return [self fail]; - } - - [OWSFileSystem protectFileOrFolderAtPath:backupZipPath]; - - [OWSFileSystem deleteFileIfExists:self.backupDirPath]; -} - -- (BOOL)writeData:(NSData *)data - fileName:(NSString *)fileName - backupDirPath:(NSString *)backupDirPath - encryptionKey:(OWSAES256Key *)encryptionKey -{ - OWSAssert(data); - OWSAssert(fileName.length > 0); - OWSAssert(backupDirPath.length > 0); - OWSAssert(encryptionKey); - - NSData *_Nullable encryptedData = [Cryptography encryptAESGCMWithData:data key:encryptionKey]; - if (!encryptedData) { - OWSFail(@"%@ failed to encrypt data: %@", self.logTag, fileName); - return NO; - } - - NSString *filePath = [backupDirPath stringByAppendingPathComponent:fileName]; - - DDLogInfo(@"%@ writeData: %@", self.logTag, filePath); - - NSError *error; - BOOL success = [encryptedData writeToFile:filePath options:NSDataWritingAtomic error:&error]; - if (!success || error) { - OWSFail(@"%@ failed to write user defaults: %@", self.logTag, error); - return NO; - } - return YES; -} - -- (BOOL)copyDirectory:(NSString *)srcDirPath dstDirName:(NSString *)dstDirName backupDirPath:(NSString *)backupDirPath -{ - OWSAssert(srcDirPath.length > 0); - OWSAssert(dstDirName.length > 0); - OWSAssert(backupDirPath.length > 0); - - NSString *dstDirPath = [backupDirPath stringByAppendingPathComponent:dstDirName]; - - DDLogInfo(@"%@ copyDirectory: %@ -> %@", self.logTag, srcDirPath, dstDirPath); - - // We "manually" copy the "root" items in the src directory. - // Can't just use [NSFileManager copyItemAtPath:...] because the shared data container - // contains files that the app is not allowed to access. - [OWSFileSystem ensureDirectoryExists:dstDirPath]; - NSError *error = nil; - NSArray *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:srcDirPath error:&error]; - if (error) { - OWSFail(@"%@ failed to list directory: %@, %@", self.logTag, srcDirPath, error); - return NO; - } - for (NSString *fileName in fileNames) { - NSString *srcFilePath = [srcDirPath stringByAppendingPathComponent:fileName]; - NSString *dstFilePath = [dstDirPath stringByAppendingPathComponent:fileName]; - if ([fileName hasPrefix:@"."]) { - DDLogInfo(@"%@ ignoring: %@", self.logTag, srcFilePath); - continue; - } - BOOL success = [[NSFileManager defaultManager] copyItemAtPath:srcFilePath toPath:dstFilePath error:&error]; - if (!success || error) { - OWSFail(@"%@ failed to copy directory item: %@, %@", self.logTag, srcFilePath, error); - return NO; - } - } - - return YES; -} - -- (BOOL)writeUserDefaults:(NSUserDefaults *)userDefaults - fileName:(NSString *)fileName - backupDirPath:(NSString *)backupDirPath - encryptionKey:(OWSAES256Key *)encryptionKey -{ - OWSAssert(userDefaults); - OWSAssert(fileName.length > 0); - OWSAssert(backupDirPath.length > 0); - OWSAssert(encryptionKey); - - DDLogInfo(@"%@ writeUserDefaults: %@", self.logTag, fileName); - - NSDictionary *dictionary = userDefaults.dictionaryRepresentation; - if (!dictionary) { - OWSFail(@"%@ failed to extract user defaults", self.logTag); - return NO; - } - NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dictionary]; - if (!data) { - OWSFail(@"%@ failed to archive user defaults", self.logTag); - return NO; - } - - return [self writeData:data fileName:fileName backupDirPath:backupDirPath encryptionKey:encryptionKey]; -} - -- (BOOL)zipDirectory:(NSString *)srcDirPath - dstFilePath:(NSString *)dstFilePath - encryptionKey:(OWSAES256Key *)encryptionKey -{ - OWSAssert(srcDirPath.length > 0); - OWSAssert(dstFilePath.length > 0); - OWSAssert(encryptionKey); - - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - srcDirPath = [srcDirPath stringByStandardizingPath]; - OWSAssert(srcDirPath.length > 0); - - NSError *error; - NSArray *_Nullable srcFilePaths = [OWSFileSystem allFilesInDirectoryRecursive:srcDirPath error:&error]; - if (!srcFilePaths || error) { - OWSFail(@"%@ failed to find files to zip: %@", self.logTag, error); - return NO; - } - - // Don't use the SSZipArchive convenience methods so that we can add the - // encryption key directly as data. - SSZipArchive *zipArchive = [[SSZipArchive alloc] initWithPath:dstFilePath]; - if (![zipArchive open]) { - OWSFail(@"%@ failed to open zip file.", self.logTag); - return NO; - } - for (NSString *srcFilePath in srcFilePaths) { - NSString *relativePath = [self relativePathforPath:srcFilePath basePath:srcDirPath]; - BOOL success = [zipArchive writeFileAtPath:srcFilePath - withFileName:relativePath - compressionLevel:Z_DEFAULT_COMPRESSION - password:self.backupPassword - AES:self.backupPassword != nil]; - if (!success) { - OWSFail(@"%@ failed to write file to zip file.", self.logTag); - return NO; - } - } - // Write the encryption key directly into the zip so that it never - // resides in plaintext on disk. - BOOL success = [zipArchive writeData:encryptionKey.keyData - filename:OWSBackup_EncryptionKeyFilename - compressionLevel:Z_DEFAULT_COMPRESSION - password:self.backupPassword - AES:self.backupPassword != nil]; - if (!success) { - OWSFail(@"%@ failed to write file to zip file.", self.logTag); - return NO; - } - - - if (![zipArchive close]) { - OWSFail(@"%@ failed to close zip file.", self.logTag); - return NO; - } - - NSNumber *fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:dstFilePath error:&error][NSFileSize]; - if (error) { - OWSFail(@"%@ failed to get zip file size: %@", self.logTag, error); - return NO; - } - DDLogInfo(@"%@ Zip file size: %@", self.logTag, fileSize); - - return YES; -} - -#pragma mark - Import Backup, Part 1 - -- (void)importBackup:(NSString *)srcZipPath password:(NSString *_Nullable)password -{ - OWSAssertIsOnMainThread(); - OWSAssert(srcZipPath.length > 0); - OWSAssert(CurrentAppContext().isMainApp); - - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - self.backupPassword = password; - - self.backupState = OWSBackupState_InProgress; - - if (password.length == 0) { - DDLogInfo(@"%@ backup import without password", self.logTag); - } else { - DDLogInfo(@"%@ backup import with password: %@", self.logTag, password); - } - - [self startImport:srcZipPath]; -} - -- (void)startImport:(NSString *)srcZipPath -{ - OWSAssertIsOnMainThread(); - OWSAssert(srcZipPath.length > 0); - - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - [self prepareForImport:srcZipPath]; - - dispatch_async(dispatch_get_main_queue(), ^{ - [self complete]; - }); - }); -} - -- (void)prepareForImport:(NSString *)srcZipPath -{ - OWSAssert(srcZipPath.length > 0); - - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - NSString *documentDirectoryPath = OWSFileSystem.appDocumentDirectoryPath; - NSString *rootDirName = [OWSBackup_DirNamePrefix stringByAppendingString:[NSUUID UUID].UUIDString]; - NSString *rootDirPath = [documentDirectoryPath stringByAppendingPathComponent:rootDirName]; - NSString *backupDirPath = [rootDirPath stringByAppendingPathComponent:@"Contents"]; - NSString *backupZipPath = [rootDirPath stringByAppendingPathComponent:srcZipPath.lastPathComponent]; - self.backupDirPath = backupDirPath; - self.backupZipPath = backupZipPath; - DDLogInfo(@"%@ rootDirPath: %@", self.logTag, rootDirPath); - DDLogInfo(@"%@ backupDirPath: %@", self.logTag, backupDirPath); - DDLogInfo(@"%@ backupZipPath: %@", self.logTag, backupZipPath); - - [OWSFileSystem ensureDirectoryExists:rootDirPath]; - [OWSFileSystem protectFileOrFolderAtPath:rootDirPath]; - [OWSFileSystem ensureDirectoryExists:backupDirPath]; - - NSError *error = nil; - BOOL success = [[NSFileManager defaultManager] copyItemAtPath:srcZipPath toPath:backupZipPath error:&error]; - if (!success || error) { - OWSFail(@"%@ failed to copy backup zip: %@, %@", self.logTag, srcZipPath, error); - return [self fail]; - } - - if (self.isCancelledOrFailed) { - return; - } - if (![self unzipFilePath]) { - return [self fail]; - } - if (self.isCancelledOrFailed) { - return; - } - if (![self extractEncryptionKey]) { - return [self fail]; - } - if (self.isCancelledOrFailed) { - return; - } - if (![self isValidBackup]) { - return [self fail]; - } - if (self.isCancelledOrFailed) { - return; - } - if (![self enqueueBackupRestore]) { - return [self fail]; - } -} - -- (BOOL)extractEncryptionKey -{ - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - NSString *encryptionKeyFilePath = - [self.backupDirPath stringByAppendingPathComponent:OWSBackup_EncryptionKeyFilename]; - if (![[NSFileManager defaultManager] fileExistsAtPath:encryptionKeyFilePath]) { - return NO; - } - NSData *_Nullable encryptionKeyData = [NSData dataWithContentsOfFile:encryptionKeyFilePath]; - if (!encryptionKeyData) { - return NO; - } - OWSAES256Key *encryptionKey = [OWSAES256Key keyWithData:encryptionKeyData]; - if (!encryptionKey) { - return NO; - } - self.encryptionKey = encryptionKey; - - NSError *error = nil; - BOOL success = [[NSFileManager defaultManager] removeItemAtPath:encryptionKeyFilePath error:&error]; - if (!success || error) { - OWSFail(@"%@ could not delete encryption key file: %@", self.logTag, error); - return NO; - } - return YES; -} - -- (BOOL)unzipFilePath -{ - OWSAssert(self.backupZipPath.length > 0); - OWSAssert(self.backupDirPath.length > 0); - - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - // Don't use the SSZipArchive convenience methods so that we can add the - // encryption key directly as data. - - // TODO: Should we use preserveAttributes? - NSError *error = nil; - BOOL success = [SSZipArchive unzipFileAtPath:self.backupZipPath - toDestination:self.backupDirPath - preserveAttributes:YES - overwrite:YES - nestedZipLevel:0 - password:self.backupPassword - error:&error - delegate:self - progressHandler:^(NSString *entry, unz_file_info zipInfo, long entryNumber, long total) { - DDLogInfo(@"%@ progressHandler: %ld %ld", self.logTag, entryNumber, total); - - CGFloat progress = entryNumber / (CGFloat)total; - self.backupProgress = progress; - } - completionHandler:^(NSString *path, BOOL succeeded, NSError *_Nullable completionError) { - DDLogInfo(@"%@ completionHandler: %d %@", self.logTag, succeeded, completionError); - }]; - if (!success || error) { - OWSFail(@"%@ failed to unzip file: %@.", self.logTag, error); - return NO; - } - - return YES; -} - -- (BOOL)isValidBackup -{ - NSString *databasePasswordFilePath = - [self.backupDirPath stringByAppendingPathComponent:OWSBackup_DatabasePasswordFilename]; - if (![[NSFileManager defaultManager] fileExistsAtPath:databasePasswordFilePath]) { - return NO; - } - NSString *standardUserDefaultsFilePath = - [self.backupDirPath stringByAppendingPathComponent:OWSBackup_StandardUserDefaultsFilename]; - if (![[NSFileManager defaultManager] fileExistsAtPath:standardUserDefaultsFilePath]) { - return NO; - } - NSString *appUserDefaultsFilePath = - [self.backupDirPath stringByAppendingPathComponent:OWSBackup_AppUserDefaultsFilename]; - if (![[NSFileManager defaultManager] fileExistsAtPath:appUserDefaultsFilePath]) { - return NO; - } - // TODO: Verify that the primary database exists. - - return YES; -} - -- (BOOL)enqueueBackupRestore -{ - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - NSError *error = nil; - [SAMKeychain setAccessibilityType:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly]; - BOOL success = [SAMKeychain setPasswordData:self.encryptionKey.keyData - forService:Keychain_ImportBackupService - account:Keychain_ImportBackupKey - error:&error]; - if (!success || error) { - OWSFail(@"%@ Could not store encryption key for import backup: %@", self.logTag, error); - return NO; - } - - NSString *documentDirectoryPath = OWSFileSystem.appDocumentDirectoryPath; - NSString *relativePath = [self relativePathforPath:self.backupDirPath basePath:documentDirectoryPath]; - [[NSUserDefaults appUserDefaults] setObject:relativePath forKey:NSUserDefaults_QueuedBackupPath]; - [[NSUserDefaults appUserDefaults] synchronize]; - - return YES; -} - -#pragma mark - Import Backup, Part 2 - -- (void)completeImportBackupIfPossible -{ - OWSAssertIsOnMainThread(); - OWSAssert(CurrentAppContext().isMainApp); - - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - NSString *_Nullable queuedBackupRelativePath = - [[NSUserDefaults appUserDefaults] stringForKey:NSUserDefaults_QueuedBackupPath]; - if (queuedBackupRelativePath.length == 0) { - return; - } - NSString *documentDirectoryPath = OWSFileSystem.appDocumentDirectoryPath; - NSString *_Nullable queuedBackupPath = - [self joinRelativePath:queuedBackupRelativePath basePath:documentDirectoryPath]; - if (![[NSFileManager defaultManager] fileExistsAtPath:queuedBackupPath]) { - OWSFail(@"%@ Missing import backup directory: %@.", self.logTag, queuedBackupPath); - return; - } - self.backupDirPath = queuedBackupPath; - self.backupState = OWSBackupState_InProgress; - DDLogInfo(@"%@ queuedBackupPath: %@", self.logTag, queuedBackupPath); - - [SAMKeychain setAccessibilityType:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly]; - NSError *error; - NSData *_Nullable encryptionKeyData = - [SAMKeychain passwordDataForService:Keychain_ImportBackupService account:Keychain_ImportBackupKey error:&error]; - if (!encryptionKeyData || error) { - OWSFail(@"%@ Could not retrieve encryption key for import backup: %@", self.logTag, error); - return; - } - self.encryptionKey = [OWSAES256Key keyWithData:encryptionKeyData]; - - if (![self isValidBackup]) { - return; - } - - NSData *_Nullable databasePassword = [self readDataFromFileName:OWSBackup_DatabasePasswordFilename]; - if (!databasePassword) { - OWSFail(@"%@ Could not retrieve database password.", self.logTag); - return; - } - - // We can't restore a backup atomically, so we: - // - // * Ensure the restore consists only of tiny writes, and file moves. - // * Write the database password last. - if (![self loadUserDefaults:NSUserDefaults.standardUserDefaults fileName:OWSBackup_StandardUserDefaultsFilename]) { - return; - } - if (![self loadUserDefaults:NSUserDefaults.appUserDefaults fileName:OWSBackup_AppUserDefaultsFilename]) { - return; - } - - if (![self restoreDirectoryContents:OWSFileSystem.appDocumentDirectoryPath - srcDirName:OWSBackup_AppDocumentDirName]) { - return; - } - if (![self restoreDirectoryContents:OWSFileSystem.appSharedDataDirectoryPath - srcDirName:OWSBackup_AppSharedDataDirName]) { - return; - } - - // TODO: Possibly verify database file location? - - [OWSStorage storeDatabasePassword:[[NSString alloc] initWithData:databasePassword encoding:NSUTF8StringEncoding]]; -} - -- (nullable NSData *)readDataFromFileName:(NSString *)fileName -{ - OWSAssert(fileName.length > 0); - OWSAssert(self.backupDirPath.length > 0); - OWSAssert(self.encryptionKey); - - NSString *filePath = [self.backupDirPath stringByAppendingPathComponent:fileName]; - - DDLogInfo(@"%@ readDataFromFileName: %@", self.logTag, filePath); - - NSData *_Nullable encryptedData = [NSData dataWithContentsOfFile:filePath]; - if (!encryptedData) { - OWSFail(@"%@ failed to read encrypted data: %@", self.logTag, fileName); - return nil; - } - - NSData *_Nullable data = [Cryptography decryptAESGCMWithData:encryptedData key:self.encryptionKey]; - if (!data) { - OWSFail(@"%@ failed to decrypt data: %@", self.logTag, fileName); - return nil; - } - - return data; -} - -- (BOOL)loadUserDefaults:(NSUserDefaults *)userDefaults fileName:(NSString *)fileName -{ - OWSAssert(userDefaults); - OWSAssert(fileName.length > 0); - OWSAssert(self.backupDirPath.length > 0); - OWSAssert(self.encryptionKey); - - DDLogInfo(@"%@ loadUserDefaults: %@", self.logTag, fileName); - - NSData *_Nullable data = [self readDataFromFileName:fileName]; - if (!data) { - OWSFail(@"%@ Could not retrieve user defaults: %@.", self.logTag, fileName); - return NO; - } - - NSError *error; - NSDictionary *_Nullable dictionary = - [NSKeyedUnarchiver unarchiveTopLevelObjectWithData:data error:&error]; - if (!dictionary || error) { - OWSFail(@"%@ Could not unarchive user defaults: %@", self.logTag, error); - return NO; - } - if (![dictionary isKindOfClass:[NSDictionary class]]) { - OWSFail(@"%@ Unexpected archived user defaults: %@", self.logTag, error); - return NO; - } - - // Clear out any existing keys in this instance of NSUserDefaults. - for (NSString *key in userDefaults.dictionaryRepresentation) { - [userDefaults removeObjectForKey:key]; - } - - // TODO: this doesn't yet remove any keys, so you end up with the "union". - for (NSString *key in dictionary) { - id value = dictionary[key]; - OWSAssert(value); - [userDefaults setObject:value forKey:key]; - } - - [userDefaults synchronize]; - - return YES; -} - -- (BOOL)renameDirectoryContents:(NSString *)dirPath -{ - OWSAssert(dirPath.length > 0); - - DDLogInfo(@"%@ renameDirectoryContents: %@", self.logTag, dirPath); - - NSError *error = nil; - NSArray *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dirPath error:&error]; - if (error) { - OWSFail(@"%@ failed to list directory: %@, %@", self.logTag, dirPath, error); - return NO; - } - for (NSString *fileName in fileNames) { - if ([fileName hasPrefix:@"."]) { - // Ignore hidden files and directories. - continue; - } - NSString *filePath = [dirPath stringByAppendingPathComponent:fileName]; - - // To replace an existing file or directory, rename the existing item - // by adding a date/time suffix. - NSDateFormatter *dateFormatter = [NSDateFormatter new]; - [dateFormatter setLocale:[NSLocale currentLocale]]; - [dateFormatter setDateFormat:@".yyyy.MM.dd hh.mm.ss"]; - NSString *replacementDateTime = [dateFormatter stringFromDate:[NSDate new]]; - - // Prefix with period to prevent subsequent backups from including these old, replaced - // files and directories. - NSString *renamedFileName = [NSString stringWithFormat:@".Old.%@.%@", fileName, replacementDateTime]; - NSString *renamedFilePath = [dirPath stringByAppendingPathComponent:renamedFileName]; - BOOL success = [[NSFileManager defaultManager] moveItemAtPath:filePath toPath:renamedFilePath error:&error]; - if (!success || error) { - OWSFail(@"%@ failed to move directory item: %@, %@", self.logTag, filePath, error); - return NO; - } - if (![OWSFileSystem protectFileOrFolderAtPath:renamedFilePath]) { - OWSFail(@"%@ failed to protect old directory item: %@, %@", self.logTag, renamedFilePath, error); - return NO; - } - } - - return YES; -} - -- (BOOL)restoreDirectoryContents:(NSString *)dstDirPath srcDirName:(NSString *)srcDirName -{ - OWSAssert(srcDirName.length > 0); - OWSAssert(dstDirPath.length > 0); - OWSAssert(self.backupDirPath.length > 0); - - // Rename any existing files and directories in this directory. - if (![self renameDirectoryContents:dstDirPath]) { - return NO; - } - - NSString *srcDirPath = [self.backupDirPath stringByAppendingPathComponent:srcDirName]; - - DDLogInfo(@"%@ restoreDirectoryContents: %@ -> %@", self.logTag, srcDirPath, dstDirPath); - - if (![[NSFileManager defaultManager] fileExistsAtPath:srcDirPath]) { - // Not all backups will have both a "app documents" and "shared data container" folder. - // The latter should always be present for "modern" installs, but we are permissive - // here about what we accept so that we can easily apply this branch to historic - // (pre-shared data container) versions of the app and restore from them. - DDLogInfo(@"%@ Skipping restore directory: %@.", self.logTag, srcDirPath); - return YES; - } - - NSError *error = nil; - NSArray *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:srcDirPath error:&error]; - if (error) { - OWSFail(@"%@ failed to list directory: %@, %@", self.logTag, srcDirPath, error); - return NO; - } - for (NSString *fileName in fileNames) { - if ([fileName hasPrefix:@"."]) { - // Ignore hidden files and directories. - OWSFail(@"%@ can't restore hidden file or directory: %@", self.logTag, fileName); - continue; - } - NSString *srcFilePath = [srcDirPath stringByAppendingPathComponent:fileName]; - NSString *dstFilePath = [dstDirPath stringByAppendingPathComponent:fileName]; - - if ([[NSFileManager defaultManager] fileExistsAtPath:dstFilePath]) { - // All conflicting contents should have already been moved by renameDirectoryContents. - OWSFail(@"%@ unexpected pre-existing file or directory: %@", self.logTag, fileName); - continue; - } - - BOOL success = [[NSFileManager defaultManager] moveItemAtPath:srcFilePath toPath:dstFilePath error:&error]; - if (!success || error) { - OWSFail(@"%@ failed to move directory item: %@, %@", self.logTag, dstFilePath, error); - return NO; - } - if (![OWSFileSystem protectFileOrFolderAtPath:dstFilePath]) { - OWSFail(@"%@ failed to protect directory item: %@, %@", self.logTag, dstFilePath, error); - return NO; - } - } - - return YES; -} - -#pragma mark - Clean up - -+ (void)cleanupBackupState -{ - DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); - - [self cleanupBackupDirectoriesInDirectory:NSTemporaryDirectory()]; - [self cleanupBackupDirectoriesInDirectory:OWSFileSystem.appDocumentDirectoryPath]; - - [[NSUserDefaults appUserDefaults] removeObjectForKey:NSUserDefaults_QueuedBackupPath]; - [[NSUserDefaults appUserDefaults] synchronize]; -} - -+ (void)cleanupBackupDirectoriesInDirectory:(NSString *)dirPath -{ - OWSAssert(dirPath.length > 0); - - NSError *error; - NSArray *filenames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dirPath error:&error]; - if (error) { - OWSFail(@"%@ could not find files in directory: %@", self.logTag, error); - return; - } - - for (NSString *filename in filenames) { - if (![filename hasPrefix:OWSBackup_DirNamePrefix]) { - continue; - } - NSString *filePath = [dirPath stringByAppendingPathComponent:filename]; - BOOL success = [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error]; - if (!success || error) { - OWSFail(@"%@ could not clean up backup directory: %@", self.logTag, error); - return; - } - } -} - -#pragma mark - Utils - -- (NSString *)relativePathforPath:(NSString *)filePath basePath:(NSString *)basePath -{ - OWSAssert(filePath.stringByStandardizingPath.length > 0); - OWSAssert([filePath.stringByStandardizingPath hasPrefix:basePath.stringByStandardizingPath]); - - NSString *relativePath = - [filePath.stringByStandardizingPath substringFromIndex:basePath.stringByStandardizingPath.length]; - NSString *separator = @"/"; - if ([relativePath hasPrefix:separator]) { - relativePath = [relativePath substringFromIndex:separator.length]; - } - OWSAssert(relativePath.length > 0); - return relativePath; -} - -- (NSString *)joinRelativePath:(NSString *)relativePath basePath:(NSString *)basePath -{ - OWSAssert(basePath.stringByStandardizingPath.length > 0); - OWSAssert(relativePath.length > 0); - - return [basePath stringByAppendingPathComponent:relativePath]; -} - -#pragma mark - App Launch - -+ (void)applicationDidFinishLaunching -{ - [[OWSBackup new] completeImportBackupIfPossible]; - - // Always clean up backup state on disk, but defer so as not to interface with - // app launch sequence. - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ - [OWSBackup cleanupBackupState]; - }); -} - -#pragma mark - SSZipArchiveDelegate - -- (void)zipArchiveProgressEvent:(unsigned long long)loaded total:(unsigned long long)total -{ - DDLogInfo(@"%@ zipArchiveProgressEvent: %llu %llu", self.logTag, loaded, total); - - CGFloat progress = loaded / (CGFloat)total; - self.backupProgress = progress; -} +//- (void)setBackupProgress:(CGFloat)backupProgress +//{ +// _backupProgress = backupProgress; +// +// dispatch_async(dispatch_get_main_queue(), ^{ +// [self.delegate backupProgressDidChange]; +// }); +//} +// +//- (void)fail +//{ +// DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); +// +// if (!self.isCancelledOrFailed) { +// self.backupState = OWSBackupState_Failed; +// } +// +// dispatch_async(dispatch_get_main_queue(), ^{ +// [OWSBackup cleanupBackupState]; +// }); +//} +// +//- (void)cancel +//{ +// DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); +// +// if (!self.isCancelledOrFailed) { +// self.backupState = OWSBackupState_Cancelled; +// } +// +// dispatch_async(dispatch_get_main_queue(), ^{ +// [OWSBackup cleanupBackupState]; +// }); +//} +// +//- (void)complete +//{ +// DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); +// +// if (!self.isCancelledOrFailed) { +// self.backupState = OWSBackupState_Complete; +// } +//} +// +//- (BOOL)isCancelledOrFailed +//{ +// return (self.backupState == OWSBackupState_Cancelled || self.backupState == OWSBackupState_Failed); +//} +// +//#pragma mark - Export Backup +// +//- (void)exportBackup:(nullable TSThread *)currentThread skipPassword:(BOOL)skipPassword +//{ +// OWSAssertIsOnMainThread(); +// OWSAssert(CurrentAppContext().isMainApp); +// +// DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); +// +// self.currentThread = currentThread; +// self.backupState = OWSBackupState_InProgress; +// +// if (skipPassword) { +// DDLogInfo(@"%@ backup export without password", self.logTag); +// } else { +// // TODO: Should the user pick a password? +// // If not, should probably generate something more user-friendly, +// // e.g. case-insensitive set of hexadecimal? +// NSString *backupPassword = [NSUUID UUID].UUIDString; +// self.backupPassword = backupPassword; +// DDLogInfo(@"%@ backup export with password: %@", self.logTag, backupPassword); +// } +// +// [self startExport]; +//} +// +//- (void)startExport +//{ +// OWSAssertIsOnMainThread(); +// +// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ +// [self exportToFilesAndZip]; +// +// dispatch_async(dispatch_get_main_queue(), ^{ +// [self complete]; +// }); +// }); +//} +// +//- (void)exportToFilesAndZip +//{ +// DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); +// +// // First, clean up any existing backup import/export state. +// [OWSBackup cleanupBackupState]; +// +// NSString *temporaryDirectory = NSTemporaryDirectory(); +// NSString *rootDirName = [OWSBackup_DirNamePrefix stringByAppendingString:[NSUUID UUID].UUIDString]; +// NSString *rootDirPath = [temporaryDirectory stringByAppendingPathComponent:rootDirName]; +// NSString *backupDirPath = [rootDirPath stringByAppendingPathComponent:@"Contents"]; +// +// NSDateFormatter *dateFormatter = [NSDateFormatter new]; +// [dateFormatter setLocale:[NSLocale currentLocale]]; +// [dateFormatter setDateFormat:@"yyyy.MM.dd hh.mm.ss"]; +// NSString *backupDateTime = [dateFormatter stringFromDate:[NSDate new]]; +// NSString *backupName = +// [NSString stringWithFormat:NSLocalizedString(@"BACKUP_FILENAME_FORMAT", +// @"Format for backup filenames. Embeds: {{the date and time of the backup}}. " +// @"Should not include characters like slash (/ or \\) or colon (:)."), +// backupDateTime]; +// NSString *backupZipPath = +// [rootDirPath stringByAppendingPathComponent:[backupName stringByAppendingString:OWSBackup_FileExtension]]; +// self.backupDirPath = backupDirPath; +// self.backupZipPath = backupZipPath; +// DDLogInfo(@"%@ rootDirPath: %@", self.logTag, rootDirPath); +// DDLogInfo(@"%@ backupDirPath: %@", self.logTag, backupDirPath); +// DDLogInfo(@"%@ backupZipPath: %@", self.logTag, backupZipPath); +// +// [OWSFileSystem ensureDirectoryExists:rootDirPath]; +// [OWSFileSystem protectFileOrFolderAtPath:rootDirPath]; +// [OWSFileSystem ensureDirectoryExists:backupDirPath]; +// +// if (self.isCancelledOrFailed) { +// return; +// } +// +// OWSAES256Key *encryptionKey = [OWSAES256Key generateRandomKey]; +// self.encryptionKey = encryptionKey; +// +// NSData *databasePassword = [OWSPrimaryStorage sharedManager].databasePassword; +// +// // TODO: We don't want this to reside unencrypted on disk even temporarily. +// // We need to encrypt this with a key that we hide in the keychain. +// if (![self writeData:databasePassword +// fileName:OWSBackup_DatabasePasswordFilename +// backupDirPath:backupDirPath +// encryptionKey:encryptionKey]) { +// return [self fail]; +// } +// if (self.isCancelledOrFailed) { +// return; +// } +// if (![self writeUserDefaults:NSUserDefaults.standardUserDefaults +// fileName:OWSBackup_StandardUserDefaultsFilename +// backupDirPath:backupDirPath +// encryptionKey:encryptionKey]) { +// return [self fail]; +// } +// if (self.isCancelledOrFailed) { +// return; +// } +// if (![self writeUserDefaults:NSUserDefaults.appUserDefaults +// fileName:OWSBackup_AppUserDefaultsFilename +// backupDirPath:backupDirPath +// encryptionKey:encryptionKey]) { +// return [self fail]; +// } +// if (self.isCancelledOrFailed) { +// return; +// } +// // Use a read/write transaction to acquire a file lock on the database files. +// // +// // TODO: If we use multiple database files, lock them too. +// [OWSPrimaryStorage.sharedManager.newDatabaseConnection +// readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { +// if (![self copyDirectory:OWSFileSystem.appDocumentDirectoryPath +// dstDirName:OWSBackup_AppDocumentDirName +// backupDirPath:backupDirPath]) { +// [self fail]; +// return; +// } +// if (self.isCancelledOrFailed) { +// return; +// } +// if (![self copyDirectory:OWSFileSystem.appSharedDataDirectoryPath +// dstDirName:OWSBackup_AppSharedDataDirName +// backupDirPath:backupDirPath]) { +// [self fail]; +// return; +// } +// }]; +// if (self.isCancelledOrFailed) { +// return; +// } +// if (![self zipDirectory:backupDirPath dstFilePath:backupZipPath encryptionKey:encryptionKey]) { +// return [self fail]; +// } +// +// [OWSFileSystem protectFileOrFolderAtPath:backupZipPath]; +// +// [OWSFileSystem deleteFileIfExists:self.backupDirPath]; +//} +// +//- (BOOL)writeData:(NSData *)data +// fileName:(NSString *)fileName +// backupDirPath:(NSString *)backupDirPath +// encryptionKey:(OWSAES256Key *)encryptionKey +//{ +// OWSAssert(data); +// OWSAssert(fileName.length > 0); +// OWSAssert(backupDirPath.length > 0); +// OWSAssert(encryptionKey); +// +// NSData *_Nullable encryptedData = [Cryptography encryptAESGCMWithData:data key:encryptionKey]; +// if (!encryptedData) { +// OWSFail(@"%@ failed to encrypt data: %@", self.logTag, fileName); +// return NO; +// } +// +// NSString *filePath = [backupDirPath stringByAppendingPathComponent:fileName]; +// +// DDLogInfo(@"%@ writeData: %@", self.logTag, filePath); +// +// NSError *error; +// BOOL success = [encryptedData writeToFile:filePath options:NSDataWritingAtomic error:&error]; +// if (!success || error) { +// OWSFail(@"%@ failed to write user defaults: %@", self.logTag, error); +// return NO; +// } +// return YES; +//} +// +//- (BOOL)copyDirectory:(NSString *)srcDirPath dstDirName:(NSString *)dstDirName backupDirPath:(NSString *)backupDirPath +//{ +// OWSAssert(srcDirPath.length > 0); +// OWSAssert(dstDirName.length > 0); +// OWSAssert(backupDirPath.length > 0); +// +// NSString *dstDirPath = [backupDirPath stringByAppendingPathComponent:dstDirName]; +// +// DDLogInfo(@"%@ copyDirectory: %@ -> %@", self.logTag, srcDirPath, dstDirPath); +// +// // We "manually" copy the "root" items in the src directory. +// // Can't just use [NSFileManager copyItemAtPath:...] because the shared data container +// // contains files that the app is not allowed to access. +// [OWSFileSystem ensureDirectoryExists:dstDirPath]; +// NSError *error = nil; +// NSArray *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:srcDirPath +// error:&error]; if (error) { +// OWSFail(@"%@ failed to list directory: %@, %@", self.logTag, srcDirPath, error); +// return NO; +// } +// for (NSString *fileName in fileNames) { +// NSString *srcFilePath = [srcDirPath stringByAppendingPathComponent:fileName]; +// NSString *dstFilePath = [dstDirPath stringByAppendingPathComponent:fileName]; +// if ([fileName hasPrefix:@"."]) { +// DDLogInfo(@"%@ ignoring: %@", self.logTag, srcFilePath); +// continue; +// } +// BOOL success = [[NSFileManager defaultManager] copyItemAtPath:srcFilePath toPath:dstFilePath error:&error]; +// if (!success || error) { +// OWSFail(@"%@ failed to copy directory item: %@, %@", self.logTag, srcFilePath, error); +// return NO; +// } +// } +// +// return YES; +//} +// +//- (BOOL)writeUserDefaults:(NSUserDefaults *)userDefaults +// fileName:(NSString *)fileName +// backupDirPath:(NSString *)backupDirPath +// encryptionKey:(OWSAES256Key *)encryptionKey +//{ +// OWSAssert(userDefaults); +// OWSAssert(fileName.length > 0); +// OWSAssert(backupDirPath.length > 0); +// OWSAssert(encryptionKey); +// +// DDLogInfo(@"%@ writeUserDefaults: %@", self.logTag, fileName); +// +// NSDictionary *dictionary = userDefaults.dictionaryRepresentation; +// if (!dictionary) { +// OWSFail(@"%@ failed to extract user defaults", self.logTag); +// return NO; +// } +// NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dictionary]; +// if (!data) { +// OWSFail(@"%@ failed to archive user defaults", self.logTag); +// return NO; +// } +// +// return [self writeData:data fileName:fileName backupDirPath:backupDirPath encryptionKey:encryptionKey]; +//} +// +//- (BOOL)zipDirectory:(NSString *)srcDirPath +// dstFilePath:(NSString *)dstFilePath +// encryptionKey:(OWSAES256Key *)encryptionKey +//{ +// OWSAssert(srcDirPath.length > 0); +// OWSAssert(dstFilePath.length > 0); +// OWSAssert(encryptionKey); +// +// DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); +// +// srcDirPath = [srcDirPath stringByStandardizingPath]; +// OWSAssert(srcDirPath.length > 0); +// +// NSError *error; +// NSArray *_Nullable srcFilePaths = [OWSFileSystem allFilesInDirectoryRecursive:srcDirPath +// error:&error]; if (!srcFilePaths || error) { +// OWSFail(@"%@ failed to find files to zip: %@", self.logTag, error); +// return NO; +// } +// +// // Don't use the SSZipArchive convenience methods so that we can add the +// // encryption key directly as data. +// SSZipArchive *zipArchive = [[SSZipArchive alloc] initWithPath:dstFilePath]; +// if (![zipArchive open]) { +// OWSFail(@"%@ failed to open zip file.", self.logTag); +// return NO; +// } +// for (NSString *srcFilePath in srcFilePaths) { +// NSString *relativePath = [self relativePathforPath:srcFilePath basePath:srcDirPath]; +// BOOL success = [zipArchive writeFileAtPath:srcFilePath +// withFileName:relativePath +// compressionLevel:Z_DEFAULT_COMPRESSION +// password:self.backupPassword +// AES:self.backupPassword != nil]; +// if (!success) { +// OWSFail(@"%@ failed to write file to zip file.", self.logTag); +// return NO; +// } +// } +// // Write the encryption key directly into the zip so that it never +// // resides in plaintext on disk. +// BOOL success = [zipArchive writeData:encryptionKey.keyData +// filename:OWSBackup_EncryptionKeyFilename +// compressionLevel:Z_DEFAULT_COMPRESSION +// password:self.backupPassword +// AES:self.backupPassword != nil]; +// if (!success) { +// OWSFail(@"%@ failed to write file to zip file.", self.logTag); +// return NO; +// } +// +// +// if (![zipArchive close]) { +// OWSFail(@"%@ failed to close zip file.", self.logTag); +// return NO; +// } +// +// NSNumber *fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:dstFilePath error:&error][NSFileSize]; +// if (error) { +// OWSFail(@"%@ failed to get zip file size: %@", self.logTag, error); +// return NO; +// } +// DDLogInfo(@"%@ Zip file size: %@", self.logTag, fileSize); +// +// return YES; +//} +// +//#pragma mark - Import Backup, Part 1 +// +//- (void)importBackup:(NSString *)srcZipPath password:(NSString *_Nullable)password +//{ +// OWSAssertIsOnMainThread(); +// OWSAssert(srcZipPath.length > 0); +// OWSAssert(CurrentAppContext().isMainApp); +// +// DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); +// +// self.backupPassword = password; +// +// self.backupState = OWSBackupState_InProgress; +// +// if (password.length == 0) { +// DDLogInfo(@"%@ backup import without password", self.logTag); +// } else { +// DDLogInfo(@"%@ backup import with password: %@", self.logTag, password); +// } +// +// [self startImport:srcZipPath]; +//} +// +//- (void)startImport:(NSString *)srcZipPath +//{ +// OWSAssertIsOnMainThread(); +// OWSAssert(srcZipPath.length > 0); +// +// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ +// [self prepareForImport:srcZipPath]; +// +// dispatch_async(dispatch_get_main_queue(), ^{ +// [self complete]; +// }); +// }); +//} +// +//- (void)prepareForImport:(NSString *)srcZipPath +//{ +// OWSAssert(srcZipPath.length > 0); +// +// DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); +// +// NSString *documentDirectoryPath = OWSFileSystem.appDocumentDirectoryPath; +// NSString *rootDirName = [OWSBackup_DirNamePrefix stringByAppendingString:[NSUUID UUID].UUIDString]; +// NSString *rootDirPath = [documentDirectoryPath stringByAppendingPathComponent:rootDirName]; +// NSString *backupDirPath = [rootDirPath stringByAppendingPathComponent:@"Contents"]; +// NSString *backupZipPath = [rootDirPath stringByAppendingPathComponent:srcZipPath.lastPathComponent]; +// self.backupDirPath = backupDirPath; +// self.backupZipPath = backupZipPath; +// DDLogInfo(@"%@ rootDirPath: %@", self.logTag, rootDirPath); +// DDLogInfo(@"%@ backupDirPath: %@", self.logTag, backupDirPath); +// DDLogInfo(@"%@ backupZipPath: %@", self.logTag, backupZipPath); +// +// [OWSFileSystem ensureDirectoryExists:rootDirPath]; +// [OWSFileSystem protectFileOrFolderAtPath:rootDirPath]; +// [OWSFileSystem ensureDirectoryExists:backupDirPath]; +// +// NSError *error = nil; +// BOOL success = [[NSFileManager defaultManager] copyItemAtPath:srcZipPath toPath:backupZipPath error:&error]; +// if (!success || error) { +// OWSFail(@"%@ failed to copy backup zip: %@, %@", self.logTag, srcZipPath, error); +// return [self fail]; +// } +// +// if (self.isCancelledOrFailed) { +// return; +// } +// if (![self unzipFilePath]) { +// return [self fail]; +// } +// if (self.isCancelledOrFailed) { +// return; +// } +// if (![self extractEncryptionKey]) { +// return [self fail]; +// } +// if (self.isCancelledOrFailed) { +// return; +// } +// if (![self isValidBackup]) { +// return [self fail]; +// } +// if (self.isCancelledOrFailed) { +// return; +// } +// if (![self enqueueBackupRestore]) { +// return [self fail]; +// } +//} +// +//- (BOOL)extractEncryptionKey +//{ +// DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); +// +// NSString *encryptionKeyFilePath = +// [self.backupDirPath stringByAppendingPathComponent:OWSBackup_EncryptionKeyFilename]; +// if (![[NSFileManager defaultManager] fileExistsAtPath:encryptionKeyFilePath]) { +// return NO; +// } +// NSData *_Nullable encryptionKeyData = [NSData dataWithContentsOfFile:encryptionKeyFilePath]; +// if (!encryptionKeyData) { +// return NO; +// } +// OWSAES256Key *encryptionKey = [OWSAES256Key keyWithData:encryptionKeyData]; +// if (!encryptionKey) { +// return NO; +// } +// self.encryptionKey = encryptionKey; +// +// NSError *error = nil; +// BOOL success = [[NSFileManager defaultManager] removeItemAtPath:encryptionKeyFilePath error:&error]; +// if (!success || error) { +// OWSFail(@"%@ could not delete encryption key file: %@", self.logTag, error); +// return NO; +// } +// return YES; +//} +// +//- (BOOL)unzipFilePath +//{ +// OWSAssert(self.backupZipPath.length > 0); +// OWSAssert(self.backupDirPath.length > 0); +// +// DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); +// +// // Don't use the SSZipArchive convenience methods so that we can add the +// // encryption key directly as data. +// +// // TODO: Should we use preserveAttributes? +// NSError *error = nil; +// BOOL success = [SSZipArchive unzipFileAtPath:self.backupZipPath +// toDestination:self.backupDirPath +// preserveAttributes:YES +// overwrite:YES +// nestedZipLevel:0 +// password:self.backupPassword +// error:&error +// delegate:self +// progressHandler:^(NSString *entry, unz_file_info zipInfo, long entryNumber, long total) { +// DDLogInfo(@"%@ progressHandler: %ld %ld", self.logTag, entryNumber, total); +// +// CGFloat progress = entryNumber / (CGFloat)total; +// self.backupProgress = progress; +// } +// completionHandler:^(NSString *path, BOOL succeeded, NSError *_Nullable completionError) { +// DDLogInfo(@"%@ completionHandler: %d %@", self.logTag, succeeded, completionError); +// }]; +// if (!success || error) { +// OWSFail(@"%@ failed to unzip file: %@.", self.logTag, error); +// return NO; +// } +// +// return YES; +//} +// +//- (BOOL)isValidBackup +//{ +// NSString *databasePasswordFilePath = +// [self.backupDirPath stringByAppendingPathComponent:OWSBackup_DatabasePasswordFilename]; +// if (![[NSFileManager defaultManager] fileExistsAtPath:databasePasswordFilePath]) { +// return NO; +// } +// NSString *standardUserDefaultsFilePath = +// [self.backupDirPath stringByAppendingPathComponent:OWSBackup_StandardUserDefaultsFilename]; +// if (![[NSFileManager defaultManager] fileExistsAtPath:standardUserDefaultsFilePath]) { +// return NO; +// } +// NSString *appUserDefaultsFilePath = +// [self.backupDirPath stringByAppendingPathComponent:OWSBackup_AppUserDefaultsFilename]; +// if (![[NSFileManager defaultManager] fileExistsAtPath:appUserDefaultsFilePath]) { +// return NO; +// } +// // TODO: Verify that the primary database exists. +// +// return YES; +//} +// +//- (BOOL)enqueueBackupRestore +//{ +// DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); +// +// NSError *error = nil; +// [SAMKeychain setAccessibilityType:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly]; +// BOOL success = [SAMKeychain setPasswordData:self.encryptionKey.keyData +// forService:Keychain_ImportBackupService +// account:Keychain_ImportBackupKey +// error:&error]; +// if (!success || error) { +// OWSFail(@"%@ Could not store encryption key for import backup: %@", self.logTag, error); +// return NO; +// } +// +// NSString *documentDirectoryPath = OWSFileSystem.appDocumentDirectoryPath; +// NSString *relativePath = [self relativePathforPath:self.backupDirPath basePath:documentDirectoryPath]; +// [[NSUserDefaults appUserDefaults] setObject:relativePath forKey:NSUserDefaults_QueuedBackupPath]; +// [[NSUserDefaults appUserDefaults] synchronize]; +// +// return YES; +//} +// +//#pragma mark - Import Backup, Part 2 +// +//- (void)completeImportBackupIfPossible +//{ +// OWSAssertIsOnMainThread(); +// OWSAssert(CurrentAppContext().isMainApp); +// +// DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); +// +// NSString *_Nullable queuedBackupRelativePath = +// [[NSUserDefaults appUserDefaults] stringForKey:NSUserDefaults_QueuedBackupPath]; +// if (queuedBackupRelativePath.length == 0) { +// return; +// } +// NSString *documentDirectoryPath = OWSFileSystem.appDocumentDirectoryPath; +// NSString *_Nullable queuedBackupPath = +// [self joinRelativePath:queuedBackupRelativePath basePath:documentDirectoryPath]; +// if (![[NSFileManager defaultManager] fileExistsAtPath:queuedBackupPath]) { +// OWSFail(@"%@ Missing import backup directory: %@.", self.logTag, queuedBackupPath); +// return; +// } +// self.backupDirPath = queuedBackupPath; +// self.backupState = OWSBackupState_InProgress; +// DDLogInfo(@"%@ queuedBackupPath: %@", self.logTag, queuedBackupPath); +// +// [SAMKeychain setAccessibilityType:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly]; +// NSError *error; +// NSData *_Nullable encryptionKeyData = +// [SAMKeychain passwordDataForService:Keychain_ImportBackupService account:Keychain_ImportBackupKey +// error:&error]; +// if (!encryptionKeyData || error) { +// OWSFail(@"%@ Could not retrieve encryption key for import backup: %@", self.logTag, error); +// return; +// } +// self.encryptionKey = [OWSAES256Key keyWithData:encryptionKeyData]; +// +// if (![self isValidBackup]) { +// return; +// } +// +// NSData *_Nullable databasePassword = [self readDataFromFileName:OWSBackup_DatabasePasswordFilename]; +// if (!databasePassword) { +// OWSFail(@"%@ Could not retrieve database password.", self.logTag); +// return; +// } +// +// // We can't restore a backup atomically, so we: +// // +// // * Ensure the restore consists only of tiny writes, and file moves. +// // * Write the database password last. +// if (![self loadUserDefaults:NSUserDefaults.standardUserDefaults fileName:OWSBackup_StandardUserDefaultsFilename]) +// { +// return; +// } +// if (![self loadUserDefaults:NSUserDefaults.appUserDefaults fileName:OWSBackup_AppUserDefaultsFilename]) { +// return; +// } +// +// if (![self restoreDirectoryContents:OWSFileSystem.appDocumentDirectoryPath +// srcDirName:OWSBackup_AppDocumentDirName]) { +// return; +// } +// if (![self restoreDirectoryContents:OWSFileSystem.appSharedDataDirectoryPath +// srcDirName:OWSBackup_AppSharedDataDirName]) { +// return; +// } +// +// // TODO: Possibly verify database file location? +// +// [OWSStorage storeDatabasePassword:[[NSString alloc] initWithData:databasePassword encoding:NSUTF8StringEncoding]]; +//} +// +//- (nullable NSData *)readDataFromFileName:(NSString *)fileName +//{ +// OWSAssert(fileName.length > 0); +// OWSAssert(self.backupDirPath.length > 0); +// OWSAssert(self.encryptionKey); +// +// NSString *filePath = [self.backupDirPath stringByAppendingPathComponent:fileName]; +// +// DDLogInfo(@"%@ readDataFromFileName: %@", self.logTag, filePath); +// +// NSData *_Nullable encryptedData = [NSData dataWithContentsOfFile:filePath]; +// if (!encryptedData) { +// OWSFail(@"%@ failed to read encrypted data: %@", self.logTag, fileName); +// return nil; +// } +// +// NSData *_Nullable data = [Cryptography decryptAESGCMWithData:encryptedData key:self.encryptionKey]; +// if (!data) { +// OWSFail(@"%@ failed to decrypt data: %@", self.logTag, fileName); +// return nil; +// } +// +// return data; +//} +// +//- (BOOL)loadUserDefaults:(NSUserDefaults *)userDefaults fileName:(NSString *)fileName +//{ +// OWSAssert(userDefaults); +// OWSAssert(fileName.length > 0); +// OWSAssert(self.backupDirPath.length > 0); +// OWSAssert(self.encryptionKey); +// +// DDLogInfo(@"%@ loadUserDefaults: %@", self.logTag, fileName); +// +// NSData *_Nullable data = [self readDataFromFileName:fileName]; +// if (!data) { +// OWSFail(@"%@ Could not retrieve user defaults: %@.", self.logTag, fileName); +// return NO; +// } +// +// NSError *error; +// NSDictionary *_Nullable dictionary = +// [NSKeyedUnarchiver unarchiveTopLevelObjectWithData:data error:&error]; +// if (!dictionary || error) { +// OWSFail(@"%@ Could not unarchive user defaults: %@", self.logTag, error); +// return NO; +// } +// if (![dictionary isKindOfClass:[NSDictionary class]]) { +// OWSFail(@"%@ Unexpected archived user defaults: %@", self.logTag, error); +// return NO; +// } +// +// // Clear out any existing keys in this instance of NSUserDefaults. +// for (NSString *key in userDefaults.dictionaryRepresentation) { +// [userDefaults removeObjectForKey:key]; +// } +// +// // TODO: this doesn't yet remove any keys, so you end up with the "union". +// for (NSString *key in dictionary) { +// id value = dictionary[key]; +// OWSAssert(value); +// [userDefaults setObject:value forKey:key]; +// } +// +// [userDefaults synchronize]; +// +// return YES; +//} +// +//- (BOOL)renameDirectoryContents:(NSString *)dirPath +//{ +// OWSAssert(dirPath.length > 0); +// +// DDLogInfo(@"%@ renameDirectoryContents: %@", self.logTag, dirPath); +// +// NSError *error = nil; +// NSArray *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dirPath error:&error]; +// if (error) { +// OWSFail(@"%@ failed to list directory: %@, %@", self.logTag, dirPath, error); +// return NO; +// } +// for (NSString *fileName in fileNames) { +// if ([fileName hasPrefix:@"."]) { +// // Ignore hidden files and directories. +// continue; +// } +// NSString *filePath = [dirPath stringByAppendingPathComponent:fileName]; +// +// // To replace an existing file or directory, rename the existing item +// // by adding a date/time suffix. +// NSDateFormatter *dateFormatter = [NSDateFormatter new]; +// [dateFormatter setLocale:[NSLocale currentLocale]]; +// [dateFormatter setDateFormat:@".yyyy.MM.dd hh.mm.ss"]; +// NSString *replacementDateTime = [dateFormatter stringFromDate:[NSDate new]]; +// +// // Prefix with period to prevent subsequent backups from including these old, replaced +// // files and directories. +// NSString *renamedFileName = [NSString stringWithFormat:@".Old.%@.%@", fileName, replacementDateTime]; +// NSString *renamedFilePath = [dirPath stringByAppendingPathComponent:renamedFileName]; +// BOOL success = [[NSFileManager defaultManager] moveItemAtPath:filePath toPath:renamedFilePath error:&error]; +// if (!success || error) { +// OWSFail(@"%@ failed to move directory item: %@, %@", self.logTag, filePath, error); +// return NO; +// } +// if (![OWSFileSystem protectFileOrFolderAtPath:renamedFilePath]) { +// OWSFail(@"%@ failed to protect old directory item: %@, %@", self.logTag, renamedFilePath, error); +// return NO; +// } +// } +// +// return YES; +//} +// +//- (BOOL)restoreDirectoryContents:(NSString *)dstDirPath srcDirName:(NSString *)srcDirName +//{ +// OWSAssert(srcDirName.length > 0); +// OWSAssert(dstDirPath.length > 0); +// OWSAssert(self.backupDirPath.length > 0); +// +// // Rename any existing files and directories in this directory. +// if (![self renameDirectoryContents:dstDirPath]) { +// return NO; +// } +// +// NSString *srcDirPath = [self.backupDirPath stringByAppendingPathComponent:srcDirName]; +// +// DDLogInfo(@"%@ restoreDirectoryContents: %@ -> %@", self.logTag, srcDirPath, dstDirPath); +// +// if (![[NSFileManager defaultManager] fileExistsAtPath:srcDirPath]) { +// // Not all backups will have both a "app documents" and "shared data container" folder. +// // The latter should always be present for "modern" installs, but we are permissive +// // here about what we accept so that we can easily apply this branch to historic +// // (pre-shared data container) versions of the app and restore from them. +// DDLogInfo(@"%@ Skipping restore directory: %@.", self.logTag, srcDirPath); +// return YES; +// } +// +// NSError *error = nil; +// NSArray *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:srcDirPath +// error:&error]; if (error) { +// OWSFail(@"%@ failed to list directory: %@, %@", self.logTag, srcDirPath, error); +// return NO; +// } +// for (NSString *fileName in fileNames) { +// if ([fileName hasPrefix:@"."]) { +// // Ignore hidden files and directories. +// OWSFail(@"%@ can't restore hidden file or directory: %@", self.logTag, fileName); +// continue; +// } +// NSString *srcFilePath = [srcDirPath stringByAppendingPathComponent:fileName]; +// NSString *dstFilePath = [dstDirPath stringByAppendingPathComponent:fileName]; +// +// if ([[NSFileManager defaultManager] fileExistsAtPath:dstFilePath]) { +// // All conflicting contents should have already been moved by renameDirectoryContents. +// OWSFail(@"%@ unexpected pre-existing file or directory: %@", self.logTag, fileName); +// continue; +// } +// +// BOOL success = [[NSFileManager defaultManager] moveItemAtPath:srcFilePath toPath:dstFilePath error:&error]; +// if (!success || error) { +// OWSFail(@"%@ failed to move directory item: %@, %@", self.logTag, dstFilePath, error); +// return NO; +// } +// if (![OWSFileSystem protectFileOrFolderAtPath:dstFilePath]) { +// OWSFail(@"%@ failed to protect directory item: %@, %@", self.logTag, dstFilePath, error); +// return NO; +// } +// } +// +// return YES; +//} +// +//#pragma mark - Clean up +// +//+ (void)cleanupBackupState +//{ +// DDLogInfo(@"%@ %s.", self.logTag, __PRETTY_FUNCTION__); +// +// [self cleanupBackupDirectoriesInDirectory:NSTemporaryDirectory()]; +// [self cleanupBackupDirectoriesInDirectory:OWSFileSystem.appDocumentDirectoryPath]; +// +// [[NSUserDefaults appUserDefaults] removeObjectForKey:NSUserDefaults_QueuedBackupPath]; +// [[NSUserDefaults appUserDefaults] synchronize]; +//} +// +//+ (void)cleanupBackupDirectoriesInDirectory:(NSString *)dirPath +//{ +// OWSAssert(dirPath.length > 0); +// +// NSError *error; +// NSArray *filenames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dirPath error:&error]; +// if (error) { +// OWSFail(@"%@ could not find files in directory: %@", self.logTag, error); +// return; +// } +// +// for (NSString *filename in filenames) { +// if (![filename hasPrefix:OWSBackup_DirNamePrefix]) { +// continue; +// } +// NSString *filePath = [dirPath stringByAppendingPathComponent:filename]; +// BOOL success = [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error]; +// if (!success || error) { +// OWSFail(@"%@ could not clean up backup directory: %@", self.logTag, error); +// return; +// } +// } +//} +// +//#pragma mark - Utils +// +//- (NSString *)relativePathforPath:(NSString *)filePath basePath:(NSString *)basePath +//{ +// OWSAssert(filePath.stringByStandardizingPath.length > 0); +// OWSAssert([filePath.stringByStandardizingPath hasPrefix:basePath.stringByStandardizingPath]); +// +// NSString *relativePath = +// [filePath.stringByStandardizingPath substringFromIndex:basePath.stringByStandardizingPath.length]; +// NSString *separator = @"/"; +// if ([relativePath hasPrefix:separator]) { +// relativePath = [relativePath substringFromIndex:separator.length]; +// } +// OWSAssert(relativePath.length > 0); +// return relativePath; +//} +// +//- (NSString *)joinRelativePath:(NSString *)relativePath basePath:(NSString *)basePath +//{ +// OWSAssert(basePath.stringByStandardizingPath.length > 0); +// OWSAssert(relativePath.length > 0); +// +// return [basePath stringByAppendingPathComponent:relativePath]; +//} +// +//#pragma mark - App Launch +// +//+ (void)applicationDidFinishLaunching +//{ +// [[OWSBackup new] completeImportBackupIfPossible]; +// +// // Always clean up backup state on disk, but defer so as not to interface with +// // app launch sequence. +// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ +// [OWSBackup cleanupBackupState]; +// }); +//} +// +//#pragma mark - SSZipArchiveDelegate +// +//- (void)zipArchiveProgressEvent:(unsigned long long)loaded total:(unsigned long long)total +//{ +// DDLogInfo(@"%@ zipArchiveProgressEvent: %llu %llu", self.logTag, loaded, total); +// +// CGFloat progress = loaded / (CGFloat)total; +// self.backupProgress = progress; +//} @end diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 961108db9..691421500 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -193,30 +193,6 @@ /* Format for backup filenames. Embeds: {{the date and time of the backup}}. Should not include characters like slash (/ or \\) or colon (:). */ "BACKUP_FILENAME_FORMAT" = "Signal Backup %@"; -/* Message indicating that backup import is complete. */ -"BACKUP_IMPORT_COMPLETE_MESSAGE" = "Restore Complete"; - -/* Label for button confirming backup import. */ -"BACKUP_IMPORT_CONFIRM_ALERT_BUTTON" = "Restore"; - -/* Message for alert confirming backup import. */ -"BACKUP_IMPORT_CONFIRM_ALERT_MESSAGE" = "To restore this backup you must restart the Signal app. Warning: you will lose all of your current Signal data."; - -/* Title for alert confirming backup import. */ -"BACKUP_IMPORT_CONFIRM_ALERT_TITLE" = "Restore Backup?"; - -/* Message indicating that backup import failed. */ -"BACKUP_IMPORT_FAILED_MESSAGE" = "Restore Failed"; - -/* Message indicating that backup import is in progress. */ -"BACKUP_IMPORT_IN_PROGRESS_MESSAGE" = "Restoring Backup..."; - -/* Label for button that restarts app to complete restore. */ -"BACKUP_IMPORT_RESTART_BUTTON" = "Restart App"; - -/* Title for the 'backup import' view. */ -"BACKUP_IMPORT_VIEW_TITLE" = "Restore Backup"; - /* An explanation of the consequences of blocking another user. */ "BLOCK_BEHAVIOR_EXPLANATION" = "Blocked users will not be able to call you or send you messages."; @@ -1603,6 +1579,9 @@ /* Format string for the default 'Note' sound. Embeds the system {{sound name}}. */ "SETTINGS_AUDIO_DEFAULT_TONE_LABEL_FORMAT" = "%@ (default)"; +/* Label for the backup view in app settings. */ +"SETTINGS_BACKUP" = "SETTINGS_BACKUP"; + /* A label for the 'add phone number' button in the block list table. */ "SETTINGS_BLOCK_LIST_ADD_BUTTON" = "Add…"; diff --git a/SignalServiceKit/src/Messages/OWSBlockingManager.m b/SignalServiceKit/src/Messages/OWSBlockingManager.m index 18151ae82..ed96ae7ba 100644 --- a/SignalServiceKit/src/Messages/OWSBlockingManager.m +++ b/SignalServiceKit/src/Messages/OWSBlockingManager.m @@ -15,6 +15,7 @@ NS_ASSUME_NONNULL_BEGIN NSString *const kNSNotificationName_BlockedPhoneNumbersDidChange = @"kNSNotificationName_BlockedPhoneNumbersDidChange"; +extern NSString *const kNSNotificationName_BlockedPhoneNumbersDidChange; NSString *const kOWSBlockingManager_BlockedPhoneNumbersCollection = @"kOWSBlockingManager_BlockedPhoneNumbersCollection"; // This key is used to persist the current "blocked phone numbers" state.