From 91b89aaf3904ba430acf717046ea61d8d0ef865c Mon Sep 17 00:00:00 2001 From: Maarten Billemont Date: Tue, 14 Jan 2020 13:59:32 -0500 Subject: [PATCH] Pearl & API update. --- platform-darwin/External/Pearl | 2 +- .../project.pbxproj | 46 +- platform-darwin/Source/MPAppDelegate_InApp.m | 36 +- platform-darwin/Source/MPAppDelegate_Key.m | 24 +- .../Source/MasterPassword-Prefix.pch | 22 +- .../Source/iOS/MPAnswersViewController.m | 43 +- platform-darwin/Source/iOS/MPAvatarCell.m | 30 +- .../Source/iOS/MPLogsViewController.m | 34 +- platform-darwin/Source/iOS/MPPopdownSegue.m | 4 +- .../Source/iOS/MPPreferencesViewController.m | 10 +- platform-darwin/Source/iOS/MPSiteCell.m | 123 +++-- .../Source/iOS/MPSitesViewController.m | 4 +- .../Source/iOS/MPStoreViewController.m | 15 +- .../Source/iOS/MPUsersViewController.m | 48 +- platform-darwin/Source/iOS/MPiOSAppDelegate.m | 433 +++++++++--------- .../Source/iOS/MasterPassword-Info.plist | 260 +++++------ platform-independent/c/core/src/mpw-util.h | 2 +- 17 files changed, 575 insertions(+), 561 deletions(-) diff --git a/platform-darwin/External/Pearl b/platform-darwin/External/Pearl index 3d04d775..4eb904f9 160000 --- a/platform-darwin/External/Pearl +++ b/platform-darwin/External/Pearl @@ -1 +1 @@ -Subproject commit 3d04d775e01ab1a437bb42166e92662ffffeedd4 +Subproject commit 4eb904f9b4c318da36b5071d57d137b63f8ef144 diff --git a/platform-darwin/MasterPassword-iOS.xcodeproj/project.pbxproj b/platform-darwin/MasterPassword-iOS.xcodeproj/project.pbxproj index 20063b5c..c2648b81 100644 --- a/platform-darwin/MasterPassword-iOS.xcodeproj/project.pbxproj +++ b/platform-darwin/MasterPassword-iOS.xcodeproj/project.pbxproj @@ -241,6 +241,11 @@ DAA1765419D8B82B0044227B /* choose_type.png in Resources */ = {isa = PBXBuildFile; fileRef = DAA1763E19D8B82B0044227B /* choose_type.png */; }; DAA449D21EEC4B5800E7BDD5 /* mpw-marshal.c in Sources */ = {isa = PBXBuildFile; fileRef = DAA449D01EEC4B5800E7BDD5 /* mpw-marshal.c */; }; DAA7BC2720C4C27100101DC7 /* libsodium.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAA7BB8A20C4C10F00101DC7 /* libsodium.a */; }; + DAAA1D4123CD145000F3DF56 /* Storyboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DAAA1D4023CD145000F3DF56 /* Storyboard.storyboard */; }; + DAAA1D4423CD161300F3DF56 /* UILayoutGuide+Pearl.m in Sources */ = {isa = PBXBuildFile; fileRef = DAAA1D4223CD161300F3DF56 /* UILayoutGuide+Pearl.m */; }; + DAAA1D4523CD161300F3DF56 /* UILayoutGuide+Pearl.h in Headers */ = {isa = PBXBuildFile; fileRef = DAAA1D4323CD161300F3DF56 /* UILayoutGuide+Pearl.h */; }; + DAAA1D4823CD164500F3DF56 /* PearlRSAKey.m in Sources */ = {isa = PBXBuildFile; fileRef = DAAA1D4623CD164500F3DF56 /* PearlRSAKey.m */; }; + DAAA1D4923CD164500F3DF56 /* PearlRSAKey.h in Headers */ = {isa = PBXBuildFile; fileRef = DAAA1D4723CD164500F3DF56 /* PearlRSAKey.h */; }; DAADBFE01A68763B00F7A756 /* mpw-algorithm.c in Sources */ = {isa = PBXBuildFile; fileRef = 93D3969393A3A46BD27D7078 /* mpw-algorithm.c */; }; DAB07C9D1F7725C500CC6D43 /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = DAB07C9B1F7725C500CC6D43 /* aes.c */; }; DAB4FBC4202FDDDD002768FB /* NSInvocation+Pearl.h in Headers */ = {isa = PBXBuildFile; fileRef = DAB4FBC2202FDDDC002768FB /* NSInvocation+Pearl.h */; }; @@ -415,8 +420,6 @@ DAFE4A3715039824003ABA7C /* PearlKeyChain.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE460115039823003ABA7C /* PearlKeyChain.m */; }; DAFE4A3C15039824003ABA7C /* Pearl-UIKit-Dependencies.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460815039823003ABA7C /* Pearl-UIKit-Dependencies.h */; }; DAFE4A3D15039824003ABA7C /* Pearl-UIKit.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460915039823003ABA7C /* Pearl-UIKit.h */; }; - DAFE4A3E15039824003ABA7C /* PearlAlert.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460A15039823003ABA7C /* PearlAlert.h */; }; - DAFE4A3F15039824003ABA7C /* PearlAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE460B15039823003ABA7C /* PearlAlert.m */; }; DAFE4A4015039824003ABA7C /* PearlArrayTVC.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460C15039823003ABA7C /* PearlArrayTVC.h */; }; DAFE4A4115039824003ABA7C /* PearlArrayTVC.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE460D15039823003ABA7C /* PearlArrayTVC.m */; }; DAFE4A4215039824003ABA7C /* PearlBoxView.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460E15039823003ABA7C /* PearlBoxView.h */; }; @@ -427,8 +430,6 @@ DAFE4A4B15039824003ABA7C /* PearlMessageView.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE461715039823003ABA7C /* PearlMessageView.m */; }; DAFE4A4C15039824003ABA7C /* PearlRootViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE461815039823003ABA7C /* PearlRootViewController.h */; }; DAFE4A4D15039824003ABA7C /* PearlRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE461915039823003ABA7C /* PearlRootViewController.m */; }; - DAFE4A4E15039824003ABA7C /* PearlSheet.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE461A15039823003ABA7C /* PearlSheet.h */; }; - DAFE4A4F15039824003ABA7C /* PearlSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE461B15039823003ABA7C /* PearlSheet.m */; }; DAFE4A5015039824003ABA7C /* PearlUIDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE461C15039823003ABA7C /* PearlUIDebug.h */; }; DAFE4A5115039824003ABA7C /* PearlUIDebug.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE461D15039823003ABA7C /* PearlUIDebug.m */; }; DAFE4A5215039824003ABA7C /* PearlUIUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE461E15039823003ABA7C /* PearlUIUtils.h */; }; @@ -896,6 +897,11 @@ DAA7BBC620C4C10F00101DC7 /* crypto_generichash_blake2b.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_generichash_blake2b.h; sourceTree = ""; }; DAA7BBC720C4C10F00101DC7 /* crypto_sign_edwards25519sha512batch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_sign_edwards25519sha512batch.h; sourceTree = ""; }; DAA7BBC820C4C10F00101DC7 /* sodium.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sodium.h; sourceTree = ""; }; + DAAA1D4023CD145000F3DF56 /* Storyboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Storyboard.storyboard; sourceTree = ""; }; + DAAA1D4223CD161300F3DF56 /* UILayoutGuide+Pearl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UILayoutGuide+Pearl.m"; sourceTree = ""; }; + DAAA1D4323CD161300F3DF56 /* UILayoutGuide+Pearl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UILayoutGuide+Pearl.h"; sourceTree = ""; }; + DAAA1D4623CD164500F3DF56 /* PearlRSAKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlRSAKey.m; sourceTree = ""; }; + DAAA1D4723CD164500F3DF56 /* PearlRSAKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlRSAKey.h; sourceTree = ""; }; DAAC35DD156BD77D00C5FD93 /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; }; DAB07C9B1F7725C500CC6D43 /* aes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aes.c; sourceTree = ""; }; DAB07C9C1F7725C500CC6D43 /* aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes.h; sourceTree = ""; }; @@ -1640,8 +1646,6 @@ DAFE460615039823003ABA7C /* README */ = {isa = PBXFileReference; fileEncoding = 1; lastKnownFileType = text; path = README; sourceTree = ""; }; DAFE460815039823003ABA7C /* Pearl-UIKit-Dependencies.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Pearl-UIKit-Dependencies.h"; sourceTree = ""; }; DAFE460915039823003ABA7C /* Pearl-UIKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Pearl-UIKit.h"; sourceTree = ""; }; - DAFE460A15039823003ABA7C /* PearlAlert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlAlert.h; sourceTree = ""; }; - DAFE460B15039823003ABA7C /* PearlAlert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlAlert.m; sourceTree = ""; }; DAFE460C15039823003ABA7C /* PearlArrayTVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlArrayTVC.h; sourceTree = ""; }; DAFE460D15039823003ABA7C /* PearlArrayTVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlArrayTVC.m; sourceTree = ""; }; DAFE460E15039823003ABA7C /* PearlBoxView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlBoxView.h; sourceTree = ""; }; @@ -1652,8 +1656,6 @@ DAFE461715039823003ABA7C /* PearlMessageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlMessageView.m; sourceTree = ""; }; DAFE461815039823003ABA7C /* PearlRootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlRootViewController.h; sourceTree = ""; }; DAFE461915039823003ABA7C /* PearlRootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlRootViewController.m; sourceTree = ""; }; - DAFE461A15039823003ABA7C /* PearlSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlSheet.h; sourceTree = ""; }; - DAFE461B15039823003ABA7C /* PearlSheet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlSheet.m; sourceTree = ""; }; DAFE461C15039823003ABA7C /* PearlUIDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlUIDebug.h; sourceTree = ""; }; DAFE461D15039823003ABA7C /* PearlUIDebug.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlUIDebug.m; sourceTree = ""; }; DAFE461E15039823003ABA7C /* PearlUIUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlUIUtils.h; sourceTree = ""; }; @@ -2940,6 +2942,7 @@ DABD3BD71711E2DC00CF925C /* iOS */ = { isa = PBXGroup; children = ( + DAAA1D4023CD145000F3DF56 /* Storyboard.storyboard */, DABD3BFA1711E2DC00CF925C /* InfoPlist.strings */, DABD3BFC1711E2DC00CF925C /* main.m */, DABD3BF31711E2DC00CF925C /* MasterPassword-Info.plist */, @@ -3166,6 +3169,8 @@ DA45711B1F572F1E00D54152 /* PearlCryptUtils.m */, DAFE460015039823003ABA7C /* PearlKeyChain.h */, DAFE460115039823003ABA7C /* PearlKeyChain.m */, + DAAA1D4723CD164500F3DF56 /* PearlRSAKey.h */, + DAAA1D4623CD164500F3DF56 /* PearlRSAKey.m */, DAFE460615039823003ABA7C /* README */, ); path = "Pearl-Crypto"; @@ -3179,8 +3184,6 @@ DAFE460815039823003ABA7C /* Pearl-UIKit-Dependencies.h */, DAFE460915039823003ABA7C /* Pearl-UIKit.h */, DA30E9D315722EF400A68B4C /* Pearl-UIKit.m */, - DAFE460A15039823003ABA7C /* PearlAlert.h */, - DAFE460B15039823003ABA7C /* PearlAlert.m */, DAFE4A61150399FF003ABA7C /* PearlAppDelegate.h */, DAFE4A60150399FF003ABA7C /* PearlAppDelegate.m */, DAFE460C15039823003ABA7C /* PearlArrayTVC.h */, @@ -3205,8 +3208,6 @@ 93D390FADEB325D8D54A957D /* PearlOverlay.m */, DAFE461815039823003ABA7C /* PearlRootViewController.h */, DAFE461915039823003ABA7C /* PearlRootViewController.m */, - DAFE461A15039823003ABA7C /* PearlSheet.h */, - DAFE461B15039823003ABA7C /* PearlSheet.m */, 93D39A4759186F6D2D34AA6B /* PearlSizedTextView.h */, 93D39156E806BB78E04F78B9 /* PearlSizedTextView.m */, 93D39B1D8177A86C5B9EDDE3 /* PearlUICollectionView.h */, @@ -3231,6 +3232,8 @@ DAFE4A63150399FF003ABA89 /* UIControl+PearlSelect.m */, DAFE4A1115039824003ABA7C /* UIImage+PearlScaling.h */, DAFE4A1215039824003ABA7C /* UIImage+PearlScaling.m */, + DAAA1D4323CD161300F3DF56 /* UILayoutGuide+Pearl.h */, + DAAA1D4223CD161300F3DF56 /* UILayoutGuide+Pearl.m */, 93D394482BB07F90E8FD1314 /* UIResponder+PearlFirstResponder.h */, 93D39A1DDFA09AE2E14D26DC /* UIResponder+PearlFirstResponder.m */, 93D39DE2CB351D4E3789462B /* UIScrollView+PearlAdjustInsets.h */, @@ -3296,6 +3299,7 @@ DAFE4A1515039824003ABA7C /* NSString+PearlNSArrayFormat.h in Headers */, DAFE4A1715039824003ABA7C /* NSString+PearlSEL.h in Headers */, DA250A1A195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.h in Headers */, + DAAA1D4923CD164500F3DF56 /* PearlRSAKey.h in Headers */, DAFE4A1915039824003ABA7C /* Pearl.h in Headers */, DAFE4A1A15039824003ABA7C /* PearlAbstractStrings.h in Headers */, DAFE4A1E15039824003ABA7C /* PearlCodeUtils.h in Headers */, @@ -3322,7 +3326,6 @@ DAB4FBD6202FDE48002768FB /* PearlLinks.h in Headers */, DAEC85B818E3DD9A007FC0DF /* UIView+Touches.h in Headers */, DAFE4A3D15039824003ABA7C /* Pearl-UIKit.h in Headers */, - DAFE4A3E15039824003ABA7C /* PearlAlert.h in Headers */, DAFE4A4015039824003ABA7C /* PearlArrayTVC.h in Headers */, DAFE4A4215039824003ABA7C /* PearlBoxView.h in Headers */, DAEFB01F19BCBD9E00525079 /* UIView+LayoutGone.h in Headers */, @@ -3332,7 +3335,6 @@ DACE2F6619BA6A0A0010F92E /* PearlProfiler.h in Headers */, DAFE4A4C15039824003ABA7C /* PearlRootViewController.h in Headers */, DAB4FBC9202FDE0F002768FB /* PearlCryptUtils.h in Headers */, - DAFE4A4E15039824003ABA7C /* PearlSheet.h in Headers */, DAFE4A5015039824003ABA7C /* PearlUIDebug.h in Headers */, DAFE4A5215039824003ABA7C /* PearlUIUtils.h in Headers */, DAFE4A5415039824003ABA7C /* PearlValidatingTextField.h in Headers */, @@ -3368,6 +3370,7 @@ 93D399E4BC1E092A8C8B12AE /* NSOrderedSetOrArray.h in Headers */, 93D39BFB5F5F9337F6565DE3 /* UIView+Visible.h in Headers */, DAB4FBD4202FDE48002768FB /* UIView+PearlLayout.h in Headers */, + DAAA1D4523CD161300F3DF56 /* UILayoutGuide+Pearl.h in Headers */, 93D39359B0DF9823F6C56A05 /* PearlHangDetector.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -3874,6 +3877,7 @@ DABD3FCF1714F45C00CF925C /* identity@2x.png in Resources */, DAA1764619D8B82B0044227B /* name_new.png in Resources */, DA45224B190628B2008F650A /* icon_gear.png in Resources */, + DAAA1D4123CD145000F3DF56 /* Storyboard.storyboard in Resources */, DA8495311A93049300B3053D /* icon_down.png in Resources */, DA25C5FF197DBF200046CDCF /* icon_thumbs-up@2x.png in Resources */, DAE1EF2217E942DE00BC0086 /* Localizable.strings in Resources */, @@ -4059,6 +4063,7 @@ DAFE4A1415039824003ABA7C /* NSObject+PearlExport.m in Sources */, DAFE4A1615039824003ABA7C /* NSString+PearlNSArrayFormat.m in Sources */, DAFE4A1815039824003ABA7C /* NSString+PearlSEL.m in Sources */, + DAAA1D4823CD164500F3DF56 /* PearlRSAKey.m in Sources */, DAFE4A1B15039824003ABA7C /* PearlAbstractStrings.m in Sources */, DAFE4A1F15039824003ABA7C /* PearlCodeUtils.m in Sources */, DAEFB01E19BCBD9E00525079 /* UIView+LayoutGone.m in Sources */, @@ -4073,7 +4078,6 @@ DAFE4A3715039824003ABA7C /* PearlKeyChain.m in Sources */, DA72BD7B19C1510C00E6ACFE /* UIView+FontScale.m in Sources */, DA250A17195665A100AC23F1 /* UITableView+PearlReloadItems.m in Sources */, - DAFE4A3F15039824003ABA7C /* PearlAlert.m in Sources */, DAFE4A4115039824003ABA7C /* PearlArrayTVC.m in Sources */, DAFE4A4315039824003ABA7C /* PearlBoxView.m in Sources */, DAFE4A4515039824003ABA7C /* PearlGradientView.m in Sources */, @@ -4082,7 +4086,6 @@ DAFE4A4B15039824003ABA7C /* PearlMessageView.m in Sources */, DACE2F6519BA6A0A0010F92E /* PearlProfiler.m in Sources */, DAFE4A4D15039824003ABA7C /* PearlRootViewController.m in Sources */, - DAFE4A4F15039824003ABA7C /* PearlSheet.m in Sources */, DAFE4A5115039824003ABA7C /* PearlUIDebug.m in Sources */, DAFE4A5315039824003ABA7C /* PearlUIUtils.m in Sources */, DAFE4A5515039824003ABA7C /* PearlValidatingTextField.m in Sources */, @@ -4119,6 +4122,7 @@ 93D39A8EA1C49CE43B63F47B /* PearlUICollectionView.m in Sources */, 93D399246DC90F50913A1287 /* UIResponder+PearlFirstResponder.m in Sources */, DAA141201922FF020032B392 /* PearlTween.m in Sources */, + DAAA1D4423CD161300F3DF56 /* UILayoutGuide+Pearl.m in Sources */, DAB4FBD7202FDE48002768FB /* UIView+PearlLayout.m in Sources */, 93D391ECBD9BD2C64115B5DD /* PearlSizedTextView.m in Sources */, DAB4FBD3202FDE48002768FB /* PearlLinks.m in Sources */, @@ -4309,7 +4313,7 @@ GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "${TARGET_NAME}"; @@ -4348,7 +4352,6 @@ "\"$(PROJECT_DIR)/../lib/libjson-c/build-ios~/out/include\"", ); INFOPLIST_FILE = "Source/iOS/MasterPassword-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -4523,7 +4526,7 @@ GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = "-ObjC"; @@ -4628,7 +4631,7 @@ GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "${TARGET_NAME}"; @@ -4666,7 +4669,6 @@ "\"$(PROJECT_DIR)/../lib/libjson-c/build-ios~/out/include\"", ); INFOPLIST_FILE = "Source/iOS/MasterPassword-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -4710,7 +4712,6 @@ "\"$(PROJECT_DIR)/../lib/libjson-c/build-ios~/out/include\"", ); INFOPLIST_FILE = "Source/iOS/MasterPassword-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -4728,7 +4729,6 @@ SWIFT_OBJC_BRIDGING_HEADER = "Source/iOS/MasterPassword-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 4.0; - TARGETED_DEVICE_FAMILY = 1; }; name = Release; }; diff --git a/platform-darwin/Source/MPAppDelegate_InApp.m b/platform-darwin/Source/MPAppDelegate_InApp.m index c5b10aa8..e093b4ba 100644 --- a/platform-darwin/Source/MPAppDelegate_InApp.m +++ b/platform-darwin/Source/MPAppDelegate_InApp.m @@ -104,24 +104,19 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve #if TARGET_OS_IPHONE if (![[MPAppDelegate_Shared get] canMakePayments]) { - [PearlAlert showAlertWithTitle:@"App Store Not Set Up" message: + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"App Store Not Set Up" message: @"Make sure your Apple ID is set under Settings -> iTunes & App Store, " - @"you have a payment method added to the account and purchases are" - @"not disabled under General -> Restrictions." - viewStyle:UIAlertViewStyleDefault initAlert:nil - tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { - if (buttonIndex == alert.cancelButtonIndex) - // Cancel - return; - if (buttonIndex == alert.firstOtherButtonIndex) { - // Settings - [PearlLinks openSettingsStore]; - return; - } - - // Try Anyway - [self performPurchaseProductWithIdentifier:productIdentifier quantity:quantity]; - } cancelTitle:@"Cancel" otherTitles:@"Settings", @"Try Anyway", nil]; + @"you have a payment method added to the account and purchases are" + @"not disabled under General -> Restrictions." + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Settings" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [PearlLinks openSettingsStore]; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Try Anyway" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [self performPurchaseProductWithIdentifier:productIdentifier quantity:quantity]; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; return; } #endif @@ -163,11 +158,12 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve MPError( error, @"StoreKit request (%@) failed.", request ); #if TARGET_OS_IPHONE - [PearlAlert showAlertWithTitle:@"Purchase Failed" message: + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Purchase Failed" message: strf( @"%@\n\n%@", error.localizedDescription, @"Ensure you are online and try logging out and back into iTunes from your device's Settings." ) - viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock:nil - cancelTitle:@"OK" otherTitles:nil]; + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; #else #endif } diff --git a/platform-darwin/Source/MPAppDelegate_Key.m b/platform-darwin/Source/MPAppDelegate_Key.m index 71800e99..305698e3 100644 --- a/platform-darwin/Source/MPAppDelegate_Key.m +++ b/platform-darwin/Source/MPAppDelegate_Key.m @@ -256,17 +256,19 @@ #ifdef PEARL_UIKIT masterPassword = PearlAwait( ^(void (^setResult)(id)) { - [PearlAlert showAlertWithTitle:@"Enter Old Master Password" - message:PearlString( - @"Your old master password is required to migrate the stored password for %@", - site.name ) - viewStyle:UIAlertViewStyleSecureTextInput - initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) { - if (buttonIndex_ == [alert_ cancelButtonIndex]) - setResult( nil ); - else - setResult( [alert_ textFieldAtIndex:0].text ); - } cancelTitle:@"Don't Migrate" otherTitles:@"Migrate", nil]; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Enter Old Master Password" message: + PearlString( @"Your old master password is required to migrate the stored password for %@", site.name ) + preferredStyle:UIAlertControllerStyleAlert]; + [controller addTextFieldWithConfigurationHandler:nil]; + [controller addAction:[UIAlertAction actionWithTitle:@"Migrate" style:UIAlertActionStyleDefault handler: + ^(UIAlertAction *_Nonnull action) { + setResult( controller.textFields.firstObject.text ); + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Don't Migrate" style:UIAlertActionStyleCancel handler: + ^(UIAlertAction *_Nonnull action) { + setResult( nil ); + }]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; } ); #endif if (!masterPassword) diff --git a/platform-darwin/Source/MasterPassword-Prefix.pch b/platform-darwin/Source/MasterPassword-Prefix.pch index 6797f1f0..742bd70d 100644 --- a/platform-darwin/Source/MasterPassword-Prefix.pch +++ b/platform-darwin/Source/MasterPassword-Prefix.pch @@ -51,17 +51,21 @@ #define mpw_log(level, format, ...) \ do { \ - void (*_sendMsg)(id, SEL, CFStringRef, NSInteger, CFStringRef, NSUInteger, CFStringRef) = (void *)objc_msgSend; \ char *_msg = NULL; \ asprintf( &_msg, format, ##__VA_ARGS__ ); \ - CFStringRef fileStr = CFStringCreateWithCString( NULL, basename( (char *)__FILE__ ), kCFStringEncodingUTF8 ); \ - CFStringRef funcStr = CFStringCreateWithCString( NULL, __FUNCTION__, kCFStringEncodingUTF8 ); \ - CFStringRef msgStr = CFStringCreateWithCString( NULL, _msg, kCFStringEncodingUTF8 ); \ - _sendMsg( objc_msgSend( (id)objc_getClass( "PearlLogger" ), sel_getUid( "get" ) ), \ - sel_getUid( "inFile:atLine:fromFunction:withLevel:text:" ), fileStr, __LINE__, funcStr, level, msgStr ); \ - CFRelease( fileStr ); \ - CFRelease( funcStr ); \ - CFRelease( msgStr ); \ + if (_msg) { \ + CFStringRef fileStr = CFStringCreateWithCString( NULL, basename( (char *)__FILE__ ), kCFStringEncodingUTF8 ); \ + CFStringRef funcStr = CFStringCreateWithCString( NULL, __FUNCTION__, kCFStringEncodingUTF8 ); \ + CFStringRef msgStr = CFStringCreateWithCString( NULL, _msg, kCFStringEncodingUTF8 ); \ + id (*_getLogger)(id, SEL) = (void *)objc_msgSend; \ + void (*_sendMsg)(id, SEL, CFStringRef, NSInteger, CFStringRef, NSUInteger, CFStringRef) = (void *)objc_msgSend; \ + _sendMsg( _getLogger( (id)objc_getClass( "PearlLogger" ), sel_getUid( "get" ) ), \ + sel_getUid( "inFile:atLine:fromFunction:withLevel:text:" ), fileStr, __LINE__, funcStr, level, msgStr ); \ + if (fileStr) { CFRelease( fileStr ); } \ + if (funcStr) { CFRelease( funcStr ); } \ + if (msgStr) { CFRelease( msgStr ); } \ + free(_msg); \ + } \ } while (0) #define trc(format, ...) mpw_log( 0, format, ##__VA_ARGS__ ); diff --git a/platform-darwin/Source/iOS/MPAnswersViewController.m b/platform-darwin/Source/iOS/MPAnswersViewController.m index 3e18885e..df2078e5 100644 --- a/platform-darwin/Source/iOS/MPAnswersViewController.m +++ b/platform-darwin/Source/iOS/MPAnswersViewController.m @@ -172,23 +172,24 @@ if (![site.questions count]) [self setMultiple:NO animated:YES]; - else - [PearlAlert showAlertWithTitle:@"Remove Site Questions?" message: + else { + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Remove Site Questions?" message: @"Do you want to remove the questions you have configured for this site?" - viewStyle:UIAlertViewStyleDefault initAlert:nil - tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { - if (buttonIndex == [alert cancelButtonIndex]) - return; - - [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { - MPSiteEntity *site_ = [self siteInContext:context]; - NSOrderedSet *questions = [site_.questions copy]; - for (MPSiteQuestionEntity *question in questions) - [context deleteObject:question]; - [context saveToStore]; - [self setMultiple:NO animated:YES]; - }]; - } cancelTitle:@"Cancel" otherTitles:@"Remove Questions", nil]; + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Remove Questions" style:UIAlertActionStyleDestructive handler: + ^(UIAlertAction *_Nonnull action) { + [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { + MPSiteEntity *site_ = [self siteInContext:context]; + NSOrderedSet *questions = [site_.questions copy]; + for (MPSiteQuestionEntity *question in questions) + [context deleteObject:question]; + [context saveToStore]; + [self setMultiple:NO animated:YES]; + }]; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [self presentViewController:controller animated:YES completion:nil]; + } } } @@ -197,9 +198,9 @@ if (!self.multiple) { NSObject *answer = [site resolveSiteAnswerUsingKey:[MPiOSAppDelegate get].key]; body = strf( @"Master Password generated the following security answer for your site: %@\n\n" - @"%@\n" - @"\n\nYou should use this as the answer to each security question the site asks you.\n" - @"Do not share this answer with others!", site.name, answer ); + @"%@\n" + @"\n\nYou should use this as the answer to each security question the site asks you.\n" + @"Do not share this answer with others!", site.name, answer ); } else { NSMutableString *bodyBuilder = [NSMutableString string]; @@ -209,7 +210,7 @@ [bodyBuilder appendFormat:@"For question: '%@', use answer: %@\n", question.keyword, answer]; } [bodyBuilder appendFormat:@"\n\nUse the answer for the matching security question.\n" - @"Do not share this answer with others!"]; + @"Do not share this answer with others!"]; body = bodyBuilder; } @@ -225,7 +226,7 @@ - (void)copyAnswer:(NSString *)answer { UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; - if (@available(iOS 10.0, *)) { + if (@available( iOS 10.0, * )) { [pasteboard setItems:@[ @{ UIPasteboardTypeAutomatic: answer } ] options:@{ UIPasteboardOptionLocalOnly : @NO, diff --git a/platform-darwin/Source/iOS/MPAvatarCell.m b/platform-darwin/Source/iOS/MPAvatarCell.m index 79d803d0..239ae848 100644 --- a/platform-darwin/Source/iOS/MPAvatarCell.m +++ b/platform-darwin/Source/iOS/MPAvatarCell.m @@ -228,9 +228,9 @@ const long MPAvatarAdd = 10000; case MPAvatarModeLowered: { [self.avatarSizeConstraint updateConstant: self.avatarImageView.image.size.height * (self.visibility * 0.3f + 0.7f)]; - [self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultLow]; - [self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow]; - [self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultLow]; + [self.avatarRaisedConstraint withPriority:UILayoutPriorityDefaultLow]; + [self.avatarToTopConstraint withPriority:UILayoutPriorityDefaultLow]; + [self.nameToCenterConstraint withPriority:UILayoutPriorityDefaultLow]; self.nameContainer.visible = YES; self.nameContainer.backgroundColor = [UIColor clearColor]; self.avatarImageView.visible = YES; @@ -239,9 +239,9 @@ const long MPAvatarAdd = 10000; case MPAvatarModeRaisedButInactive: { [self.avatarSizeConstraint updateConstant: self.avatarImageView.image.size.height * (self.visibility * 0.7f + 0.3f)]; - [self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultHigh]; - [self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow]; - [self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultLow]; + [self.avatarRaisedConstraint withPriority:UILayoutPriorityDefaultHigh]; + [self.avatarToTopConstraint withPriority:UILayoutPriorityDefaultLow]; + [self.nameToCenterConstraint withPriority:UILayoutPriorityDefaultLow]; self.nameContainer.visible = YES; self.nameContainer.backgroundColor = [UIColor clearColor]; self.avatarImageView.visible = NO; @@ -250,9 +250,9 @@ const long MPAvatarAdd = 10000; case MPAvatarModeRaisedAndActive: { [self.avatarSizeConstraint updateConstant: self.avatarImageView.image.size.height * (self.visibility * 0.7f + 0.3f)]; - [self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultHigh]; - [self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow]; - [self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh]; + [self.avatarRaisedConstraint withPriority:UILayoutPriorityDefaultHigh]; + [self.avatarToTopConstraint withPriority:UILayoutPriorityDefaultLow]; + [self.nameToCenterConstraint withPriority:UILayoutPriorityDefaultHigh]; self.nameContainer.visible = YES; self.nameContainer.backgroundColor = [UIColor blackColor]; self.avatarImageView.visible = YES; @@ -261,9 +261,9 @@ const long MPAvatarAdd = 10000; case MPAvatarModeRaisedAndHidden: { [self.avatarSizeConstraint updateConstant: self.avatarImageView.image.size.height * (self.visibility * 0.7f + 0.3f)]; - [self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultHigh]; - [self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow]; - [self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh]; + [self.avatarRaisedConstraint withPriority:UILayoutPriorityDefaultHigh]; + [self.avatarToTopConstraint withPriority:UILayoutPriorityDefaultLow]; + [self.nameToCenterConstraint withPriority:UILayoutPriorityDefaultHigh]; self.nameContainer.visible = NO; self.nameContainer.backgroundColor = [UIColor blackColor]; self.avatarImageView.visible = NO; @@ -271,9 +271,9 @@ const long MPAvatarAdd = 10000; } case MPAvatarModeRaisedAndMinimized: { [self.avatarSizeConstraint updateConstant:36]; - [self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultLow]; - [self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultHigh + 2]; - [self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh]; + [self.avatarRaisedConstraint withPriority:UILayoutPriorityDefaultLow]; + [self.avatarToTopConstraint withPriority:UILayoutPriorityDefaultHigh + 2]; + [self.nameToCenterConstraint withPriority:UILayoutPriorityDefaultHigh]; self.nameContainer.visible = NO; self.nameContainer.backgroundColor = [UIColor blackColor]; self.avatarImageView.visible = YES; diff --git a/platform-darwin/Source/iOS/MPLogsViewController.m b/platform-darwin/Source/iOS/MPLogsViewController.m index 142eea85..01d5f87b 100644 --- a/platform-darwin/Source/iOS/MPLogsViewController.m +++ b/platform-darwin/Source/iOS/MPLogsViewController.m @@ -56,16 +56,15 @@ BOOL traceEnabled = (BOOL)self.levelControl.selectedSegmentIndex; if (traceEnabled) { - [PearlAlert showAlertWithTitle:@"Enable Trace Mode?" message: - @"Trace mode will log the internal operation of the application.\n" - @"Unless you're looking for the cause of a problem, you should leave this off to save memory." - viewStyle:UIAlertViewStyleDefault initAlert:nil - tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { - if (buttonIndex == [alert cancelButtonIndex]) - return; - - [MPiOSConfig get].traceMode = @YES; - } cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Enable Trace", nil]; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Enable Trace Mode?" message: + @"Trace mode will log the internal operation of the application.\n" + @"Unless you're looking for the cause of a problem, you should leave this off to save memory." + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Enable Trace" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [MPiOSConfig get].traceMode = @YES; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [self presentViewController:controller animated:YES completion:nil]; } else [MPiOSConfig get].traceMode = @NO; @@ -79,13 +78,14 @@ - (IBAction)mail:(UIBarButtonItem *)sender { if ([[MPiOSConfig get].traceMode boolValue]) { - [PearlAlert showAlertWithTitle:@"Hiding Trace Messages" message: - @"Trace-level log messages will not be mailed. " - @"These messages contain sensitive and personal information." - viewStyle:UIAlertViewStyleDefault initAlert:nil - tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { - [[MPiOSAppDelegate get] openFeedbackWithLogs:YES forVC:self]; - } cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil]; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Hiding Trace Messages" message: + @"Trace-level log messages will not be mailed. " + @"These messages contain sensitive and personal information." + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { + [[MPiOSAppDelegate get] openFeedbackWithLogs:YES forVC:self]; + }]]; + [self presentViewController:controller animated:YES completion:nil]; } else [[MPiOSAppDelegate get] openFeedbackWithLogs:YES forVC:self]; diff --git a/platform-darwin/Source/iOS/MPPopdownSegue.m b/platform-darwin/Source/iOS/MPPopdownSegue.m index d6a07671..3546a67f 100644 --- a/platform-darwin/Source/iOS/MPPopdownSegue.m +++ b/platform-darwin/Source/iOS/MPPopdownSegue.m @@ -41,7 +41,7 @@ [UIView animateWithDuration:0.6f delay:0 usingSpringWithDamping:0.75f initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseOut animations:^{ - [[passwordsVC.popdownToTopConstraint updatePriority:1] layoutIfNeeded]; + [[passwordsVC.popdownToTopConstraint withPriority:1] layoutIfNeeded]; } completion:^(BOOL finished) { [popdownVC didMoveToParentViewController:passwordsVC]; @@ -63,7 +63,7 @@ [popdownVC willMoveToParentViewController:nil]; [UIView animateWithDuration:0.4f delay:0 options:UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionOverrideInheritedDuration animations:^{ - [[passwordsVC.popdownToTopConstraint updatePriority:UILayoutPriorityDefaultHigh] layoutIfNeeded]; + [[passwordsVC.popdownToTopConstraint withPriority:UILayoutPriorityDefaultHigh] layoutIfNeeded]; } completion:^(BOOL finished) { [popdownVC.view removeFromSuperview]; [popdownVC removeFromParentViewController]; diff --git a/platform-darwin/Source/iOS/MPPreferencesViewController.m b/platform-darwin/Source/iOS/MPPreferencesViewController.m index 37781e8c..fa800617 100644 --- a/platform-darwin/Source/iOS/MPPreferencesViewController.m +++ b/platform-darwin/Source/iOS/MPPreferencesViewController.m @@ -114,11 +114,13 @@ if (cell == self.checkInconsistencies) [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { - if ([[MPiOSAppDelegate get] findAndFixInconsistenciesSaveInContext:context] == MPFixableResultNoProblems) - [PearlAlert showAlertWithTitle:@"No Inconsistencies" message: + if ([[MPiOSAppDelegate get] findAndFixInconsistenciesSaveInContext:context] == MPFixableResultNoProblems) { + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"No Inconsistencies" message: @"No inconsistencies were detected in your sites." - viewStyle:UIAlertViewStyleDefault initAlert:nil - tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil]; + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleDefault handler:nil]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; + } }]; [tableView deselectRowAtIndexPath:indexPath animated:YES]; diff --git a/platform-darwin/Source/iOS/MPSiteCell.m b/platform-darwin/Source/iOS/MPSiteCell.m index b0d690dd..4afbd8f7 100644 --- a/platform-darwin/Source/iOS/MPSiteCell.m +++ b/platform-darwin/Source/iOS/MPSiteCell.m @@ -261,19 +261,20 @@ if (!site) return; - [PearlSheet showSheetWithTitle:strf( @"Delete %@?", site.name ) viewStyle:UIActionSheetStyleAutomatic - initSheet:nil tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) { - if (buttonIndex == [sheet cancelButtonIndex]) - return; - - [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { - MPSiteEntity *site_ = [self siteInContext:context]; - if (site_) { - [context deleteObject:site_]; - [context saveToStore]; - } - }]; - } cancelTitle:@"Cancel" destructiveTitle:@"Delete Site" otherTitles:nil]; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:strf( @"Delete %@?", site.name ) message:nil + preferredStyle:UIAlertControllerStyleActionSheet]; + [controller addAction:[UIAlertAction actionWithTitle:@"Delete Site" style:UIAlertActionStyleDestructive + handler:^(UIAlertAction *_Nonnull action) { + [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { + MPSiteEntity *site_ = [self siteInContext:context]; + if (site_) { + [context deleteObject:site_]; + [context saveToStore]; + } + }]; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [UIApp.keyWindow.rootViewController presentViewController:controller animated:YES completion:nil]; } - (IBAction)doChangeType:(UIButton *)sender { @@ -281,29 +282,24 @@ [self setMode:MPPasswordCellModePassword animated:YES]; MPSiteEntity *mainSite = [self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]]; - [PearlSheet showSheetWithTitle:@"Change Password Type" viewStyle:UIActionSheetStyleAutomatic - initSheet:^(UIActionSheet *sheet) { - for (NSNumber *typeNumber in [mainSite.algorithm allTypes]) { - MPResultType type = (MPResultType)[typeNumber unsignedIntegerValue]; - NSString *typeName = [mainSite.algorithm nameOfType:type]; - if (type == mainSite.type) - [sheet addButtonWithTitle:strf( @"● %@", typeName )]; - else - [sheet addButtonWithTitle:typeName]; - } - } tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) { - if (buttonIndex == [sheet cancelButtonIndex]) - return; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Change Password Type" message:nil + preferredStyle:UIAlertControllerStyleActionSheet]; + for (NSNumber *typeNumber in [mainSite.algorithm allTypes]) { + MPResultType type = (MPResultType)[typeNumber unsignedIntegerValue]; + NSString *typeName = [mainSite.algorithm nameOfType:type]; + NSString *title = type == mainSite.type? strf( @"● %@", typeName ): typeName; - MPResultType type = (MPResultType)[[mainSite.algorithm allTypes][buttonIndex] unsignedIntegerValue]?: - mainSite.user.defaultType?: mainSite.algorithm.defaultType; - - [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { - MPSiteEntity *site = [self siteInContext:context]; - site = [[MPiOSAppDelegate get] changeSite:site saveInContext:context toType:type]; - [self setSite:site animated:YES]; - }]; - } cancelTitle:@"Cancel" destructiveTitle:nil otherTitles:nil]; + [controller addAction:[UIAlertAction actionWithTitle:title style:UIAlertActionStyleDefault handler: + ^(UIAlertAction *_Nonnull action) { + [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { + MPSiteEntity *site = [self siteInContext:context]; + site = [[MPiOSAppDelegate get] changeSite:site saveInContext:context toType:type]; + [self setSite:site animated:YES]; + }]; + }]]; + } + [controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [UIApp.keyWindow.rootViewController presentViewController:controller animated:YES completion:nil]; } - (IBAction)doEdit:(UIButton *)sender { @@ -370,24 +366,23 @@ [MPiOSAppDelegate managedObjectContextForMainThreadPerformBlock:^(NSManagedObjectContext *mainContext) { MPSiteEntity *mainSite = [self siteInContext:mainContext]; - [PearlAlert showAlertWithTitle:@"Login Page" message:nil - viewStyle:UIAlertViewStylePlainTextInput - initAlert:^(UIAlertView *alert, UITextField *firstField) { - firstField.placeholder = strf( @"Login URL for %@", mainSite.name ); - firstField.text = mainSite.url; - } - tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { - if (buttonIndex == alert.cancelButtonIndex) - return; - - [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { - MPSiteEntity *site = [self siteInContext:context]; - NSURL *url = [NSURL URLWithString:[alert textFieldAtIndex:0].text]; - site.url = [url.host? url: nil absoluteString]; - [context saveToStore]; - }]; - } - cancelTitle:@"Cancel" otherTitles:@"Save", nil]; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Login Page" message:nil + preferredStyle:UIAlertControllerStyleAlert]; + [controller addTextFieldWithConfigurationHandler:^(UITextField *textField) { + textField.placeholder = strf( @"Login URL for %@", mainSite.name ); + textField.text = mainSite.url; + }]; + [controller addAction:[UIAlertAction actionWithTitle:@"Save" style:UIAlertActionStyleDefault + handler:^(UIAlertAction *_Nonnull action) { + [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { + MPSiteEntity *site = [self siteInContext:context]; + NSURL *url = [NSURL URLWithString:controller.textFields.firstObject.text]; + site.url = [url.host? url: nil absoluteString]; + [context saveToStore]; + }]; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [UIApp.keyWindow.rootViewController presentViewController:controller animated:YES completion:nil]; }]; } @@ -446,15 +441,11 @@ if (self.transientSite) { [[UIResponder findFirstResponder] resignFirstResponder]; - [PearlAlert showAlertWithTitle:@"Create Site" - message:strf( @"Remember site named:\n%@", self.transientSite ) - viewStyle:UIAlertViewStyleDefault - initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { - if (buttonIndex == [alert cancelButtonIndex]) { - self.contentButton.selected = NO; - return; - } - + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Create Site" message: + strf( @"Remember site named:\n%@", self.transientSite ) + preferredStyle:UIAlertControllerStyleActionSheet]; + [controller addAction:[UIAlertAction actionWithTitle:@"Yes" style:UIAlertActionStyleDefault handler: + ^(UIAlertAction *_Nonnull action) { [[MPiOSAppDelegate get] addSiteNamed:self.transientSite completion:^(MPSiteEntity *site, NSManagedObjectContext *context) { [self copyContentOfSite:site saveInContext:context]; @@ -465,7 +456,11 @@ }]; } ); }]; - } cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonYes, nil]; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { + self.contentButton.selected = NO; + }]]; + [UIApp.keyWindow.rootViewController presentViewController:controller animated:YES completion:nil]; return; } @@ -677,7 +672,7 @@ [self.window endEditing:YES]; UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; - if (@available(iOS 10.0, *)) { + if (@available( iOS 10.0, * )) { [pasteboard setItems:@[ @{ UIPasteboardTypeAutomatic: password } ] options:@{ UIPasteboardOptionLocalOnly : @NO, diff --git a/platform-darwin/Source/iOS/MPSitesViewController.m b/platform-darwin/Source/iOS/MPSitesViewController.m index f569c318..b4aca7c3 100644 --- a/platform-darwin/Source/iOS/MPSitesViewController.m +++ b/platform-darwin/Source/iOS/MPSitesViewController.m @@ -447,8 +447,8 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) { _active = active; [UIView animateWithDuration:animated? 0.4f: 0 animations:^{ - [self.navigationBarToTopConstraint updatePriority:active? 1: UILayoutPriorityDefaultHigh]; - [self.sitesToBottomConstraint updatePriority:active? 1: UILayoutPriorityDefaultHigh]; + [self.navigationBarToTopConstraint withPriority:active? 1: UILayoutPriorityDefaultHigh]; + [self.sitesToBottomConstraint withPriority:active? 1: UILayoutPriorityDefaultHigh]; [self.view layoutIfNeeded]; } completion:completion]; } diff --git a/platform-darwin/Source/iOS/MPStoreViewController.m b/platform-darwin/Source/iOS/MPStoreViewController.m index 8dbb5dd9..da28da34 100644 --- a/platform-darwin/Source/iOS/MPStoreViewController.m +++ b/platform-darwin/Source/iOS/MPStoreViewController.m @@ -146,15 +146,14 @@ PearlEnum( MPDevelopmentFuelConsumption, - (IBAction)restorePurchases:(id)sender { - [PearlAlert showAlertWithTitle:@"Restore Previous Purchases" message: + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Restore Previous Purchases" message: @"This will check with Apple to find and activate any purchases you made from other devices." - viewStyle:UIAlertViewStyleDefault initAlert:nil - tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { - if (buttonIndex == [alert cancelButtonIndex]) - return; - - [[MPAppDelegate_Shared get] restoreCompletedTransactions]; - } cancelTitle:@"Cancel" otherTitles:@"Find Purchases", nil]; + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Find Purchases" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [[MPAppDelegate_Shared get] restoreCompletedTransactions]; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [self presentViewController:controller animated:YES completion:nil]; } - (IBAction)sendThanks:(id)sender { diff --git a/platform-darwin/Source/iOS/MPUsersViewController.m b/platform-darwin/Source/iOS/MPUsersViewController.m index 1f66a530..d547877e 100644 --- a/platform-darwin/Source/iOS/MPUsersViewController.m +++ b/platform-darwin/Source/iOS/MPUsersViewController.m @@ -432,33 +432,27 @@ referenceSizeForFooterInSection:(NSInteger)section { return; NSManagedObjectID *userID = user.permanentObjectID; - [PearlSheet showSheetWithTitle:user.name - viewStyle:UIActionSheetStyleBlackTranslucent - initSheet:nil tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) { - if (buttonIndex == [sheet cancelButtonIndex]) - return; - - if (buttonIndex == [sheet destructiveButtonIndex]) { - // Delete User - [PearlAlert showParentalGateWithTitle:@"Deleting User" message: - @"The user and its sites will be deleted.\nPlease confirm by solving:" - completion:^(BOOL continuing) { - if (continuing) - [self deleteUser:userID]; - }]; - return; - } - - if (buttonIndex == [sheet firstOtherButtonIndex]) - // Reset Password - [PearlAlert showParentalGateWithTitle:@"Resetting User" message: - @"The user's master password will be reset.\nPlease confirm by solving:" - completion:^(BOOL continuing) { - if (continuing) - [self resetUser:userID avatar:avatarCell]; - }]; - } cancelTitle:[PearlStrings get].commonButtonCancel - destructiveTitle:@"Delete User" otherTitles:@"Reset Password", nil]; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:user.name message:nil preferredStyle:UIAlertControllerStyleActionSheet]; + [controller addAction:[UIAlertAction actionWithTitle:@"Delete User" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Deleting User" message: + @"The user and its sites will be deleted." preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Delete User" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { + [self deleteUser:userID]; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [self presentViewController:controller animated:YES completion:nil]; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Reset Password" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Resetting User" message: + @"The user's master password will be reset." preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Reset User" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { + [self resetUser:userID avatar:avatarCell]; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [self presentViewController:controller animated:YES completion:nil]; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [self presentViewController:controller animated:YES completion:nil]; } } diff --git a/platform-darwin/Source/iOS/MPiOSAppDelegate.m b/platform-darwin/Source/iOS/MPiOSAppDelegate.m index 68f451a7..1b528a4d 100644 --- a/platform-darwin/Source/iOS/MPiOSAppDelegate.m +++ b/platform-darwin/Source/iOS/MPiOSAppDelegate.m @@ -110,20 +110,24 @@ case MPFixableResultNoProblems: break; - case MPFixableResultProblemsFixed: - [PearlAlert showAlertWithTitle:@"Inconsistencies Fixed" message: + case MPFixableResultProblemsFixed: { + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Inconsistencies Fixed" message: @"Some inconsistencies were detected in your sites.\n" - @"All issues were fixed." - viewStyle:UIAlertViewStyleDefault initAlert:nil - tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil]; + @"All issues were fixed." + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]]; + [self presentViewController:controller animated:YES completion:nil]; break; - case MPFixableResultProblemsNotFixed: - [PearlAlert showAlertWithTitle:@"Inconsistencies Found" message: + } + case MPFixableResultProblemsNotFixed: { + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Inconsistencies Found" message: @"Some inconsistencies were detected in your sites.\n" - @"Not all issues could be fixed. Try signing in to each user or checking the logs." - viewStyle:UIAlertViewStyleDefault initAlert:nil - tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil]; + @"Not all issues could be fixed. Try signing in to each user or checking the logs." + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]]; + [self presentViewController:controller animated:YES completion:nil]; break; + } } } ); @@ -133,12 +137,14 @@ } ); NSString *latestFeatures = [MPStoreViewController latestStoreFeatures]; - if (latestFeatures) - [PearlAlert showAlertWithTitle:@"New Features" message: + if (latestFeatures) { + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"New Features" message: strf( @"The following features are now available in the store:\n\n%@•••\n\n" - @"Find the store from the user pull‑down after logging in.", latestFeatures ) - viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock:nil - cancelTitle:@"Thanks" otherTitles:nil]; + @"Find the store from the user pull‑down after logging in.", latestFeatures ) + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Thanks" style:UIAlertActionStyleCancel handler:nil]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; + } } @catch (id exception) { err( @"During Post-Startup: %@", exception ); @@ -161,14 +167,22 @@ MPError( error, @"While reading imported sites from %@.", url ); if (!importedSitesData) { - [PearlAlert showError:strf( @"Master Password couldn't read the import sites.\n\n%@", - [error localizedDescription]?: error )]; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Error" message: + strf( @"Master Password couldn't read the import sites.\n\n%@", + (id)[error localizedDescription]?: error ) + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; return; } NSString *importedSitesString = [[NSString alloc] initWithData:importedSitesData encoding:NSUTF8StringEncoding]; if (!importedSitesString) { - [PearlAlert showError:@"Master Password couldn't understand the import file."]; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Error" message: + @"Master Password couldn't understand the import file." + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; return; } @@ -190,33 +204,45 @@ PearlOverlay *activityOverlay = [PearlOverlay showProgressOverlayWithTitle:@"Importing"]; [self importSites:importData askImportPassword:^NSString *(NSString *userName) { return PearlAwait( ^(void (^setResult)(id)) { - [PearlAlert showAlertWithTitle:strf( @"Importing Sites For\n%@", userName ) - message:@"Enter the master password used to create this export file." - viewStyle:UIAlertViewStyleSecureTextInput - initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) { - if (buttonIndex_ == [alert_ cancelButtonIndex]) - setResult( nil ); - else - setResult( [alert_ textFieldAtIndex:0].text ); - } cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Import", nil]; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:strf( @"Importing Sites For\n%@", userName ) message: + @"Enter the master password used to create this export file." + preferredStyle:UIAlertControllerStyleAlert]; + [controller addTextFieldWithConfigurationHandler:^(UITextField *textField) { + textField.secureTextEntry = YES; + }]; + [controller addAction:[UIAlertAction actionWithTitle:@"Import" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + setResult( controller.textFields.firstObject.text ); + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { + setResult( nil ); + }]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; } ); } askUserPassword:^NSString *(NSString *userName) { return PearlAwait( (id)^(void (^setResult)(id)) { - [PearlAlert showAlertWithTitle:strf( @"Master Password For\n%@", userName ) - message:@"Enter the current master password for this user." - viewStyle:UIAlertViewStyleSecureTextInput - initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) { - if (buttonIndex_ == [alert_ cancelButtonIndex]) - setResult( nil ); - else - setResult( [alert_ textFieldAtIndex:0].text ); - } cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Import", nil]; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:strf( @"Master Password For\n%@", userName ) message: + @"Enter the current master password for this user." + preferredStyle:UIAlertControllerStyleAlert]; + [controller addTextFieldWithConfigurationHandler:^(UITextField *textField) { + textField.secureTextEntry = YES; + }]; + [controller addAction:[UIAlertAction actionWithTitle:@"Import" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + setResult( controller.textFields.firstObject.text ); + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { + setResult( nil ); + }]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; } ); } result:^(NSError *error) { [activityOverlay cancelOverlayAnimated:YES]; - if (error && !(error.domain == NSCocoaErrorDomain && error.code == NSUserCancelledError)) - [PearlAlert showError:error.localizedDescription]; + if (error && !(error.domain == NSCocoaErrorDomain && error.code == NSUserCancelledError)) { + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Error" message:[error localizedDescription] + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; + } }]; } @@ -237,17 +263,17 @@ PearlNotMainQueue( ^{ NSString *importData = [UIPasteboard generalPasteboard].string; MPMarshalInfo *importInfo = mpw_marshal_read_info( importData.UTF8String ); - if (importInfo->format != MPMarshalFormatNone) - [PearlAlert showAlertWithTitle:@"Import Sites?" message: + if (importInfo->format != MPMarshalFormatNone) { + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Import Sites?" message: @"We've detected Master Password import sites on your pasteboard, would you like to import them?" - viewStyle:UIAlertViewStyleDefault initAlert:nil - tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { - if (buttonIndex == [alert cancelButtonIndex]) - return; - - [self importSites:importData]; - [UIPasteboard generalPasteboard].string = @""; - } cancelTitle:@"No" otherTitles:@"Import Sites", nil]; + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Import Sites" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [self importSites:importData]; + [UIPasteboard generalPasteboard].string = @""; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"No" style:UIAlertActionStyleCancel handler:nil]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; + } mpw_marshal_info_free( &importInfo ); } ); @@ -314,26 +340,29 @@ - (void)showFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController { - if (![PearlEMail canSendMail]) - [PearlAlert showAlertWithTitle:@"Feedback" - message: - @"Have a question, comment, issue or just saying thanks?\n\n" - @"We'd love to hear what you think!\n" - @"masterpassword@lyndir.com" - viewStyle:UIAlertViewStyleDefault - initAlert:nil tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay - otherTitles:nil]; - - else if (logs) - [PearlAlert showAlertWithTitle:@"Feedback" - message: - @"Have a question, comment, issue or just saying thanks?\n\n" - @"If you're having trouble, it may help us if you can first reproduce the problem " - @"and then include log files in your message." - viewStyle:UIAlertViewStyleDefault - initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) { - [self openFeedbackWithLogs:(buttonIndex_ == [alert_ firstOtherButtonIndex]) forVC:viewController]; - } cancelTitle:nil otherTitles:@"Include Logs", @"No Logs", nil]; + if (![PearlEMail canSendMail]) { + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Feedback" message: + @"Have a question, comment, issue or just saying thanks?\n\n" + @"We'd love to hear what you think!\n" + @"masterpassword@lyndir.com" + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; + } + else if (logs) { + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Feedback" message: + @"Have a question, comment, issue or just saying thanks?\n\n" + @"If you're having trouble, it may help us if you can first reproduce the problem " + @"and then include log files in your message." + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Include Logs" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + [self openFeedbackWithLogs:YES forVC:viewController]; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"No Logs" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + [self openFeedbackWithLogs:NO forVC:viewController]; + }]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; + } else [self openFeedbackWithLogs:NO forVC:viewController]; } @@ -349,9 +378,9 @@ subject:strf( @"Feedback for Master Password [%@]", [[PearlKeyChain deviceIdentifier] stringByDeletingMatchesOf:@"-.*"] ) body:strf( @"\n\n\n" - @"--\n" - @"%@" - @"Master Password %@, build %@", + @"--\n" + @"%@" + @"Master Password %@, build %@", userName? ([userName stringByAppendingString:@"\n"]): @"", [PearlInfoPlist get].CFBundleShortVersionString, [PearlInfoPlist get].CFBundleVersion ) @@ -372,173 +401,163 @@ static dispatch_once_t once = 0; dispatch_once( &once, ^{ - [PearlAlert showAlertWithTitle:@"Failed To Load Sites" message: + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Failed To Load Sites" message: @"Master Password was unable to open your sites history.\n" - @"This may be due to corruption. You can either reset Master Password and " - @"recreate your user, or E-Mail us your logs and leave your corrupt store as-is for now." - viewStyle:UIAlertViewStyleDefault initAlert:nil - tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { - if (buttonIndex == [alert cancelButtonIndex]) - return; - if (buttonIndex == [alert firstOtherButtonIndex]) - [self openFeedbackWithLogs:YES forVC:nil]; - if (buttonIndex == [alert firstOtherButtonIndex] + 1) - [self deleteAndResetStore]; - } cancelTitle:@"Ignore" otherTitles:@"E-Mail Logs", @"Reset", nil]; + @"This may be due to corruption. You can either reset Master Password and " + @"recreate your user, or E-Mail us your logs and leave your corrupt store as-is for now." + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"E-Mail Logs" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + [self openFeedbackWithLogs:YES forVC:nil]; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Reset" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + [self deleteAndResetStore]; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Ignore" style:UIAlertActionStyleCancel handler:nil]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; } ); } - (void)showExportForVC:(UIViewController *)viewController { - [PearlAlert showAlertWithTitle:@"Exporting Your Sites" - message:@"An export is great for keeping a " - @"backup list of your accounts.\n\n" - @"When the file is ready, you will be " - @"able to mail it to yourself.\n" - @"You can open it with a text editor or " - @"with Master Password if you need to " - @"restore your list of sites." - viewStyle:UIAlertViewStyleDefault initAlert:nil - tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { - if (buttonIndex != [alert cancelButtonIndex]) - [PearlAlert showAlertWithTitle:@"Show Passwords?" - message:@"Would you like to make all your passwords " - @"visible in the export file?\n\n" - @"A safe export will include all sites " - @"but make their passwords invisible.\n" - @"It is great as a backup and remains " - @"safe when fallen in the wrong hands." - viewStyle:UIAlertViewStyleDefault initAlert:nil - tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) { - if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 0) - // Safe Export - [self showExportRevealPasswords:NO forVC:viewController]; - if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 1) - // Show Passwords - [self showExportRevealPasswords:YES forVC:viewController]; - } cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Safe Export", @"Show Passwords", - nil]; - } cancelTitle:@"Cancel" otherTitles:@"Export Sites", nil]; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Exporting Your Sites" message: + @"An export is great for keeping a backup list of your accounts.\n\n" + @"When the file is ready, you will be able to mail it to yourself.\n" + @"You can open it with a text editor or with Master Password if you need to restore your list of sites." + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Export Sites" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + UIAlertController *controller_ = [UIAlertController alertControllerWithTitle:@"Show Passwords?" message: + @"Would you like to make all your passwords visible in the export file?\n\n" + @"A safe export will include all sites but make their passwords invisible.\n" + @"It is great as a backup and remains safe when fallen in the wrong hands." + preferredStyle:UIAlertControllerStyleAlert]; + [controller_ addAction:[UIAlertAction actionWithTitle:@"Safe Export" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + [self showExportRevealPasswords:NO forVC:viewController]; + }]]; + [controller_ addAction:[UIAlertAction actionWithTitle:@"Show Passwords" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + [self showExportRevealPasswords:YES forVC:viewController]; + }]]; + [controller_ addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [self.navigationController presentViewController:controller_ animated:YES completion:nil]; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; } - (void)showExportRevealPasswords:(BOOL)revealPasswords forVC:(UIViewController *)viewController { if (![PearlEMail canSendMail]) { - [PearlAlert showAlertWithTitle:@"Cannot Send Mail" - message: - @"Your device is not yet set up for sending mail.\n" - @"Close Master Password, go into Settings and add a Mail account." - viewStyle:UIAlertViewStyleDefault - initAlert:nil tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay - otherTitles:nil]; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Cannot Send Mail" message: + @"Your device is not yet set up for sending mail.\n" + @"Close Master Password, go into Settings and add a Mail account." + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; return; } [self exportSitesRevealPasswords:revealPasswords askExportPassword:^NSString *(NSString *userName) { return PearlAwait( ^(void (^setResult)(id)) { - [PearlAlert showAlertWithTitle:strf( @"Master Password For:\n%@", userName ) - message:@"Enter the user's master password to create an export file." - viewStyle:UIAlertViewStyleSecureTextInput - initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) { - if (buttonIndex_ == [alert_ cancelButtonIndex]) - setResult( nil ); - else - setResult( [alert_ textFieldAtIndex:0].text ); - } cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Export", nil]; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:strf( @"Master Password For:\n%@", userName ) message: + @"Enter the user's master password to create an export file." + preferredStyle:UIAlertControllerStyleAlert]; + [controller addTextFieldWithConfigurationHandler:^(UITextField *textField) { + textField.secureTextEntry = YES; + }]; + [controller addAction:[UIAlertAction actionWithTitle:@"Export" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + setResult( controller.textFields.firstObject.text ); + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { + setResult( nil ); + }]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; } ); } result:^(NSString *mpsites, NSError *error) { if (!mpsites || error) { MPError( error, @"Failed to export mpsites." ); - [PearlAlert showAlertWithTitle:@"Export Error" - message:error.localizedDescription - viewStyle:UIAlertViewStyleDefault - initAlert:nil tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay - otherTitles:nil]; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Export Error" message:[error localizedDescription] + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; return; } - [PearlSheet showSheetWithTitle:@"Export Destination" viewStyle:UIActionSheetStyleBlackTranslucent initSheet:nil - tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) { - if (buttonIndex == [sheet cancelButtonIndex]) - return; + NSDateFormatter *exportDateFormatter = [NSDateFormatter new]; + [exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"]; + NSString *exportFileName = strf( @"%@ (%@).mpsites", + [self activeUserForMainThread].name, [exportDateFormatter stringFromDate:[NSDate date]] ); - NSDateFormatter *exportDateFormatter = [NSDateFormatter new]; - [exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"]; - NSString *exportFileName = strf( @"%@ (%@).mpsites", - [self activeUserForMainThread].name, [exportDateFormatter stringFromDate:[NSDate date]] ); + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Export Destination" message:nil + preferredStyle:UIAlertControllerStyleActionSheet]; + [controller addAction:[UIAlertAction actionWithTitle:@"Send As E-Mail" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + NSString *message; + if (revealPasswords) + message = strf( @"Export of Master Password sites with passwords included.\n\n" + @"REMINDER: Make sure nobody else sees this file! Passwords are visible!\n\n\n" + @"--\n" + @"%@\n" + @"Master Password %@, build %@", + [self activeUserForMainThread].name, + [PearlInfoPlist get].CFBundleShortVersionString, + [PearlInfoPlist get].CFBundleVersion ); + else + message = strf( @"Backup of Master Password sites.\n\n\n" + @"--\n" + @"%@\n" + @"Master Password %@, build %@", + [self activeUserForMainThread].name, + [PearlInfoPlist get].CFBundleShortVersionString, + [PearlInfoPlist get].CFBundleVersion ); - if (buttonIndex == [sheet firstOtherButtonIndex]) { - NSString *message; - if (revealPasswords) - message = strf( @"Export of Master Password sites with passwords included.\n\n" - @"REMINDER: Make sure nobody else sees this file! Passwords are visible!\n\n\n" - @"--\n" - @"%@\n" - @"Master Password %@, build %@", - [self activeUserForMainThread].name, - [PearlInfoPlist get].CFBundleShortVersionString, - [PearlInfoPlist get].CFBundleVersion ); - else - message = strf( @"Backup of Master Password sites.\n\n\n" - @"--\n" - @"%@\n" - @"Master Password %@, build %@", - [self activeUserForMainThread].name, - [PearlInfoPlist get].CFBundleShortVersionString, - [PearlInfoPlist get].CFBundleVersion ); - - [PearlEMail sendEMailTo:nil fromVC:viewController subject:@"Master Password Export" body:message - attachments:[[PearlEMailAttachment alloc] - initWithContent:[mpsites dataUsingEncoding:NSUTF8StringEncoding] - mimeType:@"text/plain" fileName:exportFileName], - nil]; - return; - } - - NSURL *applicationSupportURL = [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory - inDomains:NSUserDomainMask] lastObject]; - NSURL *exportURL = [[applicationSupportURL - URLByAppendingPathComponent:[NSBundle mainBundle].bundleIdentifier isDirectory:YES] - URLByAppendingPathComponent:exportFileName isDirectory:NO]; - NSError *writeError = nil; - if (![[mpsites dataUsingEncoding:NSUTF8StringEncoding] - writeToURL:exportURL options:NSDataWritingFileProtectionComplete error:&writeError]) - MPError( writeError, @"Failed to write export data to URL %@.", exportURL ); - else { - self.interactionController = [UIDocumentInteractionController interactionControllerWithURL:exportURL]; - self.interactionController.UTI = @"com.lyndir.masterpassword.sites"; - self.interactionController.delegate = self; - [self.interactionController presentOpenInMenuFromRect:CGRectZero inView:viewController.view animated:YES]; - } - } cancelTitle:@"Cancel" destructiveTitle:nil otherTitles:@"Send As E-Mail", @"Share / Airdrop", nil]; + [PearlEMail sendEMailTo:nil fromVC:viewController subject:@"Master Password Export" body:message + attachments:[[PearlEMailAttachment alloc] + initWithContent:[mpsites dataUsingEncoding:NSUTF8StringEncoding] + mimeType:@"text/plain" fileName:exportFileName], + nil]; + return; + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Share / Airdrop" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + NSURL *applicationSupportURL = [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory + inDomains:NSUserDomainMask] lastObject]; + NSURL *exportURL = [[applicationSupportURL + URLByAppendingPathComponent:[NSBundle mainBundle].bundleIdentifier isDirectory:YES] + URLByAppendingPathComponent:exportFileName isDirectory:NO]; + NSError *writeError = nil; + if (![[mpsites dataUsingEncoding:NSUTF8StringEncoding] + writeToURL:exportURL options:NSDataWritingFileProtectionComplete error:&writeError]) + MPError( writeError, @"Failed to write export data to URL %@.", exportURL ); + else { + self.interactionController = [UIDocumentInteractionController interactionControllerWithURL:exportURL]; + self.interactionController.UTI = @"com.lyndir.masterpassword.sites"; + self.interactionController.delegate = self; + [self.interactionController presentOpenInMenuFromRect:CGRectZero inView:viewController.view animated:YES]; + } + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; }]; } - (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void ( ^ )(void))didReset { - [PearlAlert showAlertWithTitle:@"Changing Master Password" - message: - @"If you continue, you'll be able to set a new master password.\n\n" - @"Changing your master password will cause all your generated passwords to change!\n" - @"Changing the master password back to the old one will cause your passwords to revert as well." - viewStyle:UIAlertViewStyleDefault - initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { - if (buttonIndex == [alert cancelButtonIndex]) - return; + UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Changing Master Password" message: + @"If you continue, you'll be able to set a new master password.\n\n" + @"Changing your master password will cause all your generated passwords to change!\n" + @"Changing the master password back to the old one will cause your passwords to revert as well." + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:@"Abort" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + [moc performBlockAndWait:^{ + inf( @"Clearing keyID for user: %@.", user.userID ); + user.keyID = nil; + [self forgetSavedKeyFor:user]; + [moc saveToStore]; + }]; - [moc performBlockAndWait:^{ - inf( @"Clearing keyID for user: %@.", user.userID ); - user.keyID = nil; - [self forgetSavedKeyFor:user]; - [moc saveToStore]; - }]; - - [self signOutAnimated:YES]; - if (didReset) - didReset(); - } - cancelTitle:[PearlStrings get].commonButtonAbort - otherTitles:[PearlStrings get].commonButtonContinue, nil]; + [self signOutAnimated:YES]; + if (didReset) + didReset(); + }]]; + [controller addAction:[UIAlertAction actionWithTitle:@"Abort" style:UIAlertActionStyleCancel handler:nil]]; + [self.navigationController presentViewController:controller animated:YES completion:nil]; } #pragma mark - UIDocumentInteractionControllerDelegate diff --git a/platform-darwin/Source/iOS/MasterPassword-Info.plist b/platform-darwin/Source/iOS/MasterPassword-Info.plist index 07ba1a85..bfd1e7d4 100644 --- a/platform-darwin/Source/iOS/MasterPassword-Info.plist +++ b/platform-darwin/Source/iOS/MasterPassword-Info.plist @@ -1,133 +1,135 @@ - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - M. Password - CFBundleDocumentTypes - - - CFBundleTypeExtensions - - mpsites - - CFBundleTypeIconFiles - - Icon-Small - - CFBundleTypeName - Master Password sites - LSHandlerRank - Owner - LSItemContentTypes - - com.lyndir.masterpassword.sites - - - - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - [auto] - CFBundleVersion - [auto] - Fabric - - APIKey - 0d10c90776f5ef5acd01ddbeaca9a6cba4814560 - Kits - - - KitInfo - - KitName - Crashlytics - - - - LSRequiresIPhoneOS - - NSHumanReadableCopyright - © 2011-2018 - UIAppFonts - - Exo2.0-Bold.otf - Exo2.0-ExtraBold.otf - Exo2.0-Regular.otf - Exo2.0-Thin.otf - SourceCodePro-Black.otf - SourceCodePro-Regular.otf - SourceCodePro-ExtraLight.otf - - UIStatusBarHidden - - UIStatusBarStyle - UIStatusBarStyleDefault - UIStatusBarTintParameters - - UINavigationBar - - Style - UIBarStyleDefault - TintColor - - Blue - 0.42745098039215684 - Green - 0.39215686274509803 - Red - 0.37254901960784315 - - Translucent - - - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UTExportedTypeDeclarations - - - UTTypeConformsTo - - public.utf8-plain-text - - UTTypeDescription - Master Password sites - UTTypeIdentifier - com.lyndir.masterpassword.sites - UTTypeSize320IconFile - Icon-320.png - UTTypeSize64IconFile - Icon-64.png - UTTypeTagSpecification - - public.filename-extension - - mpsites - - - - - + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + M. Password + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + mpsites + + CFBundleTypeIconFiles + + Icon-Small + + CFBundleTypeName + Master Password sites + LSHandlerRank + Owner + LSItemContentTypes + + com.lyndir.masterpassword.sites + + + + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + [auto] + CFBundleVersion + [auto] + Fabric + + APIKey + 0d10c90776f5ef5acd01ddbeaca9a6cba4814560 + Kits + + + KitInfo + + KitName + Crashlytics + + + + LSRequiresIPhoneOS + + NSHumanReadableCopyright + © 2011-2018 + UIAppFonts + + Exo2.0-Bold.otf + Exo2.0-ExtraBold.otf + Exo2.0-Regular.otf + Exo2.0-Thin.otf + SourceCodePro-Black.otf + SourceCodePro-Regular.otf + SourceCodePro-ExtraLight.otf + + UIMainStoryboardFile + Storyboard + UIStatusBarHidden + + UIStatusBarStyle + UIStatusBarStyleDefault + UIStatusBarTintParameters + + UINavigationBar + + Style + UIBarStyleDefault + TintColor + + Blue + 0.42745098039215684 + Green + 0.39215686274509803 + Red + 0.37254901960784315 + + Translucent + + + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UTExportedTypeDeclarations + + + UTTypeConformsTo + + public.utf8-plain-text + + UTTypeDescription + Master Password sites + UTTypeIdentifier + com.lyndir.masterpassword.sites + UTTypeSize320IconFile + Icon-320.png + UTTypeSize64IconFile + Icon-64.png + UTTypeTagSpecification + + public.filename-extension + + mpsites + + + + + diff --git a/platform-independent/c/core/src/mpw-util.h b/platform-independent/c/core/src/mpw-util.h index 57ee022f..8765a9ef 100644 --- a/platform-independent/c/core/src/mpw-util.h +++ b/platform-independent/c/core/src/mpw-util.h @@ -25,6 +25,7 @@ #include "mpw-types.h" //// Logging. +#ifndef trc extern int mpw_verbosity; #ifndef mpw_log_do @@ -39,7 +40,6 @@ extern int mpw_verbosity; }; } while (0) #endif -#ifndef trc /** Logging internal state. */ #define trc_level 3 #define trc(format, ...) mpw_log( trc_level, format, ##__VA_ARGS__ )