From c4f0462d435907e53ac834041c555391314365f6 Mon Sep 17 00:00:00 2001 From: Yishi Lin Date: Sun, 29 Sep 2019 00:28:46 +0800 Subject: [PATCH] Update the passcode lock view --- pass.xcodeproj/project.pbxproj | 8 +++++ passKit/Assets.xcassets/Contents.json | 6 ++++ .../Contents.json | 21 +++++++++++ .../PasscodeLockViewIcon.imageset/Icon-72.png | Bin 0 -> 4234 bytes .../PasscodeLockViewController.swift | 34 +++++++++--------- passKit/Extensions/UITextFieldExtension.swift | 10 ++++++ 6 files changed, 63 insertions(+), 16 deletions(-) create mode 100644 passKit/Assets.xcassets/Contents.json create mode 100644 passKit/Assets.xcassets/PasscodeLockViewIcon.imageset/Contents.json create mode 100644 passKit/Assets.xcassets/PasscodeLockViewIcon.imageset/Icon-72.png diff --git a/pass.xcodeproj/project.pbxproj b/pass.xcodeproj/project.pbxproj index 9bc6e4e..98991c7 100644 --- a/pass.xcodeproj/project.pbxproj +++ b/pass.xcodeproj/project.pbxproj @@ -88,6 +88,7 @@ A239F59C2158C08C00576CBF /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A239F59A2158C08C00576CBF /* MainInterface.storyboard */; }; A239F5A12158C08C00576CBF /* passAutoFillExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = A239F5952158C08B00576CBF /* passAutoFillExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; A239F5A52158C3F400576CBF /* passKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A26075781EEC6F34005DB03E /* passKit.framework */; }; + A23DD0DC233FB46900E6CD83 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A23DD0DB233FB46900E6CD83 /* Assets.xcassets */; }; A26075811EEC6F34005DB03E /* passKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A26075781EEC6F34005DB03E /* passKit.framework */; }; A26075881EEC6F34005DB03E /* passKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A26075871EEC6F34005DB03E /* passKitTests.swift */; }; A260758A1EEC6F34005DB03E /* passKit.h in Headers */ = {isa = PBXBuildFile; fileRef = A260757A1EEC6F34005DB03E /* passKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -299,6 +300,7 @@ A239F59B2158C08C00576CBF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = ""; }; A239F59D2158C08C00576CBF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A239F59E2158C08C00576CBF /* passAutoFillExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = passAutoFillExtension.entitlements; sourceTree = ""; }; + A23DD0DB233FB46900E6CD83 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; A26075781EEC6F34005DB03E /* passKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = passKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A260757A1EEC6F34005DB03E /* passKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = passKit.h; sourceTree = ""; }; A260757B1EEC6F34005DB03E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -603,6 +605,7 @@ A2F4E20F1EED7F0A0011986E /* Helpers */, A2F4E20E1EED7F040011986E /* Models */, 30C015A3214ECF2B005BB6DF /* Parser */, + A23DD0DB233FB46900E6CD83 /* Assets.xcassets */, A260757A1EEC6F34005DB03E /* passKit.h */, A26075A51EEC7125005DB03E /* pass.xcdatamodeld */, A260757B1EEC6F34005DB03E /* Info.plist */, @@ -1065,6 +1068,7 @@ files = ( 556EC3DA22335D3400934F9C /* InfoPlist.strings in Resources */, 556EC3D522335CD900934F9C /* Localizable.strings in Resources */, + A23DD0DC233FB46900E6CD83 /* Assets.xcassets in Resources */, 556EC3D622335CD900934F9C /* Localizable.stringsdict in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1822,6 +1826,8 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; + EMBED_ASSET_PACKS_IN_PRODUCT_BUNDLE = NO; + ENABLE_ON_DEMAND_RESOURCES = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/iOS"; @@ -1888,7 +1894,9 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + EMBED_ASSET_PACKS_IN_PRODUCT_BUNDLE = NO; ENABLE_NS_ASSERTIONS = NO; + ENABLE_ON_DEMAND_RESOURCES = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/iOS"; GCC_C_LANGUAGE_STANDARD = gnu99; diff --git a/passKit/Assets.xcassets/Contents.json b/passKit/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/passKit/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/passKit/Assets.xcassets/PasscodeLockViewIcon.imageset/Contents.json b/passKit/Assets.xcassets/PasscodeLockViewIcon.imageset/Contents.json new file mode 100644 index 0000000..d4712fc --- /dev/null +++ b/passKit/Assets.xcassets/PasscodeLockViewIcon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Icon-72.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/passKit/Assets.xcassets/PasscodeLockViewIcon.imageset/Icon-72.png b/passKit/Assets.xcassets/PasscodeLockViewIcon.imageset/Icon-72.png new file mode 100644 index 0000000000000000000000000000000000000000..de42014e74b65071a089dfa37d681941adef9c52 GIT binary patch literal 4234 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 literal 0 HcmV?d00001 diff --git a/passKit/Controllers/PasscodeLockViewController.swift b/passKit/Controllers/PasscodeLockViewController.swift index f7d198a..163c108 100644 --- a/passKit/Controllers/PasscodeLockViewController.swift +++ b/passKit/Controllers/PasscodeLockViewController.swift @@ -17,7 +17,6 @@ open class PasscodeLockViewController: UIViewController, UITextFieldDelegate { open var successCallback: (()->Void)? open var cancelCallback: (()->Void)? - weak var passcodeLabel: UILabel? weak var passcodeTextField: UITextField? weak var biometryAuthButton: UIButton? weak var forgotPasscodeButton: UIButton? @@ -30,14 +29,6 @@ open class PasscodeLockViewController: UIViewController, UITextFieldDelegate { open override func loadView() { super.loadView() - let passcodeLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 300, height: 40)) - passcodeLabel.text = "EnterPasscode".localize() - passcodeLabel.font = UIFont.boldSystemFont(ofSize: 18) - passcodeLabel.textAlignment = .center - passcodeLabel.translatesAutoresizingMaskIntoConstraints = false - self.view.addSubview(passcodeLabel) - self.passcodeLabel = passcodeLabel - let passcodeTextField = UITextField(frame: CGRect(x: 0, y: 0, width: 300, height: 40)) passcodeTextField.borderStyle = UITextField.BorderStyle.roundedRect passcodeTextField.placeholder = "EnterPasscode".localize() @@ -100,19 +91,29 @@ open class PasscodeLockViewController: UIViewController, UITextFieldDelegate { cancelButton.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.left self.view.addSubview(cancelButton) self.cancelButton = cancelButton + + // Display the Pass icon in the middle of the screen + let bundle = Bundle(for: PasscodeLockViewController.self) + let appIcon = UIImage(named: "PasscodeLockViewIcon", in: bundle, compatibleWith: nil) + let appIconSize = (appIcon?.size.height) ?? 0 + let appIconView = UIImageView(image: appIcon) + appIconView.translatesAutoresizingMaskIntoConstraints = false + appIconView.layer.cornerRadius = appIconSize / 5 + appIconView.layer.masksToBounds = true + self.view?.addSubview(appIconView) NSLayoutConstraint.activate([ - passcodeTextField.widthAnchor.constraint(equalToConstant: 300), + passcodeTextField.widthAnchor.constraint(equalToConstant: 250), passcodeTextField.heightAnchor.constraint(equalToConstant: 40), passcodeTextField.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), passcodeTextField.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: -20), // above passocde - passcodeLabel.widthAnchor.constraint(equalToConstant: 300), - passcodeLabel.heightAnchor.constraint(equalToConstant: 40), - passcodeLabel.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), - passcodeLabel.bottomAnchor.constraint(equalTo: passcodeTextField.topAnchor), + appIconView.widthAnchor.constraint(equalToConstant: appIconSize), + appIconView.heightAnchor.constraint(equalToConstant: appIconSize), + appIconView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), + appIconView.bottomAnchor.constraint(equalTo: passcodeTextField.topAnchor, constant: -appIconSize), // below passcode - biometryAuthButton.widthAnchor.constraint(equalToConstant: 300), + biometryAuthButton.widthAnchor.constraint(equalToConstant: 250), biometryAuthButton.heightAnchor.constraint(equalToConstant: 40), biometryAuthButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), biometryAuthButton.topAnchor.constraint(equalTo: passcodeTextField.bottomAnchor), @@ -122,7 +123,7 @@ open class PasscodeLockViewController: UIViewController, UITextFieldDelegate { cancelButton.topAnchor.constraint(equalTo: self.view.safeTopAnchor), cancelButton.leftAnchor.constraint(equalTo: self.view.safeLeftAnchor, constant: 20), // bottom of the screen - forgotPasscodeButton.widthAnchor.constraint(equalToConstant: 300), + forgotPasscodeButton.widthAnchor.constraint(equalToConstant: 250), forgotPasscodeButton.heightAnchor.constraint(equalToConstant: 40), forgotPasscodeButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), forgotPasscodeButton.bottomAnchor.constraint(equalTo: self.view.safeBottomAnchor, constant: -40) @@ -227,6 +228,7 @@ open class PasscodeLockViewController: UIViewController, UITextFieldDelegate { self.passcodeTextField?.placeholder = "TryAgain".localize() self.passcodeTextField?.text = "" + self.passcodeTextField?.shake() } } textField.resignFirstResponder() diff --git a/passKit/Extensions/UITextFieldExtension.swift b/passKit/Extensions/UITextFieldExtension.swift index d3d430c..67df2f2 100644 --- a/passKit/Extensions/UITextFieldExtension.swift +++ b/passKit/Extensions/UITextFieldExtension.swift @@ -20,4 +20,14 @@ extension UITextField { objc_setAssociatedObject(self, &kAssociationKeyNextField, newField, .OBJC_ASSOCIATION_RETAIN) } } + + func shake() { + let animation = CAKeyframeAnimation(keyPath: "transform.translation.x") + animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) + animation.repeatCount = 3 + animation.duration = 0.2/TimeInterval(animation.repeatCount) + animation.autoreverses = true + animation.values = [3, -3] + layer.add(animation, forKey: "shake") + } }