diff --git a/enzevalos_iphone.xcodeproj/project.pbxproj b/enzevalos_iphone.xcodeproj/project.pbxproj index 4c744e87c00a245f8e5824f8035ebe95c93fb693..bd06860173ee41d637a04d5b36c1d36bdd6c1f76 100644 --- a/enzevalos_iphone.xcodeproj/project.pbxproj +++ b/enzevalos_iphone.xcodeproj/project.pbxproj @@ -161,6 +161,8 @@ 479B597B20691C1A00B3944D /* ObjectivePGP.framework in Resources */ = {isa = PBXBuildFile; fileRef = 47CEF4EA2052C3C700887CDB /* ObjectivePGP.framework */; }; 479C649621F2139B00A01071 /* support_pk.asc in Resources */ = {isa = PBXBuildFile; fileRef = 479C649521F2139B00A01071 /* support_pk.asc */; }; 479C649721F2139B00A01071 /* support_pk.asc in Resources */ = {isa = PBXBuildFile; fileRef = 479C649521F2139B00A01071 /* support_pk.asc */; }; + 479C649A21F45DAF00A01071 /* HideShowPasswordTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 479C649821F45DAF00A01071 /* HideShowPasswordTextField.swift */; }; + 479C649B21F45DAF00A01071 /* PasswordToggleVisibilityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 479C649921F45DAF00A01071 /* PasswordToggleVisibilityView.swift */; }; 47A7975B1FCD56B7006B3BC4 /* enzevalos_iphone.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = A135267F1D955BDF00D3BFE1 /* enzevalos_iphone.xcdatamodeld */; }; 47C22281218AFD6300BD2C2B /* AutocryptTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C22280218AFD6300BD2C2B /* AutocryptTest.swift */; }; 47C22283218B02C700BD2C2B /* autocryptSimpleExample1.eml in Resources */ = {isa = PBXBuildFile; fileRef = 47C22282218B02C700BD2C2B /* autocryptSimpleExample1.eml */; }; @@ -243,7 +245,7 @@ F12041FD1DA409A5002E4940 /* ListViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F12041FC1DA409A5002E4940 /* ListViewCell.swift */; }; F12060801DA540FE00F6EF37 /* RefreshControlExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F120607F1DA540FE00F6EF37 /* RefreshControlExtension.swift */; }; F12060821DA552FC00F6EF37 /* MailHandlerDelegator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F12060811DA552FC00F6EF37 /* MailHandlerDelegator.swift */; }; - F120A7D31F7937BB006D5BF1 /* (null) in Frameworks */ = {isa = PBXBuildFile; }; + F120A7D31F7937BB006D5BF1 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; F12D8DBB2069422A0068788E /* About.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F12D8DBD2069422A0068788E /* About.storyboard */; }; F14239C11F30A99C00998A83 /* QRCodeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F14239C01F30A99C00998A83 /* QRCodeGenerator.swift */; }; F1737ACB2031D7D70000312B /* StudySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = A17FDFF2202C685800F7BA89 /* StudySettings.swift */; }; @@ -349,6 +351,8 @@ 47953AA81FD7000200D4631A /* bitcoinde.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = bitcoinde.asc; sourceTree = "<group>"; }; 479B5976206914BE00B3944D /* CryptoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptoTests.swift; sourceTree = "<group>"; }; 479C649521F2139B00A01071 /* support_pk.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = support_pk.asc; sourceTree = "<group>"; }; + 479C649821F45DAF00A01071 /* HideShowPasswordTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HideShowPasswordTextField.swift; sourceTree = "<group>"; }; + 479C649921F45DAF00A01071 /* PasswordToggleVisibilityView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordToggleVisibilityView.swift; sourceTree = "<group>"; }; 47B2318A1F0D458100961B28 /* enzevalos_iphone 2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "enzevalos_iphone 2.xcdatamodel"; sourceTree = "<group>"; }; 47C22280218AFD6300BD2C2B /* AutocryptTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutocryptTest.swift; sourceTree = "<group>"; }; 47C22282218B02C700BD2C2B /* autocryptSimpleExample1.eml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = autocryptSimpleExample1.eml; sourceTree = "<group>"; }; @@ -493,7 +497,7 @@ 47F867E42052B49800AA832F /* libbz2.tbd in Frameworks */, 47F867E22052B48E00AA832F /* libz.tbd in Frameworks */, 47F867E02052B47C00AA832F /* Security.framework in Frameworks */, - F120A7D31F7937BB006D5BF1 /* (null) in Frameworks */, + F120A7D31F7937BB006D5BF1 /* BuildFile in Frameworks */, 472F396E1E14F384009260FB /* CoreData.framework in Frameworks */, 9935BC866A86C4A4B9819F35 /* Pods_enzevalos_iphone.framework in Frameworks */, ); @@ -839,6 +843,8 @@ A18C76851E8185ED00B21414 /* onboarding */ = { isa = PBXGroup; children = ( + 479C649821F45DAF00A01071 /* HideShowPasswordTextField.swift */, + 479C649921F45DAF00A01071 /* PasswordToggleVisibilityView.swift */, A1083A531E8BFEA6003666B7 /* Onboarding.swift */, A102AA891EDDB4E80024B457 /* videoOnboarding2.m4v */, A1C62E992018F716000E5273 /* OnboardingValueState.swift */, @@ -1467,6 +1473,7 @@ A1EB05821D95685B008659C1 /* CollectionDataDelegate.swift in Sources */, 47D1302B1F7CEE6D007B14DF /* DebugSettings.swift in Sources */, A1EB05801D956851008659C1 /* SendViewController.swift in Sources */, + 479C649B21F45DAF00A01071 /* PasswordToggleVisibilityView.swift in Sources */, 47691A8C1ECC3EC7004BCFC5 /* EphemeralMail.swift in Sources */, 8428A8671F436A11007649A5 /* SubBadgeHeaderTableViewCell.swift in Sources */, A1EB05981D956947008659C1 /* InboxViewController.swift in Sources */, @@ -1499,6 +1506,7 @@ A12FC23120221A1400196008 /* ExportInfoViewController.swift in Sources */, 475DF47A1F0D54C9009D807F /* Folder+CoreDataProperties.swift in Sources */, 475B00431F7BB6D6006CDD41 /* PersistentKey+CoreDataProperties.swift in Sources */, + 479C649A21F45DAF00A01071 /* HideShowPasswordTextField.swift in Sources */, F119D2901E364B59001D732A /* AnimatedSendIcon.swift in Sources */, 4707096D1F8F9F4900657F41 /* ExportViewController.swift in Sources */, F12060801DA540FE00F6EF37 /* RefreshControlExtension.swift in Sources */, diff --git a/enzevalos_iphone/Assets.xcassets/passwordInput/Contents.json b/enzevalos_iphone/Assets.xcassets/passwordInput/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..da4a164c918651cdd1e11dca5cc62c333f097601 --- /dev/null +++ b/enzevalos_iphone/Assets.xcassets/passwordInput/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_closed.imageset/Contents.json b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_closed.imageset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..1bb26ac5def09970c595f7a8c63be73007770a2d --- /dev/null +++ b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_closed.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "ic_eye_closed.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ic_eye_closed@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ic_eye_closed@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_closed.imageset/ic_eye_closed.png b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_closed.imageset/ic_eye_closed.png new file mode 100644 index 0000000000000000000000000000000000000000..10a89456c953256b948001ad9009ea4de285a457 Binary files /dev/null and b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_closed.imageset/ic_eye_closed.png differ diff --git a/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_closed.imageset/ic_eye_closed@2x.png b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_closed.imageset/ic_eye_closed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f8feed2ee39a7433e44e39b55189429d00f50c3c Binary files /dev/null and b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_closed.imageset/ic_eye_closed@2x.png differ diff --git a/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_closed.imageset/ic_eye_closed@3x.png b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_closed.imageset/ic_eye_closed@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..798f10fd18b30cbfb052cb6a615e4c262742f411 Binary files /dev/null and b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_closed.imageset/ic_eye_closed@3x.png differ diff --git a/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_open.imageset/Contents.json b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_open.imageset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..63979ef42fc4258f587c9d33d2b76142b4b306bc --- /dev/null +++ b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_open.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "ic_eye_open.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ic_eye_open@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ic_eye_open@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_open.imageset/ic_eye_open.png b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_open.imageset/ic_eye_open.png new file mode 100644 index 0000000000000000000000000000000000000000..59f0c2c81cc86cebcbfae3ac00daedc7b7db8a30 Binary files /dev/null and b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_open.imageset/ic_eye_open.png differ diff --git a/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_open.imageset/ic_eye_open@2x.png b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_open.imageset/ic_eye_open@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1ec7263d1549f769fc6fef04025cffe1e0090918 Binary files /dev/null and b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_open.imageset/ic_eye_open@2x.png differ diff --git a/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_open.imageset/ic_eye_open@3x.png b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_open.imageset/ic_eye_open@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..1aa74e4b83f5898736dc1929020e36497b46f299 Binary files /dev/null and b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_eye_open.imageset/ic_eye_open@3x.png differ diff --git a/enzevalos_iphone/Assets.xcassets/passwordInput/ic_password_checkmark.imageset/Contents.json b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_password_checkmark.imageset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..85a76208ad5a387b04f895ed8f01815f668fe032 --- /dev/null +++ b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_password_checkmark.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "ic_password_checkmark.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ic_password_checkmark@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ic_password_checkmark@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/enzevalos_iphone/Assets.xcassets/passwordInput/ic_password_checkmark.imageset/ic_password_checkmark.png b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_password_checkmark.imageset/ic_password_checkmark.png new file mode 100644 index 0000000000000000000000000000000000000000..05a5bccd35783d27d8904dbf4fc9b66c0343f23d Binary files /dev/null and b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_password_checkmark.imageset/ic_password_checkmark.png differ diff --git a/enzevalos_iphone/Assets.xcassets/passwordInput/ic_password_checkmark.imageset/ic_password_checkmark@2x.png b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_password_checkmark.imageset/ic_password_checkmark@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4bf6c49ebebc5f5cc258567ecb6d375432087d8e Binary files /dev/null and b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_password_checkmark.imageset/ic_password_checkmark@2x.png differ diff --git a/enzevalos_iphone/Assets.xcassets/passwordInput/ic_password_checkmark.imageset/ic_password_checkmark@3x.png b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_password_checkmark.imageset/ic_password_checkmark@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..7740a41d8e0daf48bdc11325356cb816dead3271 Binary files /dev/null and b/enzevalos_iphone/Assets.xcassets/passwordInput/ic_password_checkmark.imageset/ic_password_checkmark@3x.png differ diff --git a/enzevalos_iphone/HideShowPasswordTextField.swift b/enzevalos_iphone/HideShowPasswordTextField.swift new file mode 100644 index 0000000000000000000000000000000000000000..451696a891fb914fdfec85d91d8efabcc37682c9 --- /dev/null +++ b/enzevalos_iphone/HideShowPasswordTextField.swift @@ -0,0 +1,135 @@ +// +// HideShowPasswordTextField.swift +// Guidebook +// +// Created by Mike Sprague on 4/15/16. +// See: https://github.com/Guidebook/HideShowPasswordTextField +// +// + +import Foundation +import UIKit + +protocol HideShowPasswordTextFieldDelegate: class { + func isValidPassword(password: String) -> Bool +} + +class HideShowPasswordTextField: UITextField { + + weak var passwordDelegate: HideShowPasswordTextFieldDelegate? + var preferredFont: UIFont? { + didSet { + self.font = preferredFont + + if self.isSecureTextEntry { + self.font = nil + } + } + } + + override var isSecureTextEntry: Bool { + didSet { + if !isSecureTextEntry { + self.font = nil + self.font = preferredFont + } + if isSecureTextEntry { + passwordToggleVisibilityView.eyeState = .closed + } + } + } + private var passwordToggleVisibilityView: PasswordToggleVisibilityView! + + override init(frame: CGRect) { + super.init(frame: frame) + super.isSecureTextEntry = true + setupViews() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setupViews() + } + + override func awakeFromNib() { + super.awakeFromNib() + setupViews() + } +} + +// MARK: UITextFieldDelegate needed calls +// Implement UITextFieldDelegate when you use this, and forward these calls to this class! +extension HideShowPasswordTextField { + func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { + // Hack to prevent text from getting cleared + // http://stackoverflow.com/a/29195723/1417922 + //Setting the new text. + let updatedString = (textField.text as NSString?)?.replacingCharacters(in: range, with: string) + textField.text = updatedString + + //Setting the cursor at the right place + let selectedRange = NSMakeRange(range.location + string.count, 0) + let from = textField.position(from: textField.beginningOfDocument, offset:selectedRange.location)! + let to = textField.position(from: from, offset:selectedRange.length)! + textField.selectedTextRange = textField.textRange(from: from, to: to) + + //Sending an action + textField.sendActions(for: .editingChanged) + + return false + } + + func textFieldDidEndEditing(textField: UITextField) { + passwordToggleVisibilityView.eyeState = PasswordToggleVisibilityView.EyeState.closed + self.isSecureTextEntry = !isSelected + } + +} + +// MARK: PasswordToggleVisibilityDelegate +extension HideShowPasswordTextField: PasswordToggleVisibilityDelegate { + func viewWasToggled(passwordToggleVisibilityView: PasswordToggleVisibilityView, isSelected selected: Bool) { + + // hack to fix a bug with padding when switching between secureTextEntry state + let hackString = self.text + self.text = " " + self.text = hackString + + // hack to save our correct font. The order here is VERY finicky + self.isSecureTextEntry = !selected + } +} + +// MARK: Control events +extension HideShowPasswordTextField { + @objc func passwordTextChanged(sender: AnyObject) { + if let password = self.text { + passwordToggleVisibilityView.checkmarkVisible = passwordDelegate?.isValidPassword(password: password) ?? false + } else { + passwordToggleVisibilityView.checkmarkVisible = false + } + } +} + +// MARK: Private helpers +extension HideShowPasswordTextField { + private func setupViews() { + let toggleFrame = CGRect(x: 0, y: 0, width: 66, height: frame.height) + passwordToggleVisibilityView = PasswordToggleVisibilityView(frame: toggleFrame) + passwordToggleVisibilityView.delegate = self + passwordToggleVisibilityView.checkmarkVisible = false + + self.keyboardType = .asciiCapable + self.rightView = passwordToggleVisibilityView + self.rightViewMode = .whileEditing + + self.font = self.preferredFont + self.addTarget(self, action: #selector(HideShowPasswordTextField.passwordTextChanged(sender:)), for: .editingChanged) + + // if we don't do this, the eye flies in on textfield focus! + self.rightView?.frame = self.rightViewRect(forBounds: self.bounds) + + // default eye state based on our initial secure text entry + passwordToggleVisibilityView.eyeState = isSecureTextEntry ? .closed : .open + } +} diff --git a/enzevalos_iphone/Onboarding.swift b/enzevalos_iphone/Onboarding.swift index c101aecf7688720774aaa38f3377a0eed90b1f4d..5f117a4a7fc3bdb4fb77d47188735fd3436e26fc 100644 --- a/enzevalos_iphone/Onboarding.swift +++ b/enzevalos_iphone/Onboarding.swift @@ -32,7 +32,7 @@ class Onboarding: NSObject { static let textColor = UIColor.white static var mailaddress = UITextField.init() static var username = UITextField.init() - static var password = UITextField.init() + static var password = HideShowPasswordTextField.init()//UITextField.init() static var googleButton = UIBarButtonItem.init() static var credentials: UIView? = nil static var imapServer = UITextField.init() @@ -66,7 +66,7 @@ class Onboarding: NSObject { static var transportRows: [Int: String] = [MCOConnectionType.clear.rawValue: NSLocalizedString("Plaintext", comment: ""), MCOConnectionType.startTLS.rawValue: "StartTLS", MCOConnectionType.TLS.rawValue: "TLS"] static func onboarding(_ callback: @escaping () -> ()) -> UIViewController { - + password.isSecureTextEntry = true doWhenDone = callback //Background @@ -149,18 +149,34 @@ class Onboarding: NSObject { let mailaddressUnderline = UIView.init(frame: CGRect.init(x: 0, y: mailaddress.frame.maxY, width: mailaddress.frame.width, height: 0.5)) mailaddressUnderline.backgroundColor = textColor - password = UITextField.init() + + // Create passwordinput view + let frame = CGRect.init(x: 0, y: mailaddress.frame.height + padding + mailaddressUnderline.frame.height, width: 50, height: 30) + password = HideShowPasswordTextField.init(frame: frame) + password.isSecureTextEntry = true password.textColor = textColor password.tintColor = textColor password.borderStyle = UITextBorderStyle.none - password.isSecureTextEntry = true password.returnKeyType = UIReturnKeyType.continue - password.frame = CGRect.init(x: 0, y: mailaddress.frame.height + padding + mailaddressUnderline.frame.height, width: 50, height: 30) + password.attributedPlaceholder = NSAttributedString.init(string: NSLocalizedString("Password", comment: ""), attributes: [NSAttributedStringKey.foregroundColor: textColor]) password.delegate = textDelegate + + password.rightView?.tintColor = UIColor(red: 0.204, green: 0.624, blue: 0.847, alpha: 1) + + + // left view hack to add padding + password.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 3)) + password.leftViewMode = .always + + let passwordUnderline = UIView.init(frame: CGRect.init(x: 0, y: mailaddress.frame.height + padding + mailaddressUnderline.frame.height + password.frame.height, width: password.frame.width, height: 0.5)) passwordUnderline.backgroundColor = textColor + + + + // End let keyboardToolbar = UIToolbar() keyboardToolbar.sizeToFit() @@ -227,6 +243,7 @@ class Onboarding: NSObject { loginViewController = vc! vc?.pageChanged = {(oldPage:Int, newPage: Int) -> () in + password.isSecureTextEntry = true // Logger.queue.async(flags: .barrier) { Logger.log(onboardingPageTransition: oldPage, to: newPage, onboardingSection: "intro") // } @@ -289,6 +306,7 @@ class Onboarding: NSObject { let start = OnboardingContentViewController.content(withTitle: NSLocalizedString("WhatAShame", comment: ""), body: NSLocalizedString("CouldNotConnect", comment: ""), videoURL: nil, inputView: nil, buttonText: nil, actionBlock: nil) Onboarding.password.returnKeyType = .done + password.isSecureTextEntry = true password.text = UserManager.loadUserValue(.userPW) as? String mailaddress.text = UserManager.loadUserValue(.userAddr) as? String doWhenDone = { () -> () in } @@ -699,6 +717,18 @@ class Onboarding: NSObject { } } +/* MARK: UITextFieldDelegate +extension ViewController: UITextFieldDelegate { + func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, textField string: String) -> Bool { + return passwordTextField.textField(textField, shouldChangeCharactersInRange: range, replacementString: string) + } + + func textFieldDidEndEditing(textField: UITextField) { + passwordTextField.textFieldDidEndEditing(textField) + } +} + */ + class TextFieldDelegate: NSObject, UITextFieldDelegate { func textFieldShouldReturn(_ textField: UITextField) -> Bool { @@ -721,6 +751,19 @@ class TextFieldDelegate: NSObject, UITextFieldDelegate { textField.endEditing(true) return true } + + func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, textField string: String) -> Bool { + if textField == Onboarding.password, let passwordTextField = textField as? HideShowPasswordTextField { + return passwordTextField.textField(textField: textField, shouldChangeCharactersInRange: range, replacementString: string) + } + return true + } + + func textFieldDidEndEditing(textField: UITextField) { + if textField == Onboarding.password, let passwordTextField = textField as? HideShowPasswordTextField { + return passwordTextField.textFieldDidEndEditing(textField: textField) + } + } } class PickerDataDelegate: NSObject, UIPickerViewDataSource { diff --git a/enzevalos_iphone/PasswordToggleVisibilityView.swift b/enzevalos_iphone/PasswordToggleVisibilityView.swift new file mode 100644 index 0000000000000000000000000000000000000000..c39d6c2b8615d7f0d65a8c4316d0980e5609dc83 --- /dev/null +++ b/enzevalos_iphone/PasswordToggleVisibilityView.swift @@ -0,0 +1,100 @@ +// +// PasswordToggleVisibilityView.swift +// Guidebook +// +// Created by Mike Sprague on 4/14/16. +// See: https://github.com/Guidebook/HideShowPasswordTextField +// +// + +import Foundation +import UIKit + +protocol PasswordToggleVisibilityDelegate: class { + func viewWasToggled(passwordToggleVisibilityView: PasswordToggleVisibilityView, isSelected selected: Bool) +} + +class PasswordToggleVisibilityView: UIView { + private let eyeOpenedImage: UIImage + private let eyeClosedImage: UIImage + private let checkmarkImage: UIImage + private let eyeButton: UIButton + private let checkmarkImageView: UIImageView + weak var delegate: PasswordToggleVisibilityDelegate? + + enum EyeState { + case open + case closed + } + + var eyeState: EyeState { + set { + eyeButton.isSelected = newValue == .open + } + get { + return eyeButton.isSelected ? .open : .closed + } + } + + var checkmarkVisible: Bool { + set { + checkmarkImageView.isHidden = !newValue + } + get { + return !checkmarkImageView.isHidden + } + } + + override var tintColor: UIColor! { + didSet { + eyeButton.tintColor = tintColor + checkmarkImageView.tintColor = tintColor + } + } + + override init(frame: CGRect) { + self.eyeOpenedImage = UIImage(named: "ic_eye_open")!.withRenderingMode(.alwaysTemplate) + self.eyeClosedImage = UIImage(named: "ic_eye_closed")! + self.checkmarkImage = UIImage(named: "ic_password_checkmark")!.withRenderingMode(.alwaysTemplate) + self.eyeButton = UIButton(type: .custom) + self.checkmarkImageView = UIImageView(image: self.checkmarkImage) + super.init(frame: frame) + setupViews() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("Don't use init with coder.") + } + + private func setupViews() { + let padding: CGFloat = 10 + let buttonWidth = (frame.width / 2) - padding + let buttonFrame = CGRect(x: buttonWidth + padding, y: 0, width: buttonWidth, height: frame.height) + eyeButton.frame = buttonFrame + eyeButton.backgroundColor = UIColor.clear + eyeButton.adjustsImageWhenHighlighted = false + eyeButton.setImage(self.eyeClosedImage, for: .normal) + eyeButton.setImage(self.eyeOpenedImage.withRenderingMode(.alwaysTemplate), for: .selected) + eyeButton.addTarget(self, action: #selector(eyeButtonPressed), for: .touchUpInside) + eyeButton.autoresizingMask = [.flexibleWidth, .flexibleHeight] + eyeButton.tintColor = self.tintColor + self.addSubview(eyeButton) + + let checkmarkImageWidth = (frame.width / 2) - padding + let checkmarkFrame = CGRect(x: padding, y: 0, width: checkmarkImageWidth, height: frame.height) + checkmarkImageView.frame = checkmarkFrame + checkmarkImageView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + checkmarkImageView.contentMode = .center + checkmarkImageView.backgroundColor = UIColor.clear + checkmarkImageView.tintColor = self.tintColor + self.addSubview(checkmarkImageView) + } + + + @objc func eyeButtonPressed(sender: AnyObject) { + eyeButton.isSelected = !eyeButton.isSelected + delegate?.viewWasToggled(passwordToggleVisibilityView: self, isSelected: eyeButton.isSelected) + } +} + +// Animation helpers