diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index 09a31a78e..29c30b0fe 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WordPressAuthenticator" - s.version = "1.8.0-beta.2" + s.version = "1.8.0-beta.3" s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps." s.description = <<-DESC diff --git a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorConfiguration.swift b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorConfiguration.swift index 8b7d9c16a..a33b90296 100644 --- a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorConfiguration.swift +++ b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorConfiguration.swift @@ -56,6 +56,10 @@ public struct WordPressAuthenticatorConfiguration { /// and verified. /// let showLoginOptionsFromSiteAddress: Bool + + /// Flag indicating if the Sign In With Apple option should be displayed. + /// + let enableSignInWithApple: Bool /// Designated Initializer /// @@ -70,7 +74,8 @@ public struct WordPressAuthenticatorConfiguration { googleLoginScheme: String, userAgent: String, showNewLoginFlow: Bool = false, - showLoginOptionsFromSiteAddress: Bool = false) { + showLoginOptionsFromSiteAddress: Bool = false, + enableSignInWithApple: Bool = false) { self.wpcomClientId = wpcomClientId self.wpcomSecret = wpcomSecret @@ -84,5 +89,6 @@ public struct WordPressAuthenticatorConfiguration { self.userAgent = userAgent self.showNewLoginFlow = showNewLoginFlow self.showLoginOptionsFromSiteAddress = showLoginOptionsFromSiteAddress + self.enableSignInWithApple = enableSignInWithApple } } diff --git a/WordPressAuthenticator/Extensions/WPStyleGuide+Login.swift b/WordPressAuthenticator/Extensions/WPStyleGuide+Login.swift index df42529e5..10bb8742e 100644 --- a/WordPressAuthenticator/Extensions/WPStyleGuide+Login.swift +++ b/WordPressAuthenticator/Extensions/WPStyleGuide+Login.swift @@ -1,6 +1,7 @@ import WordPressShared import WordPressUI import Gridicons +import AuthenticationServices final class SubheadlineButton: UIButton { override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { @@ -16,7 +17,10 @@ final class SubheadlineButton: UIButton { extension WPStyleGuide { private struct Constants { - static let buttonMinHeight: CGFloat = 40.0 + // This matches the button height in NUXButtonView.storyboard + static let buttonMinHeight: CGFloat = 50.0 + + static let textButtonMinHeight: CGFloat = 40.0 static let googleIconOffset: CGFloat = -1.0 static let domainsIconPaddingToRemove: CGFloat = 2.0 static let domainsIconSize = CGSize(width: 18, height: 18) @@ -112,6 +116,24 @@ extension WPStyleGuide { return textButton(normal: attrStrNormal, highlighted: attrStrHighlight, font: font) } + /// Creates a button for Apple Sign-in + /// + /// - Returns: A properly styled UIControl + /// + + class func appleLoginButton() -> UIControl { + #if XCODE11 + if #available(iOS 13.0, *) { + let appleButton = ASAuthorizationAppleIDButton(authorizationButtonType: .continue, authorizationButtonStyle: .black) + appleButton.translatesAutoresizingMaskIntoConstraints = false + appleButton.heightAnchor.constraint(greaterThanOrEqualToConstant: Constants.buttonMinHeight).isActive = true + return appleButton + } + #endif + + return UIControl() + } + /// Creates a button for Self-hosted Login /// /// - Returns: A properly styled UIButton @@ -189,7 +211,7 @@ extension WPStyleGuide { // for the titleLabel's height. button.titleLabel?.topAnchor.constraint(equalTo: button.topAnchor, constant: Constants.verticalLabelSpacing).isActive = true button.titleLabel?.bottomAnchor.constraint(equalTo: button.bottomAnchor, constant: -Constants.verticalLabelSpacing).isActive = true - button.heightAnchor.constraint(greaterThanOrEqualToConstant: Constants.buttonMinHeight).isActive = true + button.heightAnchor.constraint(greaterThanOrEqualToConstant: Constants.textButtonMinHeight).isActive = true button.setAttributedTitle(normalString, for: .normal) diff --git a/WordPressAuthenticator/Signin/LoginPrologueLoginMethodViewController.swift b/WordPressAuthenticator/Signin/LoginPrologueLoginMethodViewController.swift index 16cc7aae2..56e61d7e9 100644 --- a/WordPressAuthenticator/Signin/LoginPrologueLoginMethodViewController.swift +++ b/WordPressAuthenticator/Signin/LoginPrologueLoginMethodViewController.swift @@ -11,6 +11,7 @@ class LoginPrologueLoginMethodViewController: NUXViewController { open var emailTapped: (() -> Void)? open var googleTapped: (() -> Void)? open var selfHostedTapped: (() -> Void)? + open var appleTapped: (() -> Void)? override func prepare(for segue: UIStoryboardSegue, sender: Any?) { super.prepare(for: segue, sender: sender) @@ -34,15 +35,14 @@ class LoginPrologueLoginMethodViewController: NUXViewController { guard let buttonViewController = buttonViewController else { return } - - let wordpressTitle = NSLocalizedString("Continue with WordPress.com", comment: "Button title. Tapping begins our normal log in process.") - let googleTitle = NSLocalizedString("Continue with Google", comment: "Button title. Tapping begins log in using Google.") + let wordpressTitle = NSLocalizedString("Continue with WordPress.com", comment: "Button title. Tapping begins our normal log in process.") buttonViewController.setupTopButton(title: wordpressTitle, isPrimary: false, accessibilityIdentifier: "Log in with Email Button") { [weak self] in self?.dismiss(animated: true) self?.emailTapped?() } + let googleTitle = NSLocalizedString("Continue with Google", comment: "Button title. Tapping begins log in using Google.") buttonViewController.setupBottomButton(title: googleTitle, isPrimary: false, accessibilityIdentifier: "Log in with Google Button") { [weak self] in defer { WordPressAuthenticator.track(.loginSocialButtonClick) @@ -58,6 +58,16 @@ class LoginPrologueLoginMethodViewController: NUXViewController { selfHostedLoginButton.addTarget(self, action: #selector(handleSelfHostedButtonTapped), for: .touchUpInside) } + if WordPressAuthenticator.shared.configuration.enableSignInWithApple { + #if XCODE11 + if #available(iOS 13.0, *) { + let appleButton = WPStyleGuide.appleLoginButton() + appleButton.addTarget(self, action: #selector(handleAppleButtonTapped), for: .touchDown) + buttonViewController.stackView?.insertArrangedSubview(appleButton, at: 0) + } + #endif + } + buttonViewController.backgroundColor = WordPressAuthenticator.shared.style.viewControllerBackgroundColor } @@ -70,4 +80,9 @@ class LoginPrologueLoginMethodViewController: NUXViewController { selfHostedTapped?() } + @objc func handleAppleButtonTapped() { + dismiss(animated: true) + appleTapped?() + } + } diff --git a/WordPressAuthenticator/Signin/LoginPrologueViewController.swift b/WordPressAuthenticator/Signin/LoginPrologueViewController.swift index 1dbdf1067..2ffd84eac 100644 --- a/WordPressAuthenticator/Signin/LoginPrologueViewController.swift +++ b/WordPressAuthenticator/Signin/LoginPrologueViewController.swift @@ -66,7 +66,10 @@ class LoginPrologueViewController: LoginViewController { vc.selfHostedTapped = { [weak self] in self?.performSegue(withIdentifier: NUXViewController.SegueIdentifier.showSelfHostedLogin.rawValue, sender: self) } - + vc.appleTapped = { [weak self] in + self?.appleTapped() + } + vc.modalPresentationStyle = .custom } } @@ -110,4 +113,9 @@ class LoginPrologueViewController: LoginViewController { WordPressAuthenticator.track(.signupButtonTapped) performSegue(withIdentifier: NUXViewController.SegueIdentifier.showSignupMethod.rawValue, sender: self) } + + private func appleTapped() { + print("Login Prologue: Apple tapped.") + } + } diff --git a/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift b/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift index 66af8af7b..1a6cf9062 100644 --- a/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift +++ b/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift @@ -277,11 +277,18 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder vc.googleTapped = { [weak self] in self?.performSegue(withIdentifier: .showGoogle, sender: self) } + vc.appleTapped = { [weak self] in + self?.appleTapped() + } vc.modalPresentationStyle = .custom } } - + + private func appleTapped() { + print("Login Site Address: Apple tapped.") + } + /// Whether the form can be submitted. /// @objc func canSubmit() -> Bool { @@ -322,7 +329,6 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder } } - @IBAction func handleSubmitButtonTapped(_ sender: UIButton) { validateForm() }