mirror of https://github.com/oxen-io/session-ios
				
				
				
			Sketch out the 'onboarding phone number' view.
							parent
							
								
									f25e54f58b
								
							
						
					
					
						commit
						2a4b9426c3
					
				| @ -0,0 +1,514 @@ | ||||
| // | ||||
| //  Copyright (c) 2019 Open Whisper Systems. All rights reserved. | ||||
| // | ||||
| 
 | ||||
| import UIKit | ||||
| import PromiseKit | ||||
| 
 | ||||
| @objc | ||||
| public class OnboardingPhoneNumberViewController: OnboardingBaseViewController { | ||||
| 
 | ||||
|     // MARK: - Dependencies | ||||
| 
 | ||||
|     private var tsAccountManager: TSAccountManager { | ||||
|         return TSAccountManager.sharedInstance() | ||||
|     } | ||||
| 
 | ||||
|     // MARK: - | ||||
| 
 | ||||
|     private let countryNameLabel = UILabel() | ||||
|     private let callingCodeLabel = UILabel() | ||||
|     private let phoneNumberTextField = UITextField() | ||||
|     private var nextButton: OWSFlatButton? | ||||
| 
 | ||||
|     //    - (void)didTapLegalTerms:(UIButton *)sender | ||||
| //{ | ||||
| //    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:kLegalTermsUrlString]]; | ||||
| //    } | ||||
| //#pragma mark - Keyboard notifications | ||||
| // | ||||
| //- (void)initializeKeyboardHandlers | ||||
| //{ | ||||
| //    UITapGestureRecognizer *outsideTabRecognizer = | ||||
| //        [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)]; | ||||
| //    [self.view addGestureRecognizer:outsideTabRecognizer]; | ||||
| //    } | ||||
| // | ||||
| //    - (void)dismissKeyboardFromAppropriateSubView | ||||
| //        { | ||||
| //            [self.view endEditing:NO]; | ||||
| //} | ||||
| // | ||||
| 
 | ||||
|     override public func loadView() { | ||||
|         super.loadView() | ||||
| 
 | ||||
|         // TODO: Is this still necessary? | ||||
|         if let navigationController = self.navigationController as? OWSNavigationController { | ||||
|             SignalApp.shared().signUpFlowNavigationController = navigationController | ||||
|         } else { | ||||
|             owsFailDebug("Missing or invalid navigationController") | ||||
|         } | ||||
| 
 | ||||
|         populateDefaults() | ||||
| 
 | ||||
|         view.backgroundColor = Theme.backgroundColor | ||||
|         view.layoutMargins = .zero | ||||
| 
 | ||||
|         // TODO: | ||||
| //        navigationItem.title = NSLocalizedString("SETTINGS_BACKUP", comment: "Label for the backup view in app settings.") | ||||
| 
 | ||||
|         let titleLabel = self.titleLabel(text: NSLocalizedString("ONBOARDING_PHONE_NUMBER_TITLE", comment: "Title of the 'onboarding phone number' view.")) | ||||
| 
 | ||||
|         // Country | ||||
| 
 | ||||
|         // TODO: dynamic | ||||
|         let fontSizePoints: CGFloat = ScaleFromIPhone5To7Plus(16, 20) | ||||
|         let rowHeight: CGFloat = 40 | ||||
| 
 | ||||
|         countryNameLabel.textColor = Theme.primaryColor | ||||
|         countryNameLabel.font = UIFont.ows_dynamicTypeBody | ||||
|         countryNameLabel.setContentHuggingHorizontalLow() | ||||
|         countryNameLabel.setCompressionResistanceHorizontalLow() | ||||
| 
 | ||||
|         let countryIcon = UIImage(named: (CurrentAppContext().isRTL | ||||
|             ? "small_chevron_left" | ||||
|             : "small_chevron_right")) | ||||
| //        NavBarBackRTL | ||||
| //        small_chevron_right | ||||
| //        system_disclosure_indicator_rtl | ||||
|         let countryImageView = UIImageView(image: countryIcon?.withRenderingMode(.alwaysTemplate)) | ||||
|         countryImageView.tintColor = Theme.placeholderColor | ||||
|         countryImageView.setContentHuggingHigh() | ||||
|         countryImageView.setCompressionResistanceHigh() | ||||
| 
 | ||||
|         let countryRow = UIStackView(arrangedSubviews: [ | ||||
|             countryNameLabel, | ||||
|             countryImageView | ||||
|             ]) | ||||
|         countryRow.axis = .horizontal | ||||
|         countryRow.alignment = .center | ||||
|         countryRow.spacing = 10 | ||||
|         countryRow.isUserInteractionEnabled = true | ||||
|         countryRow.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(countryRowTapped))) | ||||
|         countryRow.autoSetDimension(.height, toSize: rowHeight) | ||||
|         addBottomStroke(countryRow) | ||||
| 
 | ||||
|         callingCodeLabel.textColor = Theme.primaryColor | ||||
|         callingCodeLabel.font = UIFont.ows_dynamicTypeBody | ||||
|         callingCodeLabel.setContentHuggingHorizontalHigh() | ||||
|         callingCodeLabel.setCompressionResistanceHorizontalHigh() | ||||
|         callingCodeLabel.isUserInteractionEnabled = true | ||||
|         callingCodeLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(countryCodeTapped))) | ||||
|         addBottomStroke(callingCodeLabel) | ||||
|         callingCodeLabel.autoSetDimension(.width, toSize: rowHeight, relation: .greaterThanOrEqual) | ||||
| 
 | ||||
|         phoneNumberTextField.textAlignment = .left | ||||
|         phoneNumberTextField.delegate = self | ||||
|         phoneNumberTextField.keyboardType = .numberPad | ||||
|         phoneNumberTextField.textColor = Theme.primaryColor | ||||
|         phoneNumberTextField.font = UIFont.ows_dynamicTypeBody | ||||
|         phoneNumberTextField.setContentHuggingHorizontalLow() | ||||
|         phoneNumberTextField.setCompressionResistanceHorizontalLow() | ||||
| 
 | ||||
|         addBottomStroke(phoneNumberTextField) | ||||
| 
 | ||||
|         let phoneNumberRow = UIStackView(arrangedSubviews: [ | ||||
|             callingCodeLabel, | ||||
|             phoneNumberTextField | ||||
|             ]) | ||||
|         phoneNumberRow.axis = .horizontal | ||||
|         phoneNumberRow.alignment = .fill | ||||
|         phoneNumberRow.spacing = 10 | ||||
|         phoneNumberRow.autoSetDimension(.height, toSize: rowHeight) | ||||
|         callingCodeLabel.autoMatch(.height, to: .height, of: phoneNumberTextField) | ||||
| 
 | ||||
|         // TODO: Finalize copy. | ||||
| 
 | ||||
|         let nextButton = self.button(title: NSLocalizedString("BUTTON_NEXT", | ||||
|                                                                 comment: "Label for the 'next' button."), | ||||
|                                            selector: #selector(nextPressed)) | ||||
|         self.nextButton = nextButton | ||||
|         let topSpacer = UIView.vStretchingSpacer() | ||||
|         let bottomSpacer = UIView.vStretchingSpacer() | ||||
| 
 | ||||
|         let stackView = UIStackView(arrangedSubviews: [ | ||||
|             titleLabel, | ||||
|             topSpacer, | ||||
|             countryRow, | ||||
|             UIView.spacer(withHeight: 8), | ||||
|             phoneNumberRow, | ||||
|             bottomSpacer, | ||||
|             nextButton | ||||
|             ]) | ||||
|         stackView.axis = .vertical | ||||
|         stackView.alignment = .fill | ||||
|         stackView.layoutMargins = UIEdgeInsets(top: 32, left: 32, bottom: 32, right: 32) | ||||
|         stackView.isLayoutMarginsRelativeArrangement = true | ||||
|         view.addSubview(stackView) | ||||
|         stackView.autoPinWidthToSuperviewMargins() | ||||
|         stackView.autoPinWidthToSuperviewMargins() | ||||
|         stackView.autoPin(toTopLayoutGuideOf: self, withInset: 0) | ||||
|         autoPinView(toBottomOfViewControllerOrKeyboard: stackView, avoidNotch: true) | ||||
| 
 | ||||
|         // Ensure whitespace is balanced, so inputs are vertically centered. | ||||
|         topSpacer.autoMatch(.height, to: .height, of: bottomSpacer) | ||||
|     } | ||||
| 
 | ||||
|     private func addBottomStroke(_ view: UIView) { | ||||
|         let strokeView = UIView() | ||||
|         strokeView.backgroundColor = Theme.middleGrayColor | ||||
|         view.addSubview(strokeView) | ||||
|         strokeView.autoSetDimension(.height, toSize: CGHairlineWidth()) | ||||
|         strokeView.autoPinWidthToSuperview() | ||||
|         strokeView.autoPinEdge(toSuperviewEdge: .bottom) | ||||
|     } | ||||
| 
 | ||||
|     public override func viewWillAppear(_ animated: Bool) { | ||||
|         super.viewWillAppear(animated) | ||||
| 
 | ||||
|         self.navigationController?.isNavigationBarHidden = false | ||||
| 
 | ||||
|         phoneNumberTextField.becomeFirstResponder() | ||||
|     } | ||||
| 
 | ||||
|     public override func viewDidAppear(_ animated: Bool) { | ||||
|         super.viewDidAppear(animated) | ||||
| 
 | ||||
|         self.navigationController?.isNavigationBarHidden = false | ||||
| 
 | ||||
|         phoneNumberTextField.becomeFirstResponder() | ||||
| 
 | ||||
|         if tsAccountManager.isReregistering() { | ||||
|             // If re-registering, pre-populate the country (country code, calling code, country name) | ||||
|             // and phone number state. | ||||
|             guard let phoneNumberE164 = tsAccountManager.reregisterationPhoneNumber() else { | ||||
|                 owsFailDebug("Could not resume re-registration; missing phone number.") | ||||
|                 return | ||||
|             } | ||||
|             tryToReregister(phoneNumberE164: phoneNumberE164) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private func tryToReregister(phoneNumberE164: String) { | ||||
|         guard phoneNumberE164.count > 0 else { | ||||
|             owsFailDebug("Could not resume re-registration; invalid phoneNumberE164.") | ||||
|             return | ||||
|         } | ||||
|         guard let parsedPhoneNumber = PhoneNumber(fromE164: phoneNumberE164) else { | ||||
|             owsFailDebug("Could not resume re-registration; couldn't parse phoneNumberE164.") | ||||
|             return | ||||
|         } | ||||
|         guard let callingCode = parsedPhoneNumber.getCountryCode() else { | ||||
|             owsFailDebug("Could not resume re-registration; missing callingCode.") | ||||
|             return | ||||
|         } | ||||
|         let callingCodeText = "\(COUNTRY_CODE_PREFIX)\(callingCode)" | ||||
|         let countryCodes: [String] = | ||||
|             PhoneNumberUtil.sharedThreadLocal().countryCodes(fromCallingCode: callingCodeText) | ||||
|         guard let countryCode = countryCodes.first else { | ||||
|             owsFailDebug("Could not resume re-registration; unknown countryCode.") | ||||
|             return | ||||
|         } | ||||
|         guard let countryName = PhoneNumberUtil.countryName(fromCountryCode: countryCode) else { | ||||
|             owsFailDebug("Could not resume re-registration; unknown countryName.") | ||||
|             return | ||||
|         } | ||||
|         if !phoneNumberE164.hasPrefix(callingCodeText) { | ||||
|             owsFailDebug("Could not resume re-registration; non-matching calling code.") | ||||
|             return | ||||
|         } | ||||
|         let phoneNumberWithoutCallingCode = phoneNumberE164.substring(from: callingCodeText.count) | ||||
| 
 | ||||
|         update(withCountryName: countryName, callingCode: callingCodeText, countryCode: countryCode) | ||||
| 
 | ||||
|         phoneNumberTextField.text = phoneNumberWithoutCallingCode | ||||
|         // Don't let user edit their phone number while re-registering. | ||||
|         phoneNumberTextField.isEnabled = false | ||||
|     } | ||||
| 
 | ||||
|     // MARK: - | ||||
| 
 | ||||
|     private var countryName = "" | ||||
|     private var callingCode = "" | ||||
|     private var countryCode = "" | ||||
| 
 | ||||
|     private func populateDefaults() { | ||||
| 
 | ||||
|         var countryCode: String = PhoneNumber.defaultCountryCode() | ||||
|         if let lastRegisteredCountryCode = self.lastRegisteredCountryCode(), | ||||
|             lastRegisteredCountryCode.count > 0 { | ||||
|             countryCode = lastRegisteredCountryCode | ||||
|         } | ||||
| 
 | ||||
|         let callingCodeNumber: NSNumber = PhoneNumberUtil.sharedThreadLocal().nbPhoneNumberUtil.getCountryCode(forRegion: countryCode) | ||||
|         let callingCode = "\(COUNTRY_CODE_PREFIX)\(callingCodeNumber)" | ||||
| 
 | ||||
|         if let lastRegisteredPhoneNumber = self.lastRegisteredPhoneNumber(), | ||||
|             lastRegisteredPhoneNumber.count > 0, | ||||
|             lastRegisteredPhoneNumber.hasPrefix(callingCode) { | ||||
|             phoneNumberTextField.text = lastRegisteredPhoneNumber.substring(from: callingCode.count) | ||||
|         } | ||||
| 
 | ||||
|         var countryName = NSLocalizedString("UNKNOWN_COUNTRY_NAME", comment: "Label for unknown countries.") | ||||
|         if let countryNameDerived = PhoneNumberUtil.countryName(fromCountryCode: countryCode) { | ||||
|             countryName = countryNameDerived | ||||
|         } | ||||
| 
 | ||||
|         update(withCountryName: countryName, callingCode: callingCode, countryCode: countryCode) | ||||
|     } | ||||
| 
 | ||||
|     private func update(withCountryName countryName: String, callingCode: String, countryCode: String) { | ||||
|         AssertIsOnMainThread() | ||||
| 
 | ||||
|         guard countryCode.count > 0 else { | ||||
|             owsFailDebug("Invalid country code.") | ||||
|             return | ||||
|         } | ||||
|         guard countryName.count > 0 else { | ||||
|             owsFailDebug("Invalid country name.") | ||||
|             return | ||||
|         } | ||||
|         guard callingCode.count > 0 else { | ||||
|             owsFailDebug("Invalid calling code.") | ||||
|             return | ||||
|         } | ||||
| 
 | ||||
|         self.countryName = countryName | ||||
|         self.callingCode = callingCode | ||||
|         self.countryCode = countryCode | ||||
| 
 | ||||
|         countryNameLabel.text = countryName | ||||
|         callingCodeLabel.text = callingCode | ||||
| 
 | ||||
|         self.phoneNumberTextField.placeholder = ViewControllerUtils.examplePhoneNumber(forCountryCode: countryCode, callingCode: callingCode) | ||||
|     } | ||||
| 
 | ||||
|     // MARK: - Debug | ||||
| 
 | ||||
|     private let kKeychainService_LastRegistered = "kKeychainService_LastRegistered" | ||||
|     private let kKeychainKey_LastRegisteredCountryCode = "kKeychainKey_LastRegisteredCountryCode" | ||||
|     private let kKeychainKey_LastRegisteredPhoneNumber = "kKeychainKey_LastRegisteredPhoneNumber" | ||||
| 
 | ||||
|     private func debugValue(forKey key: String) -> String? { | ||||
|         guard CurrentAppContext().isDebugBuild() else { | ||||
|             return nil | ||||
|         } | ||||
| 
 | ||||
|         do { | ||||
|             let value = try CurrentAppContext().keychainStorage().string(forService: kKeychainService_LastRegistered, key: key) | ||||
|             return value | ||||
|         } catch { | ||||
|             owsFailDebug("Error: \(error)") | ||||
|             return nil | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private func setDebugValue(_ value: String, forKey key: String) { | ||||
|         guard CurrentAppContext().isDebugBuild() else { | ||||
|             return | ||||
|         } | ||||
| 
 | ||||
|         do { | ||||
|             try CurrentAppContext().keychainStorage().set(string: value, service: kKeychainService_LastRegistered, key: key) | ||||
|         } catch { | ||||
|             owsFailDebug("Error: \(error)") | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private func lastRegisteredCountryCode() -> String? { | ||||
|         return debugValue(forKey: kKeychainKey_LastRegisteredCountryCode) | ||||
|     } | ||||
| 
 | ||||
|     private func setLastRegisteredCountryCode(value: String) { | ||||
|         setDebugValue(value, forKey: kKeychainKey_LastRegisteredCountryCode) | ||||
|     } | ||||
| 
 | ||||
|     private func lastRegisteredPhoneNumber() -> String? { | ||||
|         return debugValue(forKey: kKeychainKey_LastRegisteredPhoneNumber) | ||||
|     } | ||||
| 
 | ||||
|     private func setLastRegisteredPhoneNumber(value: String) { | ||||
|         setDebugValue(value, forKey: kKeychainKey_LastRegisteredPhoneNumber) | ||||
|     } | ||||
| 
 | ||||
|      // MARK: - Events | ||||
| 
 | ||||
|     @objc func explanationLabelTapped(sender: UIGestureRecognizer) { | ||||
|         guard sender.state == .recognized else { | ||||
|             return | ||||
|         } | ||||
|         // TODO: | ||||
|     } | ||||
| 
 | ||||
|     @objc func countryRowTapped(sender: UIGestureRecognizer) { | ||||
|         guard sender.state == .recognized else { | ||||
|             return | ||||
|         } | ||||
|         showCountryPicker() | ||||
|     } | ||||
| 
 | ||||
|     @objc func countryCodeTapped(sender: UIGestureRecognizer) { | ||||
|         guard sender.state == .recognized else { | ||||
|             return | ||||
|         } | ||||
|         showCountryPicker() | ||||
|     } | ||||
| 
 | ||||
|     @objc func nextPressed() { | ||||
|         Logger.info("") | ||||
| 
 | ||||
|         onboardingController.onboardingPhoneNumberDidComplete(viewController: self) | ||||
|     } | ||||
| 
 | ||||
|     // MARK: - Country Picker | ||||
| 
 | ||||
|     private func showCountryPicker() { | ||||
|         guard !tsAccountManager.isReregistering() else { | ||||
|             return | ||||
|         } | ||||
| 
 | ||||
|         let countryCodeController = CountryCodeViewController() | ||||
|         countryCodeController.countryCodeDelegate = self | ||||
|         countryCodeController.interfaceOrientationMask = .portrait | ||||
|         let navigationController = OWSNavigationController(rootViewController: countryCodeController) | ||||
|         self.present(navigationController, animated: true, completion: nil) | ||||
|     } | ||||
| 
 | ||||
|     // MARK: - Register | ||||
| 
 | ||||
|     private func didTapRegisterButton() { | ||||
|         guard let phoneNumberText = phoneNumberTextField.text?.ows_stripped(), | ||||
|             phoneNumberText.count > 0 else { | ||||
|                 OWSAlerts.showAlert(title: | ||||
|                     NSLocalizedString("REGISTRATION_VIEW_NO_PHONE_NUMBER_ALERT_TITLE", | ||||
|                                       comment: "Title of alert indicating that users needs to enter a phone number to register."), | ||||
|                     message: | ||||
|                     NSLocalizedString("REGISTRATION_VIEW_NO_PHONE_NUMBER_ALERT_MESSAGE", | ||||
|                                       comment: "Message of alert indicating that users needs to enter a phone number to register.")) | ||||
|                 return | ||||
|         } | ||||
| 
 | ||||
|         let phoneNumber = "\(callingCode)\(phoneNumberText)" | ||||
|         guard let localNumber = PhoneNumber.tryParsePhoneNumber(fromUserSpecifiedText: phoneNumber), | ||||
|             localNumber.toE164().count > 0, | ||||
|             PhoneNumberValidator().isValidForRegistration(phoneNumber: localNumber) else { | ||||
|                 OWSAlerts.showAlert(title: | ||||
|                     NSLocalizedString("REGISTRATION_VIEW_INVALID_PHONE_NUMBER_ALERT_TITLE", | ||||
|                                       comment: "Title of alert indicating that users needs to enter a valid phone number to register."), | ||||
|                     message: | ||||
|                     NSLocalizedString("REGISTRATION_VIEW_INVALID_PHONE_NUMBER_ALERT_MESSAGE", | ||||
|                                       comment: "Message of alert indicating that users needs to enter a valid phone number to register.")) | ||||
|                 return | ||||
|         } | ||||
|         let parsedPhoneNumber = localNumber.toE164() | ||||
| 
 | ||||
|         if UIDevice.current.isIPad { | ||||
|             let countryCode = self.countryCode | ||||
|             OWSAlerts.showConfirmationAlert(title: NSLocalizedString("REGISTRATION_IPAD_CONFIRM_TITLE", | ||||
|                                                                       comment: "alert title when registering an iPad"), | ||||
|                                             message: NSLocalizedString("REGISTRATION_IPAD_CONFIRM_BODY", | ||||
|                                                                         comment: "alert body when registering an iPad"), | ||||
|                                             proceedTitle: NSLocalizedString("REGISTRATION_IPAD_CONFIRM_BUTTON", | ||||
|                                                                              comment: "button text to proceed with registration when on an iPad"), | ||||
|                                             proceedAction: { (_) in | ||||
|                                                 self.sendCode(parsedPhoneNumber: parsedPhoneNumber, | ||||
|                                                               phoneNumberText: phoneNumberText, | ||||
|                                                               countryCode: countryCode) | ||||
|             }) | ||||
|         } else { | ||||
|             sendCode(parsedPhoneNumber: parsedPhoneNumber, | ||||
|                      phoneNumberText: phoneNumberText, | ||||
|                      countryCode: countryCode) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private func sendCode(parsedPhoneNumber: String, | ||||
|                           phoneNumberText: String, | ||||
|                           countryCode: String) { | ||||
|         ModalActivityIndicatorViewController.present(fromViewController: self, | ||||
|                                                      canCancel: true) { (modal) in | ||||
|                                                         self.setLastRegisteredCountryCode(value: countryCode) | ||||
|                                                         self.setLastRegisteredPhoneNumber(value: phoneNumberText) | ||||
| 
 | ||||
|                                                         self.tsAccountManager.register(withPhoneNumber: parsedPhoneNumber, | ||||
|                                                                                        success: { | ||||
|                                                                                         DispatchQueue.main.async { | ||||
|                                                                                             modal.dismiss(completion: { | ||||
|                                                                                                 self.registrationSucceeded() | ||||
|                                                                                             }) | ||||
|                                                                                         } | ||||
|                                                         }, failure: { (error) in | ||||
|                                                             Logger.error("Error: \(error)") | ||||
| 
 | ||||
|                                                             DispatchQueue.main.async { | ||||
|                                                                 modal.dismiss(completion: { | ||||
|                                                                     self.registrationFailed(error: error as NSError) | ||||
|                                                                 }) | ||||
|                                                             } | ||||
|                                                         }, smsVerification: true) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private func registrationSucceeded() { | ||||
|         self.onboardingController.onboardingPhoneNumberDidComplete(viewController: self) | ||||
|     } | ||||
| 
 | ||||
|     private func registrationFailed(error: NSError) { | ||||
|         if error.code == 400 { | ||||
|             OWSAlerts.showAlert(title: NSLocalizedString("REGISTRATION_ERROR", comment: ""), | ||||
|                                 message: NSLocalizedString("REGISTRATION_NON_VALID_NUMBER", comment: "")) | ||||
| 
 | ||||
|         } else { | ||||
|             OWSAlerts.showAlert(title: error.localizedDescription, | ||||
|                                 message: error.localizedRecoverySuggestion) | ||||
|         } | ||||
| 
 | ||||
|         phoneNumberTextField.becomeFirstResponder() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // MARK: - | ||||
| 
 | ||||
| extension OnboardingPhoneNumberViewController: UITextFieldDelegate { | ||||
|     public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { | ||||
|         var prefix = self.callingCode | ||||
|         if prefix.hasPrefix(COUNTRY_CODE_PREFIX) { | ||||
|             prefix = prefix.substring(from: COUNTRY_CODE_PREFIX.count) | ||||
|         } | ||||
|         ViewControllerUtils.phoneNumber(textField, shouldChangeCharactersIn: range, replacementString: string, countryCode: countryCode, prefix: prefix) | ||||
| 
 | ||||
|         // Inform our caller that we took care of performing the change. | ||||
|         return false | ||||
|     } | ||||
| 
 | ||||
|     public func textFieldShouldReturn(_ textField: UITextField) -> Bool { | ||||
|         didTapRegisterButton() | ||||
|         textField.resignFirstResponder() | ||||
|         return false | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // MARK: - | ||||
| 
 | ||||
| extension OnboardingPhoneNumberViewController: CountryCodeViewControllerDelegate { | ||||
|     public func countryCodeViewController(_ vc: CountryCodeViewController, didSelectCountryCode countryCode: String, countryName: String, callingCode: String) { | ||||
|         guard countryCode.count > 0 else { | ||||
|             owsFailDebug("Invalid country code.") | ||||
|             return | ||||
|         } | ||||
|         guard countryName.count > 0 else { | ||||
|             owsFailDebug("Invalid country name.") | ||||
|             return | ||||
|         } | ||||
|         guard callingCode.count > 0 else { | ||||
|             owsFailDebug("Invalid calling code.") | ||||
|             return | ||||
|         } | ||||
| 
 | ||||
|         update(withCountryName: countryName, callingCode: callingCode, countryCode: countryCode) | ||||
| 
 | ||||
|             // Trigger the formatting logic with a no-op edit. | ||||
|         _ = textField(phoneNumberTextField, shouldChangeCharactersIn: NSRange(location: 0, length: 0), replacementString: "") | ||||
|     } | ||||
| } | ||||
					Loading…
					
					
				
		Reference in New Issue