From a5456ffdc792fb513886ef098609ee6cc374cc6a Mon Sep 17 00:00:00 2001 From: James Frost Date: Wed, 24 Feb 2021 11:53:12 +0000 Subject: [PATCH 01/23] Stop tracking prologue step based on view presentation --- .../Signin/LoginPrologueViewController.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/WordPressAuthenticator/Signin/LoginPrologueViewController.swift b/WordPressAuthenticator/Signin/LoginPrologueViewController.swift index c7b0ea18c..2c9c024c6 100644 --- a/WordPressAuthenticator/Signin/LoginPrologueViewController.swift +++ b/WordPressAuthenticator/Signin/LoginPrologueViewController.swift @@ -97,9 +97,10 @@ class LoginPrologueViewController: LoginViewController { WordPressAuthenticator.track(.loginPrologueViewed) tracker.set(flow: .prologue) - - if isBeingPresentedInAnyWay { + + if !prologueFlowTracked { tracker.track(step: .prologue) + prologueFlowTracked = true } else { tracker.set(step: .prologue) } From 0c22ec2caf68bef6fc23deb96666a11afc1a4bb7 Mon Sep 17 00:00:00 2001 From: James Frost Date: Wed, 24 Feb 2021 11:57:15 +0000 Subject: [PATCH 02/23] Bumped podspec version to 1.35.2 --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index 9bff9a952..b918abca7 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WordPressAuthenticator" - s.version = "1.35.1" + s.version = "1.35.2" s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps." s.description = <<-DESC From 990b08a50c367036d81e1242666d0d8531cbe632 Mon Sep 17 00:00:00 2001 From: Emily Laguna Date: Tue, 2 Mar 2021 16:54:54 -0500 Subject: [PATCH 03/23] Change reads to blogs --- .../Signin/LoginProloguePromoViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator/Signin/LoginProloguePromoViewController.swift b/WordPressAuthenticator/Signin/LoginProloguePromoViewController.swift index e847b62e4..af0758560 100644 --- a/WordPressAuthenticator/Signin/LoginProloguePromoViewController.swift +++ b/WordPressAuthenticator/Signin/LoginProloguePromoViewController.swift @@ -58,7 +58,7 @@ class LoginProloguePromoViewController: UIViewController { case .analytics: return NSLocalizedString("Watch your audience grow with in-depth analytics.", comment: "Shown in the prologue carousel (promotional screens) during first launch.") case .discover: - return NSLocalizedString("Follow your favorite sites and discover new reads.", comment: "Shown in the prologue carousel (promotional screens) during first launch.") + return NSLocalizedString("Follow your favorite sites and discover new blogs.", comment: "Shown in the prologue carousel (promotional screens) during first launch.") } } From 73de81462fbc0444b1cad13b408a25a5a1798d38 Mon Sep 17 00:00:00 2001 From: Emily Laguna Date: Tue, 2 Mar 2021 16:58:18 -0500 Subject: [PATCH 04/23] Bump to 1.36.8-beta.1 --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index b918abca7..4dc9110b9 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WordPressAuthenticator" - s.version = "1.35.2" + s.version = "1.36.0-beta.1" s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps." s.description = <<-DESC From 015b8a6354ac3579c6721e7be944e8e8c39ea662 Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Fri, 12 Mar 2021 18:27:20 +0100 Subject: [PATCH 05/23] Test new spec repo push command --- .circleci/config.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b8c41f37e..ae37480b8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2.1 orbs: # Using 1.0 of our Orbs means it will use the latest 1.0.x version from https://github.com/wordpress-mobile/circleci-orbs - ios: wordpress-mobile/ios@1.0 + ios: wordpress-mobile/ios@dev:pod-repo-push workflows: test_and_validate: @@ -21,6 +21,16 @@ workflows: xcode-version: "12.2.0" podspec-path: WordPressAuthenticator.podspec bundle-install: true + - ios/publish-podspec: + name: Publish to a8c Spec Repo + xcode-version: "12.2.0" + podspec-path: WordPressAuthenticator.podspec + spec-repo: https://github.com/wordpress-mobile/cocoapods-specs.git + bundle-install: true + post-to-slack: false + filters: + branches: + only: /test-spec-repo/ - ios/publish-podspec: name: Publish to Trunk xcode-version: "12.2.0" From 678abbb659c36844dd9b4572cffe5bf21d9439e9 Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Mon, 15 Mar 2021 14:54:30 +0100 Subject: [PATCH 06/23] Update CI config to target --- .circleci/config.yml | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ae37480b8..bea0ab5c1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,12 +4,22 @@ orbs: # Using 1.0 of our Orbs means it will use the latest 1.0.x version from https://github.com/wordpress-mobile/circleci-orbs ios: wordpress-mobile/ios@dev:pod-repo-push +# YAML anchors for some common/repeated values +x-common-params: + - &xcode-version "12.2.0" + - &podspec "WordPressAuthenticator.podspec" + - &on-tags-only + tags: + only: /.*/ + branches: + ignore: /.*/ + workflows: test_and_validate: jobs: - ios/test: name: Test - xcode-version: "12.2.0" + xcode-version: *xcode-version workspace: WordPressAuthenticator.xcworkspace scheme: WordPressAuthenticator device: iPhone 11 @@ -18,27 +28,21 @@ workflows: pod-install: true - ios/validate-podspec: name: Validate Podspec - xcode-version: "12.2.0" - podspec-path: WordPressAuthenticator.podspec + xcode-version: *xcode-version + podspec-path: *podspec bundle-install: true - ios/publish-podspec: name: Publish to a8c Spec Repo - xcode-version: "12.2.0" - podspec-path: WordPressAuthenticator.podspec + xcode-version: *xcode-version + podspec-path: *podspec spec-repo: https://github.com/wordpress-mobile/cocoapods-specs.git bundle-install: true post-to-slack: false - filters: - branches: - only: /test-spec-repo/ + filters: *on-tags-only - ios/publish-podspec: name: Publish to Trunk - xcode-version: "12.2.0" - podspec-path: WordPressAuthenticator.podspec + xcode-version: *xcode-version + podspec-path: *podspec bundle-install: true post-to-slack: true - filters: - tags: - only: /.*/ - branches: - ignore: /.*/ + filters: *on-tags-only From 77f736bcc2ecbd6db08286d5a8642074d832187f Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Tue, 16 Mar 2021 13:20:05 +0100 Subject: [PATCH 07/23] Restore ios orb import to 1.0 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index bea0ab5c1..257700f52 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2.1 orbs: # Using 1.0 of our Orbs means it will use the latest 1.0.x version from https://github.com/wordpress-mobile/circleci-orbs - ios: wordpress-mobile/ios@dev:pod-repo-push + ios: wordpress-mobile/ios@1.0 # YAML anchors for some common/repeated values x-common-params: From 47a3dc19b98ce31a2b5fe5ee1349fd9a28a3cff6 Mon Sep 17 00:00:00 2001 From: rachelmcr Date: Thu, 18 Mar 2021 15:44:26 +0000 Subject: [PATCH 08/23] Compare CGColor values instead of UIColor objects --- WordPressAuthenticator/Signin/LoginPrologueViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator/Signin/LoginPrologueViewController.swift b/WordPressAuthenticator/Signin/LoginPrologueViewController.swift index 2c9c024c6..d201b1626 100644 --- a/WordPressAuthenticator/Signin/LoginPrologueViewController.swift +++ b/WordPressAuthenticator/Signin/LoginPrologueViewController.swift @@ -275,7 +275,7 @@ class LoginPrologueViewController: LoginViewController { /// 2. Set the background color of the view controller to prologueViewBackgroundColor let prologueViewBackgroundColor = WordPressAuthenticator.shared.unifiedStyle?.prologueViewBackgroundColor ?? .clear - guard prologueViewBackgroundColor == buttonsBackgroundColor else { + guard prologueViewBackgroundColor.cgColor == buttonsBackgroundColor.cgColor else { buttonBlurEffectView.effect = UIBlurEffect(style: blurEffect) return } From 654349f5bb5ef48d3b19388840c183e33d9faf4a Mon Sep 17 00:00:00 2001 From: rachelmcr Date: Thu, 18 Mar 2021 15:45:14 +0000 Subject: [PATCH 09/23] Bump version to 1.36.0-beta.2 --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index 4dc9110b9..9cc33fd88 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WordPressAuthenticator" - s.version = "1.36.0-beta.1" + s.version = "1.36.0-beta.2" s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps." s.description = <<-DESC From c71f031cb272b90189073798c4c57b0adde2a4d8 Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Mon, 22 Mar 2021 20:11:04 +0100 Subject: [PATCH 10/23] Standardize podspec format --- WordPressAuthenticator.podspec | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index 9cc33fd88..6f26bc00e 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -1,20 +1,23 @@ Pod::Spec.new do |s| s.name = "WordPressAuthenticator" s.version = "1.36.0-beta.2" - s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps." + s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps." s.description = <<-DESC This framework encapsulates everything required to display the Authentication UI and perform authentication against WordPress.com and WordPress.org sites. - Plus: WordPress.com *signup* is supported. + Plus: WordPress.com *signup* is supported. DESC - s.homepage = "https://github.com/wordpress-mobile/WordPressAuthenticator-iOS" - s.license = "GPLv2" - s.author = { "WordPress" => "mobile@automattic.com" } + s.homepage = "http://apps.wordpress.com" + s.license = { :type => "GPLv2", :file => "LICENSE" } + s.author = { "Automattic" => "mobile@automattic.com" } + s.social_media_url = "http://twitter.com/WordPressiOS" + s.platform = :ios, "11.0" s.swift_version = '4.2' + s.source = { :git => "https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git", :tag => s.version.to_s } s.source_files = 'WordPressAuthenticator/**/*.{h,m,swift}' s.private_header_files = "WordPressAuthenticator/Private/*.h" @@ -26,7 +29,6 @@ Pod::Spec.new do |s| 'WordPressAuthenticator/**/*.{storyboard,xib}' ] } - s.requires_arc = true s.static_framework = true # This is needed because GoogleSignIn vendors a static framework s.header_dir = 'WordPressAuthenticator' @@ -36,7 +38,6 @@ Pod::Spec.new do |s| s.dependency 'lottie-ios', '~> 3.1.6' s.dependency 'NSURL+IDN', '0.4' s.dependency 'SVProgressHUD', '~> 2.2.5' - s.dependency 'Gridicons', '~> 1.0' s.dependency 'GoogleSignIn', '~> 5.0.2' @@ -49,5 +50,4 @@ Pod::Spec.new do |s| # Fixing arm64 issue with Xcode 12: https://github.com/CocoaPods/CocoaPods/issues/10104 s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' } s.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' } - end From 460306d3958d7ba53374b3f6bc6b77309a0b690f Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Tue, 23 Mar 2021 20:09:03 +0100 Subject: [PATCH 11/23] Update WordPressAuthenticator.podspec Co-authored-by: Gio Lodi --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index 6f26bc00e..dde58105a 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -13,7 +13,7 @@ Pod::Spec.new do |s| s.homepage = "http://apps.wordpress.com" s.license = { :type => "GPLv2", :file => "LICENSE" } s.author = { "Automattic" => "mobile@automattic.com" } - s.social_media_url = "http://twitter.com/WordPressiOS" + s.social_media_url = "https://twitter.com/automattic" s.platform = :ios, "11.0" s.swift_version = '4.2' From b3225b9f225aecd308cb32eb7c1ffb556067e991 Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Tue, 23 Mar 2021 20:09:18 +0100 Subject: [PATCH 12/23] Update WordPressAuthenticator.podspec Co-authored-by: Gio Lodi --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index dde58105a..68b7110fb 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -10,7 +10,7 @@ Pod::Spec.new do |s| Plus: WordPress.com *signup* is supported. DESC - s.homepage = "http://apps.wordpress.com" + s.homepage = "https://apps.wordpress.com" s.license = { :type => "GPLv2", :file => "LICENSE" } s.author = { "Automattic" => "mobile@automattic.com" } s.social_media_url = "https://twitter.com/automattic" From feb0a2aa17f1e8f536c72412503e5e0f980b3597 Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Tue, 23 Mar 2021 20:14:15 +0100 Subject: [PATCH 13/23] Update homepage metadata --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index 68b7110fb..6c5623f9f 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -10,7 +10,7 @@ Pod::Spec.new do |s| Plus: WordPress.com *signup* is supported. DESC - s.homepage = "https://apps.wordpress.com" + s.homepage = "https://github.com/wordpress-mobile/WordPressAuthenticator-iOS" s.license = { :type => "GPLv2", :file => "LICENSE" } s.author = { "Automattic" => "mobile@automattic.com" } s.social_media_url = "https://twitter.com/automattic" From 3b9e72663c6cf2cd2442fb53ee96fc779e54f89b Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Fri, 26 Mar 2021 15:01:21 +0100 Subject: [PATCH 14/23] Adjust attributes order --- WordPressAuthenticator.podspec | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index 6c5623f9f..49803576e 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -32,6 +32,10 @@ Pod::Spec.new do |s| s.static_framework = true # This is needed because GoogleSignIn vendors a static framework s.header_dir = 'WordPressAuthenticator' + # Fixing arm64 issue with Xcode 12: https://github.com/CocoaPods/CocoaPods/issues/10104 + s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' } + s.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' } + s.dependency '1PasswordExtension', '~> 1.8.6' s.dependency 'Alamofire', '~> 4.8' s.dependency 'CocoaLumberjack', '~> 3.5' @@ -46,8 +50,4 @@ Pod::Spec.new do |s| s.dependency 'WordPressUI', '~> 1.7-beta' s.dependency 'WordPressKit', '~> 4.18-beta' # Don't change this until we hit 5.0 in WPKit s.dependency 'WordPressShared', '~> 1.12-beta' # Don't change this until we hit 2.0 in WPShared - - # Fixing arm64 issue with Xcode 12: https://github.com/CocoaPods/CocoaPods/issues/10104 - s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' } - s.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' } end From 797bd907b44d8ab15ece56e0bf36437bf6c50b7c Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Fri, 26 Mar 2021 16:19:20 +0100 Subject: [PATCH 15/23] Adjust formatting --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index 49803576e..023a6c39b 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| and perform authentication against WordPress.com and WordPress.org sites. Plus: WordPress.com *signup* is supported. - DESC + DESC s.homepage = "https://github.com/wordpress-mobile/WordPressAuthenticator-iOS" s.license = { :type => "GPLv2", :file => "LICENSE" } From 773916c635a612fec4871655e63c09744c2a1d89 Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Fri, 26 Mar 2021 17:13:13 +0100 Subject: [PATCH 16/23] Update author to WPM and remove social_media_url After discussing it with @elibud and @jkmassel --- WordPressAuthenticator.podspec | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index 023a6c39b..ffbf5a7b1 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -12,8 +12,7 @@ Pod::Spec.new do |s| s.homepage = "https://github.com/wordpress-mobile/WordPressAuthenticator-iOS" s.license = { :type => "GPLv2", :file => "LICENSE" } - s.author = { "Automattic" => "mobile@automattic.com" } - s.social_media_url = "https://twitter.com/automattic" + s.author = { "The WordPress Mobile Team" => "mobile@automattic.com" } s.platform = :ios, "11.0" s.swift_version = '4.2' From b998ba013df0071555e8521df8531418642f224d Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Fri, 26 Mar 2021 20:22:03 +0100 Subject: [PATCH 17/23] Fix author email --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index ffbf5a7b1..b06b91885 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -12,7 +12,7 @@ Pod::Spec.new do |s| s.homepage = "https://github.com/wordpress-mobile/WordPressAuthenticator-iOS" s.license = { :type => "GPLv2", :file => "LICENSE" } - s.author = { "The WordPress Mobile Team" => "mobile@automattic.com" } + s.author = { "The WordPress Mobile Team" => "mobile@wordpress.org" } s.platform = :ios, "11.0" s.swift_version = '4.2' From c03682599606e28298c472327f80a459510f12fb Mon Sep 17 00:00:00 2001 From: Stephenie Harris Date: Mon, 29 Mar 2021 14:25:58 -0600 Subject: [PATCH 18/23] Update regex pattern to remove everything after wp-admin. --- WordPressAuthenticator.podspec | 2 +- .../WordPressAuthenticator.swift | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index b06b91885..a17173fb2 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WordPressAuthenticator" - s.version = "1.36.0-beta.2" + s.version = "1.36.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/WordPressAuthenticator.swift b/WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift index 19adecb99..e12ba201f 100644 --- a/WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift +++ b/WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift @@ -418,25 +418,26 @@ import WordPressKit /// - Returns: The base URL or an empty string. /// class func baseSiteURL(string: String) -> String { - guard let siteURL = NSURL(string: NSURL.idnEncodedURL(string)), string.count > 0 else { + + guard !string.isEmpty, + let siteURL = NSURL(string: NSURL.idnEncodedURL(string)), + var path = siteURL.absoluteString else { return "" } - var path = siteURL.absoluteString! let isSiteURLSchemeEmpty = siteURL.scheme == nil || siteURL.scheme!.isEmpty - if path.isWordPressComPath() { - if isSiteURLSchemeEmpty { - path = "https://\(path)" - } else if path.range(of: "http://") != nil { - path = path.replacingOccurrences(of: "http://", with: "https://") - } - } else if isSiteURLSchemeEmpty { + if isSiteURLSchemeEmpty { path = "https://\(path)" + } else if path.isWordPressComPath() && path.range(of: "http://") != nil { + path = path.replacingOccurrences(of: "http://", with: "https://") } path.removeSuffix("/wp-login.php") - try? path.removeSuffix(pattern: "/wp-admin/?") + + // Remove wp-admin and everything after it. + try? path.removeSuffix(pattern: "/wp-admin(.*)") + path.removeSuffix("/") return path @@ -444,7 +445,6 @@ import WordPressKit // MARK: - Other Helpers - /// Opens Safari to display the forgot password page for a wpcom or self-hosted /// based on the passed LoginFields instance. /// From 302ee6458ce9d2e6556c165d9c38527bfec40c89 Mon Sep 17 00:00:00 2001 From: Stephenie Harris Date: Mon, 29 Mar 2021 14:26:40 -0600 Subject: [PATCH 19/23] swiftlint autocorrect changes. --- .../AuthenticatorAnalyticsTracker.swift | 184 +++++++++--------- .../WordPressAuthenticator+Errors.swift | 1 - ...WordPressAuthenticator+Notifications.swift | 2 +- .../WordPressAuthenticator.swift | 80 ++++---- .../WordPressAuthenticatorConfiguration.swift | 10 +- ...rdPressAuthenticatorDelegateProtocol.swift | 2 - ...WordPressAuthenticatorDisplayStrings.swift | 5 +- .../WordPressAuthenticatorResult.swift | 1 - .../WordPressAuthenticatorStyles.swift | 10 +- .../WordPressSupportSourceTag.swift | 3 +- .../Credentials/WordPressComCredentials.swift | 5 +- .../Credentials/WordPressOrgCredentials.swift | 1 - .../Email Client Picker/AppSelector.swift | 8 +- .../LinkMailPresenter.swift | 1 - .../Email Client Picker/URLHandler.swift | 3 +- .../FancyAlertViewController+LoginError.swift | 14 +- .../Extensions/NSObject+Helpers.swift | 4 +- .../Extensions/UIImage+Assets.swift | 1 - .../Extensions/UIPasteboard+Detect.swift | 2 +- .../Extensions/UIStoryboard+Helpers.swift | 5 +- .../Extensions/UIView+AuthHelpers.swift | 1 - .../UIViewController+Dismissal.swift | 2 +- .../Extensions/UIViewController+Helpers.swift | 3 +- .../Extensions/WPStyleGuide+Login.swift | 36 ++-- .../Logging/CocoaLumberjack.swift | 2 +- .../Model/LoginFields+Validation.swift | 2 +- .../Model/LoginFields.swift | 7 +- .../Model/WordPressComSiteInfo.swift | 5 +- WordPressAuthenticator/NUX/NUXButton.swift | 8 +- .../NUX/NUXButtonViewController.swift | 8 +- .../NUX/NUXKeyboardResponder.swift | 7 - .../NUX/NUXLinkAuthViewController.swift | 8 +- .../NUX/NUXLinkMailViewController.swift | 3 - .../NUX/NUXNavigationController.swift | 1 - .../NUX/NUXViewController.swift | 3 +- .../NUX/NUXViewControllerBase.swift | 28 ++- .../NUX/WPHelpIndicatorView.swift | 8 +- .../Navigation/NavigateToEnterAccount.swift | 1 - .../Navigation/NavigateToEnterSite.swift | 2 - .../Navigation/NavigateToRoot.swift | 1 - .../Navigation/NavigationCommand.swift | 1 - .../Services/LoginFacade.swift | 18 +- .../Services/OnePasswordFacade.swift | 3 - .../Services/OnePasswordResultsFetcher.swift | 1 - .../Services/SafariCredentialsService.swift | 3 +- .../Services/SignupService.swift | 15 +- .../Services/SocialService.swift | 2 +- .../Services/WordPressComAccountService.swift | 6 +- .../Services/WordPressComBlogService.swift | 9 +- .../Signin/AppleAuthenticator.swift | 52 ++--- .../Signin/Login2FAViewController.swift | 29 +-- .../Signin/LoginEmailViewController.swift | 43 ++-- .../LoginLinkRequestViewController.swift | 4 - .../Signin/LoginNavigationController.swift | 3 +- ...ginPrologueLoginMethodViewController.swift | 19 +- .../LoginProloguePageViewController.swift | 2 - .../LoginProloguePromoViewController.swift | 2 - ...inPrologueSignupMethodViewController.swift | 13 +- .../Signin/LoginPrologueViewController.swift | 74 +++---- .../LoginSelfHostedViewController.swift | 29 --- .../LoginSiteAddressViewController.swift | 39 ++-- .../Signin/LoginSocialErrorCell.swift | 7 +- .../LoginSocialErrorViewController.swift | 21 +- .../LoginUsernamePasswordViewController.swift | 27 --- .../Signin/LoginViewController.swift | 98 +++++----- .../Signin/LoginWPComViewController.swift | 16 +- .../Signup/SignupEmailViewController.swift | 11 +- .../Signup/SignupGoogleViewController.swift | 5 +- .../Signup/SignupNavigationController.swift | 1 - .../UI/CircularImageView.swift | 1 - .../UI/LoginTextField.swift | 2 +- .../UI/SearchTableViewCell.swift | 5 - .../UI/SiteInfoHeaderView.swift | 5 - .../Unified Auth/GoogleAuthenticator.swift | 59 +++--- .../StoredCredentialsAuthenticator.swift | 60 +++--- .../StoredCredentialsPicker.swift | 14 +- .../2FA/TwoFAViewController.swift | 74 +++---- .../GetStartedViewController.swift | 162 +++++++-------- .../Google/GoogleAuthViewController.swift | 2 +- ...ogleSignupConfirmationViewController.swift | 36 ++-- .../Login/LoginMagicLinkViewController.swift | 13 +- .../Password/PasswordViewController.swift | 128 ++++++------ .../GravatarEmailTableViewCell.swift | 23 ++- .../TextFieldTableViewCell.swift | 6 +- .../Reusable Views/TextFieldTableViewCell.xib | 14 +- .../TextLabelTableViewCell.swift | 1 - .../TextLinkButtonTableViewCell.swift | 18 +- .../TextWithLinkTableViewCell.swift | 5 +- .../SignupMagicLinkViewController.swift | 13 +- .../Sign up/UnifiedSignupViewController.swift | 16 +- .../SiteAddressViewController.swift | 58 +++--- .../SiteCredentialsViewController.swift | 20 +- .../Analytics/AnalyticsTrackerTests.swift | 156 +++++++-------- .../Authenticator/PasteboardTests.swift | 8 +- ...rdPressAuthenticatorDisplayTextTests.swift | 2 +- .../WordPressAuthenticatorTests.swift | 5 +- .../WordPressSourceTagTests.swift | 44 ++--- .../Credentials/CredentialsTests.swift | 38 ++-- .../AppSelectorTests.swift | 3 +- .../WordpressAuthenticatorProvider.swift | 24 ++- .../Model/LoginFieldsValidationTests.swift | 5 +- 101 files changed, 897 insertions(+), 1154 deletions(-) diff --git a/WordPressAuthenticator/Analytics/AuthenticatorAnalyticsTracker.swift b/WordPressAuthenticator/Analytics/AuthenticatorAnalyticsTracker.swift index 4cea4a3fc..07aebbfdb 100644 --- a/WordPressAuthenticator/Analytics/AuthenticatorAnalyticsTracker.swift +++ b/WordPressAuthenticator/Analytics/AuthenticatorAnalyticsTracker.swift @@ -3,21 +3,21 @@ import Foundation /// Implements the analytics tracking logic for our sign in flow. /// public class AuthenticatorAnalyticsTracker { - + private static let defaultSource: Source = .default private static let defaultFlow: Flow = .prologue private static let defaultStep: Step = .prologue - + /// The method used for analytics tracking. Useful for overriding in automated tests. /// - typealias TrackerMethod = (_ event: AnalyticsEvent) -> () + typealias TrackerMethod = (_ event: AnalyticsEvent) -> Void public enum EventType: String { case step = "unified_login_step" case interaction = "unified_login_interaction" case failure = "unified_login_failure" } - + public enum Property: String { case failure case flow @@ -25,240 +25,240 @@ public class AuthenticatorAnalyticsTracker { case source case step } - + public enum Source: String { /// Starts when the user logs in / sign up from the prologue screen /// case `default` - + case jetpack case share case deeplink case reauthentication - + /// Starts when the used adds a site from the site picker /// case selfHosted = "self_hosted" } - + public enum Flow: String { /// The initial flow before we decide whether the user is logging in or signing up /// case wpCom = "wordpress_com" - + /// Flow for Google login /// case loginWithGoogle = "google_login" - + /// Flow for Google signup /// case signupWithGoogle = "google_signup" - + /// Flow for Apple login /// case loginWithApple = "siwa_login" - + /// Flow for Apple signup /// case signupWithApple = "siwa_signup" - + /// Flow for iCloud Keychain login /// case loginWithiCloudKeychain = "icloud_keychain_login" - + /// The flow that starts when we offer the user the magic link login /// case loginWithMagicLink = "login_magic_link" - + /// This flow starts when the user decides to login with a password instead /// case loginWithPassword = "login_password" - + /// This flow starts when the user decides to log in with their site address /// case loginWithSiteAddress = "login_site_address" - + /// This flow represents the signup (when the user inputs an email that’s not registered with a .com account) /// case signup - + /// This flow represents the prologue screen. /// case prologue } - + public enum Step: String { /// Gets shown on the Prologue screen /// case prologue - + /// Triggered when a flow is started /// case start - + /// Triggered when a user requests a magic link and sees the screen with the “Open mail” button /// case magicLinkRequested = "magic_link_requested" - + /// This represents the user opening their mail. It’s not strictly speaking an in-app screen but for the user it is part of the flow. case emailOpened = "email_opened" - + /// The screen with a username and password visible /// case usernamePassword = "username_password" - + /// The screen that requests the password /// case passwordChallenge = "password_challenge" - + /// Triggered on the epilogue screen /// case success - + /// Triggered on the help screen /// case help - + /// When we ask user to input the code from the 2 factor authentication case twoFactorAuthentication = "2fa" } - + public enum ClickTarget: String { /// Tracked when submitting the email form, the email & password form, site address form, /// username & password form and signup email form /// case submit - + /// Tracked when the user clicks on continue in the login/signup epilogue /// case `continue` - + /// Tracked when the post signup interstitial screen is dismissed, when the /// login signup help dialog is dismissed and when the email hint dialog is dismissed /// case dismiss - + /// Tracked when the user clicks “Continue with WordPress.com” on the Prologue screen /// case continueWithWordPressCom = "continue_with_wordpress_com" - + /// Tracked when the user clicks “Login with site address” on the Prologue screen /// case loginWithSiteAddress = "login_with_site_address" - + /// When the user tries to login with Apple from the confirmation screen /// case loginWithApple = "login_with_apple" - + /// Tracked when the user clicks “Login with Google” on the WordPress.com flow screen /// case loginWithGoogle = "login_with_google" - + /// When the user clicks on “Forgotten password” on one of the screens that show the password field /// case forgottenPassword = "forgotten_password" - + /// When the user clicks on terms of service anywhere /// case termsOfService = "terms_of_service_clicked" - + /// When the user tries to sign up with email from the confirmation screen /// case signupWithEmail = "signup_with_email" - + /// When the user tries to sign up with Apple from the confirmation screen /// case signupWithApple = "signup_with_apple" - + /// When the user tries to sign up with Google from the confirmation screen /// case signupWithGoogle = "signup_with_google" - + /// When the user opens the email client from the magic link screen /// case openEmailClient = "open_email_client" - + /// Any time the user clicks on the help icon in the login flow /// case showHelp = "show_help" - + /// Used on the 2FA screen to send code with a text instead of using the authenticator app /// case sendCodeWithText = "send_code_with_text" - + /// Used on the 2FA screen to submit authentication code /// case submitTwoFactorCode = "submit_2fa_code" - + /// When the user requests a magic link after filling in email address /// case requestMagicLink = "request_magic_link" - + /// Click on “Create new site” button after a successful signup /// case createNewSite = "create_new_site" - + /// Adding a self-hosted site from the epilogue /// case addSelfHostedSite = "add_self_hosted_site" - + /// Connecting a site from the epilogue /// case connectSite = "connect_site" - + /// Picking an avatar from the epilogue after a successful signup /// case selectAvatar = "select_avatar" - + /// Editing the username from the epilogue after a successful signup /// case editUsername = "edit_username" - + /// Clicking on “Need help finding site address” from a dialog /// case helpFindingSiteAddress = "help_finding_site_address" - + /// When the user clicks on the email field to log in, this triggers the hint dialog to show up /// case selectEmailField = "select_email_field" - + /// When the user selects an email from the hint dialog /// case pickEmailFromHint = "pick_email_from_hint" - + /// When the user clicks on “Create account” on the signup confirmation screen /// case createAccount = "create_account" } - + /// Shared Instance. /// public static var shared: AuthenticatorAnalyticsTracker = { return AuthenticatorAnalyticsTracker() }() - + /// State for the analytics tracker. /// public class State { internal(set) public var lastFlow: Flow internal(set) public var lastSource: Source internal(set) public var lastStep: Step - + init(lastFlow: Flow = AuthenticatorAnalyticsTracker.defaultFlow, lastSource: Source = AuthenticatorAnalyticsTracker.defaultSource, lastStep: Step = AuthenticatorAnalyticsTracker.defaultStep) { self.lastFlow = lastFlow self.lastSource = lastSource self.lastStep = lastStep } } - + /// The state of this tracker. /// public let state = State() - + /// The backing analytics tracking method. Can be overridden for testing purposes. /// let track: TrackerMethod - + /// Whether tracking is enabled or not. This is just a convenience configuration to enable this tracker to be turned on and off /// using a feature flag. It should go away once we remove the legacy tracking. /// @@ -270,16 +270,16 @@ public class AuthenticatorAnalyticsTracker { self.enabled = enabled self.track = track } - + /// Resets the flow and step to the defaults. The source is left untouched, and should only be set explicitely. /// func resetState() { set(flow: Self.defaultFlow) set(step: Self.defaultStep) } - + // MARK: - Legacy vs Unified tracking - + /// This method will reply whether, for the current flow in the state, tracking is enabled. /// /// It's the responsibility of the class calling the tracking methods to check this before attempting to actually do the tracking. @@ -289,7 +289,7 @@ public class AuthenticatorAnalyticsTracker { public func canTrack() -> Bool { return enabled } - + /// This is a convenience method, that's useful for cases where we simply want to check if the legacy tracking should be /// enabled. It can be particularly useful in cases where we don't have a matching tracking call in the new flow. /// @@ -298,45 +298,45 @@ public class AuthenticatorAnalyticsTracker { public func shouldUseLegacyTracker() -> Bool { return !canTrack() } - + // MARK: - Tracking - + /// Track a step within a flow. /// public func track(step: Step) { guard canTrack() else { return } - + track(event(step: step)) } - + /// Track a click interaction. /// public func track(click: ClickTarget) { guard canTrack() else { return } - + track(event(click: click)) } - + /// Track a failure. /// public func track(failure: String) { guard canTrack() else { return } - + track(event(failure: failure)) } - + // MARK: - Tracking: Legacy Tracking Support - + /// Tracks a step within a flow if tracking is enabled for that flow, or executes the specified block if tracking is not enabled /// for the flow. /// - public func track(step: Step, ifTrackingNotEnabled legacyTracking: () -> ()) { + public func track(step: Step, ifTrackingNotEnabled legacyTracking: () -> Void) { guard canTrack() else { legacyTracking() return @@ -344,11 +344,11 @@ public class AuthenticatorAnalyticsTracker { track(step: step) } - + /// Track a click interaction if tracking is enabled for that flow, or executes the specified block if tracking is not enabled /// for the flow. /// - public func track(click: ClickTarget, ifTrackingNotEnabled legacyTracking: () -> ()) { + public func track(click: ClickTarget, ifTrackingNotEnabled legacyTracking: () -> Void) { guard canTrack() else { legacyTracking() return @@ -356,11 +356,11 @@ public class AuthenticatorAnalyticsTracker { track(event(click: click)) } - + /// Track a failure if tracking is enabled for that flow, or executes the specified block if tracking is not enabled /// for the flow. /// - public func track(failure: String, ifTrackingNotEnabled legacyTracking: () -> ()) { + public func track(failure: String, ifTrackingNotEnabled legacyTracking: () -> Void) { guard canTrack() else { legacyTracking() return @@ -368,9 +368,9 @@ public class AuthenticatorAnalyticsTracker { track(event(failure: failure)) } - + // MARK: - Event Construction & Context Updating - + /// Creates an event for a step. Updates the state machine. /// /// - Parameters: @@ -383,9 +383,9 @@ public class AuthenticatorAnalyticsTracker { let event = AnalyticsEvent( name: EventType.step.rawValue, properties: properties(step: step)) - + state.lastStep = step - + return event } @@ -399,12 +399,12 @@ public class AuthenticatorAnalyticsTracker { private func event(failure: String) -> AnalyticsEvent { var properties = lastProperties() properties[Property.failure.rawValue] = failure - + return AnalyticsEvent( name: EventType.failure.rawValue, properties: properties) } - + /// Creates an event for a click interaction. Loads the properties from the state machine. /// /// - Parameters: @@ -420,41 +420,41 @@ public class AuthenticatorAnalyticsTracker { name: EventType.interaction.rawValue, properties: properties) } - + // MARK: - Source & Flow - + /// Allows the caller to set the flow without tracking. /// public func set(flow: Flow) { state.lastFlow = flow } - + /// Allows the caller to set the source without tracking. /// public func set(source: Source) { state.lastSource = source } - + /// Allows the caller to set the step without tracking. /// public func set(step: Step) { state.lastStep = step } - + // MARK: - Properties - + private func properties(step: Step) -> [String: String] { return properties(step: step, flow: state.lastFlow, source: state.lastSource) } - + private func properties(step: Step, flow: Flow, source: Source) -> [String: String] { return [ Property.flow.rawValue: flow.rawValue, Property.source.rawValue: source.rawValue, - Property.step.rawValue: step.rawValue, + Property.step.rawValue: step.rawValue ] } - + /// Retrieve the last step, flow and source stored in the state machine. /// private func lastProperties() -> [String: String] { diff --git a/WordPressAuthenticator/Authenticator/WordPressAuthenticator+Errors.swift b/WordPressAuthenticator/Authenticator/WordPressAuthenticator+Errors.swift index 37a0bca62..7d86cb7b6 100644 --- a/WordPressAuthenticator/Authenticator/WordPressAuthenticator+Errors.swift +++ b/WordPressAuthenticator/Authenticator/WordPressAuthenticator+Errors.swift @@ -1,6 +1,5 @@ import Foundation - // MARK: - WordPressAuthenticator Error Constants. Once the entire code is Swifted, let's *PLEASE* have a // beautiful Error `Swift Enum`. // diff --git a/WordPressAuthenticator/Authenticator/WordPressAuthenticator+Notifications.swift b/WordPressAuthenticator/Authenticator/WordPressAuthenticator+Notifications.swift index d64637bcc..718de5214 100644 --- a/WordPressAuthenticator/Authenticator/WordPressAuthenticator+Notifications.swift +++ b/WordPressAuthenticator/Authenticator/WordPressAuthenticator+Notifications.swift @@ -12,7 +12,7 @@ extension NSNotification.Name { /// Posted whenever a Support notification is received. /// public static let wordpressSupportNotificationReceived = NSNotification.Name(rawValue: "WordPressSupportNotificationReceived") - + /// Posted whenever a Support notification has been viewed. /// public static let wordpressSupportNotificationCleared = NSNotification.Name(rawValue: "WordPressSupportNotificationCleared") diff --git a/WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift b/WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift index e12ba201f..98bc20715 100644 --- a/WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift +++ b/WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift @@ -44,7 +44,7 @@ import WordPressKit /// Authenticator's Styles for unified flows. /// public let unifiedStyle: WordPressAuthenticatorUnifiedStyle? - + /// Authenticator's Display Images. /// public let displayImages: WordPressAuthenticatorDisplayImages @@ -52,7 +52,7 @@ import WordPressKit /// Authenticator's Display Texts. /// public let displayStrings: WordPressAuthenticatorDisplayStrings - + /// Notification to be posted whenever the signing flow completes. /// @objc public static let WPSigninDidFinishNotification = "WPSigninDidFinishNotification" @@ -90,15 +90,15 @@ import WordPressKit displayImages: displayImages, displayStrings: displayStrings) } - + // MARK: - Testing Support - + class func isInitialized() -> Bool { return privateInstance != nil } // MARK: - Public Methods - + public func supportPushNotificationReceived() { NotificationCenter.default.post(name: .wordpressSupportNotificationReceived, object: nil) } @@ -106,10 +106,10 @@ import WordPressKit public func supportPushNotificationCleared() { NotificationCenter.default.post(name: .wordpressSupportNotificationCleared, object: nil) } - + /// Indicates if the specified ViewController belongs to the Authentication Flow, or not. /// - public class func isAuthenticationViewController(_ viewController: UIViewController) -> Bool { + public class func isAuthenticationViewController(_ viewController: UIViewController) -> Bool { return viewController is LoginPrologueViewController || viewController is NUXViewControllerBase } @@ -138,7 +138,6 @@ import WordPressKit return WordPressAuthenticator.openAuthenticationURL(url, fromRootViewController: rootViewController, automatedTesting: automatedTesting) } - // MARK: - Helpers for presenting the login flow /// Used to present the new login flow from the app delegate @@ -196,7 +195,7 @@ import WordPressKit showEmailLogin(from: presenter, jetpackLogin: jetpackLogin, connectedEmail: connectedEmail) return } - + showGetStarted(from: presenter, jetpackLogin: jetpackLogin, connectedEmail: connectedEmail) } @@ -207,16 +206,16 @@ import WordPressKit DDLogError("Failed to navigate from LoginPrologueViewController to GetStartedViewController") return } - + controller.loginFields.restrictToWPCom = true controller.loginFields.username = connectedEmail ?? String() controller.loginFields.meta.jetpackLogin = jetpackLogin - + let navController = LoginNavigationController(rootViewController: controller) navController.modalPresentationStyle = .fullScreen presenter.present(navController, animated: true, completion: nil) } - + /// Shows the Email Login view with Signup option. /// private class func showEmailLogin(from presenter: UIViewController, jetpackLogin: Bool, connectedEmail: String? = nil) { @@ -243,29 +242,29 @@ import WordPressKit defer { trackOpenedLogin() } - + AuthenticatorAnalyticsTracker.shared.set(source: .selfHosted) - + guard let controller = signinForWPOrg() else { DDLogError("WordPressAuthenticator: Failed to instantiate Site Address view controller.") return } - + let navController = LoginNavigationController(rootViewController: controller) navController.modalPresentationStyle = .fullScreen presenter.present(navController, animated: true, completion: nil) } - + /// Returns a Site Address view controller: allows the user to log into a WordPress.org website. /// @objc public class func signinForWPOrg() -> UIViewController? { guard WordPressAuthenticator.shared.configuration.enableUnifiedAuth else { return LoginSiteAddressViewController.instantiate(from: .login) } - + return SiteAddressViewController.instantiate(from: .siteAddress) } - + // Helper used by WPAuthTokenIssueSolver @objc public class func signinForWPCom(dotcomEmailAddress: String?, dotcomUsername: String?, onDismissed: ((_ cancelled: Bool) -> Void)? = nil) -> UIViewController { @@ -278,25 +277,25 @@ import WordPressKit DDLogError("WordPressAuthenticator: Failed to instantiate LoginWPComViewController") return UIViewController() } - + controller.loginFields = loginFields controller.dismissBlock = onDismissed - + return NUXNavigationController(rootViewController: controller) } - + AuthenticatorAnalyticsTracker.shared.set(source: .reauthentication) AuthenticatorAnalyticsTracker.shared.set(flow: .loginWithPassword) - + guard let controller = PasswordViewController.instantiate(from: .password) else { DDLogError("WordPressAuthenticator: Failed to instantiate PasswordViewController") return UIViewController() } - + controller.loginFields = loginFields controller.dismissBlock = onDismissed controller.trackAsPasswordChallenge = false - + return NUXNavigationController(rootViewController: controller) } @@ -311,12 +310,10 @@ import WordPressKit return controller } - private class func trackOpenedLogin() { WordPressAuthenticator.track(.openedLogin) } - // MARK: - Authentication Link Helpers /// Present a signin view controller to handle an authentication link. @@ -335,27 +332,27 @@ import WordPressKit DDLogError("Magic link error: we couldn't retrieve the query dictionary from the sign-in URL.") return false } - + guard let authToken = queryDictionary.string(forKey: "token") else { DDLogError("Magic link error: we couldn't retrieve the authentication token from the sign-in URL.") return false } - + guard let flowRawValue = queryDictionary.string(forKey: "flow") else { DDLogError("Magic link error: we couldn't retrieve the flow from the sign-in URL.") return false } - + let loginFields = LoginFields() - + if url.isJetpackConnect { loginFields.meta.jetpackLogin = true } - + // We could just use the flow, but since `MagicLinkFlow` is an ObjC enum, it always // allows a `default` value. By mapping the ObjC enum to a Swift enum we can avoid that afterwards. let flow: NUXLinkAuthViewController.Flow - + switch MagicLinkFlow(rawValue: flowRawValue) { case .signup: flow = .signup @@ -369,7 +366,7 @@ import WordPressKit DDLogError("Magic link error: the flow should be either `signup` or `login`. We can't handle an unsupported flow.") return false } - + if !automatedTesting { let storyboard = Storyboard.emailMagicLink.instance guard let loginVC = storyboard.instantiateViewController(withIdentifier: "LinkAuthView") as? NUXLinkAuthViewController else { @@ -377,10 +374,10 @@ import WordPressKit return false } loginVC.loginFields = loginFields - + let navController = LoginNavigationController(rootViewController: loginVC) navController.modalPresentationStyle = .fullScreen - + // The way the magic link flow works some view controller might // still be presented when the app is resumed by tapping on the auth link. // We need to do a little work to present the SigninLinkAuth controller @@ -400,17 +397,15 @@ import WordPressKit } else { presenter.present(navController, animated: false, completion: nil) } - + loginVC.syncAndContinue(authToken: authToken, flow: flow, isJetpackConnect: url.isJetpackConnect) } - + return true } - // MARK: - Site URL helper - /// The base site URL path derived from `loginFields.siteUrl` /// /// - Parameter string: The source URL as a string. @@ -473,7 +468,6 @@ import WordPressKit // MARK: - 1Password Helper - /// Request credentails from 1Password (if supported) /// /// - Parameter sender: A UIView. Typically the button the user tapped on. @@ -491,7 +485,7 @@ import WordPressKit if allowUsernameChange { loginFields.username = username } - + loginFields.password = password loginFields.multifactorCode = otp ?? String() @@ -520,11 +514,11 @@ public extension WordPressAuthenticator { } func startObservingAppleIDCredentialRevoked(completion: @escaping () -> Void) { - appleIDCredentialObserver = NotificationCenter.default.addObserver(forName: AppleAuthenticator.credentialRevokedNotification, object: nil, queue: nil) { (notification) in + appleIDCredentialObserver = NotificationCenter.default.addObserver(forName: AppleAuthenticator.credentialRevokedNotification, object: nil, queue: nil) { (_) in completion() } } - + func stopObservingAppleIDCredentialRevoked() { if let observer = appleIDCredentialObserver { NotificationCenter.default.removeObserver(observer) diff --git a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorConfiguration.swift b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorConfiguration.swift index 3c7f62c86..c57ad7c5b 100644 --- a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorConfiguration.swift +++ b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorConfiguration.swift @@ -20,11 +20,11 @@ public struct WordPressAuthenticatorConfiguration { /// WordPress.com Terms of Service URL /// let wpcomTermsOfServiceURL: String - + /// WordPress.com Base URL for OAuth /// let wpcomBaseURL: String - + /// WordPress.com API Base URL /// let wpcomAPIBaseURL: String @@ -59,7 +59,7 @@ public struct WordPressAuthenticatorConfiguration { /// If enabled, "Find your site address", "Reset your password", and others will be displayed. /// If disabled, none of the hint buttons will appear on the unified auth flows. let displayHintButtons: Bool - + /// Flag indicating if the Sign In With Apple option should be displayed. /// let enableSignInWithApple: Bool @@ -71,7 +71,7 @@ public struct WordPressAuthenticatorConfiguration { /// If disabled, a view is displayed providing the user with other options. /// let enableSignupWithGoogle: Bool - + /// Flag for the unified login/signup flows. /// If disabled, none of the unified flows will display. /// If enabled, all unified flows will display. @@ -82,7 +82,7 @@ public struct WordPressAuthenticatorConfiguration { /// If disabled, displays the old carousel. /// If enabled, displays the new carousel. let enableUnifiedCarousel: Bool - + /// Flag for the unified login/signup flows. /// If disabled, the "Continue With WordPress" button in the login prologue is shown first. /// If enabled, the "Enter your existing site address" button in the login prologue is shown first. diff --git a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorDelegateProtocol.swift b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorDelegateProtocol.swift index 2e684e3f3..bb4b84681 100644 --- a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorDelegateProtocol.swift +++ b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorDelegateProtocol.swift @@ -1,5 +1,3 @@ - - // MARK: - WordPressAuthenticator Delegate Protocol // public protocol WordPressAuthenticatorDelegate: class { diff --git a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorDisplayStrings.swift b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorDisplayStrings.swift index 447f72af3..bce0c0504 100644 --- a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorDisplayStrings.swift +++ b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorDisplayStrings.swift @@ -1,6 +1,5 @@ import Foundation - // MARK: - WordPress Authenticator Display Strings // public struct WordPressAuthenticatorDisplayStrings { @@ -30,7 +29,7 @@ public struct WordPressAuthenticatorDisplayStrings { public let createAccountButtonTitle: String public let continueWithWPButtonTitle: String public let enterYourSiteAddressButtonTitle: String - + /// Large titles displayed in unified auth flows. /// public let getStartedTitle: String @@ -182,7 +181,7 @@ public extension WordPressAuthenticatorDisplayStrings { comment: "The button title for a secondary call-to-action button. When the user wants to try sending a magic link instead of entering a password."), textCodeButtonTitle: NSLocalizedString("Text me a code instead", comment: "The button's title text to send a 2FA code via SMS text message."), - loginTermsOfService:NSLocalizedString("By continuing, you agree to our _Terms of Service_.", comment: "Legal disclaimer for logging in. The underscores _..._ denote underline."), + loginTermsOfService: NSLocalizedString("By continuing, you agree to our _Terms of Service_.", comment: "Legal disclaimer for logging in. The underscores _..._ denote underline."), signupTermsOfService: NSLocalizedString("If you continue with Apple or Google and don't already have a WordPress.com account, you are creating an account and you agree to our _Terms of Service_.", comment: "Legal disclaimer for signing up. The underscores _..._ denote underline."), getStartedTitle: NSLocalizedString("Get Started", comment: "View title for initial auth views."), diff --git a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorResult.swift b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorResult.swift index ecd7a6309..e84970642 100644 --- a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorResult.swift +++ b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorResult.swift @@ -1,6 +1,5 @@ import Foundation - /// Provides options for clients of WordPressAuthenticator /// to signal what they expect WPAuthenticator to do in response to /// `shouldPresentUsernamePasswordController` diff --git a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorStyles.swift b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorStyles.swift index ff85df1d1..9b231bae9 100644 --- a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorStyles.swift +++ b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorStyles.swift @@ -77,7 +77,7 @@ public struct WordPressAuthenticatorStyle { public let navBarBadgeColor: UIColor public let navBarBackgroundColor: UIColor - + public let navButtonTextColor: UIColor /// Style: prologue background colors @@ -96,7 +96,7 @@ public struct WordPressAuthenticatorStyle { /// Style: status bar style /// public let statusBarStyle: UIStatusBarStyle - + /// Designated initializer /// public init(primaryNormalBackgroundColor: UIColor, @@ -197,7 +197,7 @@ public struct WordPressAuthenticatorUnifiedStyle { /// Style: Auth view background colors /// public let viewControllerBackgroundColor: UIColor - + /// Style: Auth Prologue buttons background color public let prologueButtonsBackgroundColor: UIColor @@ -207,13 +207,13 @@ public struct WordPressAuthenticatorUnifiedStyle { /// Style: Status bar style. Defaults to `default`. /// public let statusBarStyle: UIStatusBarStyle - + /// Style: Navigation bar. /// public let navBarBackgroundColor: UIColor public let navButtonTextColor: UIColor public let navTitleTextColor: UIColor - + /// Designated initializer /// public init(borderColor: UIColor, diff --git a/WordPressAuthenticator/Authenticator/WordPressSupportSourceTag.swift b/WordPressAuthenticator/Authenticator/WordPressSupportSourceTag.swift index c19ec7651..eae558e3b 100644 --- a/WordPressAuthenticator/Authenticator/WordPressSupportSourceTag.swift +++ b/WordPressAuthenticator/Authenticator/WordPressSupportSourceTag.swift @@ -1,12 +1,11 @@ import Foundation - // MARK: - Authentication Flow Event. Useful to relay internal Auth events over to activity trackers. // public struct WordPressSupportSourceTag { public let name: String public let origin: String? - + public init(name: String, origin: String? = nil) { self.name = name self.origin = origin diff --git a/WordPressAuthenticator/Credentials/WordPressComCredentials.swift b/WordPressAuthenticator/Credentials/WordPressComCredentials.swift index c0a577571..205a42191 100644 --- a/WordPressAuthenticator/Credentials/WordPressComCredentials.swift +++ b/WordPressAuthenticator/Credentials/WordPressComCredentials.swift @@ -19,9 +19,9 @@ public struct WordPressComCredentials: Equatable { /// The site address used during login /// public var siteURL: String - + private let wpComURL = "https://wordpress.com" - + /// Legacy initializer, for backwards compatibility /// public init(authToken: String, @@ -35,7 +35,6 @@ public struct WordPressComCredentials: Equatable { } } - // MARK: - Equatable Conformance // public func ==(lhs: WordPressComCredentials, rhs: WordPressComCredentials) -> Bool { diff --git a/WordPressAuthenticator/Credentials/WordPressOrgCredentials.swift b/WordPressAuthenticator/Credentials/WordPressOrgCredentials.swift index 0408dc419..34f496626 100644 --- a/WordPressAuthenticator/Credentials/WordPressOrgCredentials.swift +++ b/WordPressAuthenticator/Credentials/WordPressOrgCredentials.swift @@ -32,7 +32,6 @@ public struct WordPressOrgCredentials: Equatable { } } - // MARK: - Equatable Conformance // public func ==(lhs: WordPressOrgCredentials, rhs: WordPressOrgCredentials) -> Bool { diff --git a/WordPressAuthenticator/Email Client Picker/AppSelector.swift b/WordPressAuthenticator/Email Client Picker/AppSelector.swift index b6ed96773..2b2e2f19f 100644 --- a/WordPressAuthenticator/Email Client Picker/AppSelector.swift +++ b/WordPressAuthenticator/Email Client Picker/AppSelector.swift @@ -28,7 +28,7 @@ class AppSelector { guard let url = URL(string: urlString), urlHandler.canOpenURL(url) else { continue } - actions.append(UIAlertAction(title: AppSelectorTitles(rawValue: name)?.localized ?? name, style: .default) { action in + actions.append(UIAlertAction(title: AppSelectorTitles(rawValue: name)?.localized ?? name, style: .default) { _ in urlHandler.open(url, options: [:], completionHandler: nil) }) } @@ -36,7 +36,7 @@ class AppSelector { guard !actions.isEmpty else { return nil } - //sort the apps alphabetically + // sort the apps alphabetically actions = actions.sorted { $0.title ?? "" < $1.title ?? "" } actions.append(UIAlertAction(title: AppSelectorTitles.cancel.localized, style: .cancel, handler: nil)) @@ -59,7 +59,6 @@ class AppSelector { } } - /// Initializers for Email Picker extension AppSelector { /// initializes the picker with a plist file in a specified bundle @@ -90,7 +89,7 @@ extension AppSelector { // if available, prepend apple mail if MFMailComposeViewController.canSendMail(), let url = URL(string: "message://") { - defaultAction = UIAlertAction(title: AppSelectorTitles.appleMail.localized, style: .default) { action in + defaultAction = UIAlertAction(title: AppSelectorTitles.appleMail.localized, style: .default) { _ in UIApplication.shared.open(url) } } @@ -101,7 +100,6 @@ extension AppSelector { } } - /// Localizable app selector titles enum AppSelectorTitles: String { case appleMail diff --git a/WordPressAuthenticator/Email Client Picker/LinkMailPresenter.swift b/WordPressAuthenticator/Email Client Picker/LinkMailPresenter.swift index f758fb2b3..55537db46 100644 --- a/WordPressAuthenticator/Email Client Picker/LinkMailPresenter.swift +++ b/WordPressAuthenticator/Email Client Picker/LinkMailPresenter.swift @@ -1,6 +1,5 @@ import MessageUI - /// Email picker presenter class LinkMailPresenter { diff --git a/WordPressAuthenticator/Email Client Picker/URLHandler.swift b/WordPressAuthenticator/Email Client Picker/URLHandler.swift index 24a92f2a3..47730a73b 100644 --- a/WordPressAuthenticator/Email Client Picker/URLHandler.swift +++ b/WordPressAuthenticator/Email Client Picker/URLHandler.swift @@ -4,10 +4,9 @@ protocol URLHandler { func canOpenURL(_ url: URL) -> Bool /// opens the specified URL func open(_ url: URL, - options: [UIApplication.OpenExternalURLOptionsKey : Any], + options: [UIApplication.OpenExternalURLOptionsKey: Any], completionHandler completion: ((Bool) -> Void)?) } /// conforms UIApplication to URLHandler to allow dependency injection extension UIApplication: URLHandler {} - diff --git a/WordPressAuthenticator/Extensions/FancyAlertViewController+LoginError.swift b/WordPressAuthenticator/Extensions/FancyAlertViewController+LoginError.swift index 38efdf5ed..b80af63da 100644 --- a/WordPressAuthenticator/Extensions/FancyAlertViewController+LoginError.swift +++ b/WordPressAuthenticator/Extensions/FancyAlertViewController+LoginError.swift @@ -3,7 +3,6 @@ import wpxmlrpc import SafariServices import WordPressUI - extension FancyAlertViewController { private struct Strings { static let titleText = NSLocalizedString("What's my site address?", comment: "Title of alert helping users understand their site address") @@ -25,7 +24,7 @@ extension FancyAlertViewController { sourceTag: WordPressSupportSourceTag, moreHelpTapped: (() -> Void)? = nil, onDismiss: (() -> Void)? = nil) -> FancyAlertViewController { - + let moreHelpButton = ButtonConfig(Strings.moreHelp) { controller, _ in controller.dismiss(animated: true) { // Find the topmost view controller that we can present from @@ -46,7 +45,7 @@ extension FancyAlertViewController { onDismiss?() controller.dismiss(animated: true, completion: nil) } - + let config = FancyAlertViewController.Config(titleText: Strings.titleText, bodyText: Strings.bodyText, headerImage: image, @@ -61,10 +60,8 @@ extension FancyAlertViewController { return controller } - // MARK: - Error Handling - /// Get an alert for the specified error. /// The view is configured differently depending on the kind of error. /// @@ -111,7 +108,6 @@ extension FancyAlertViewController { return alertForGenericErrorMessage(message, loginFields: loginFields, sourceTag: sourceTag) } - /// Shows a generic error message. /// /// - Parameter message: The error message to show. @@ -141,7 +137,6 @@ extension FancyAlertViewController { return FancyAlertViewController.controllerWithConfiguration(configuration: config) } - /// Shows a generic error message. /// If Support is enabled, the view is configured so the user can open Support for assistance. /// @@ -151,7 +146,7 @@ extension FancyAlertViewController { static func alertForGenericErrorMessageWithHelpButton(_ message: String, loginFields: LoginFields, sourceTag: WordPressSupportSourceTag) -> FancyAlertViewController { // If support is not enabled, don't add a Help Button since it won't do anything. - var moreHelpButton: ButtonConfig? = nil + var moreHelpButton: ButtonConfig? if WordPressAuthenticator.shared.delegate?.supportEnabled == false { DDLogInfo("Error Alert: Support not enabled. Hiding Help button.") @@ -166,7 +161,7 @@ extension FancyAlertViewController { else { return } - + WordPressAuthenticator.shared.delegate?.presentSupportRequest(from: viewController, sourceTag: sourceTag) } } @@ -185,7 +180,6 @@ extension FancyAlertViewController { return FancyAlertViewController.controllerWithConfiguration(configuration: config) } - /// Shows a WPWalkthroughOverlayView for a bad url error message. /// /// - Parameter message: The error message to show. diff --git a/WordPressAuthenticator/Extensions/NSObject+Helpers.swift b/WordPressAuthenticator/Extensions/NSObject+Helpers.swift index 5c0bb9298..dddb827a6 100644 --- a/WordPressAuthenticator/Extensions/NSObject+Helpers.swift +++ b/WordPressAuthenticator/Extensions/NSObject+Helpers.swift @@ -1,8 +1,6 @@ - import Foundation - -// MARK - NSObject Helper Methods +// MARK: - NSObject Helper Methods // extension NSObject { diff --git a/WordPressAuthenticator/Extensions/UIImage+Assets.swift b/WordPressAuthenticator/Extensions/UIImage+Assets.swift index 79fb3e099..4ffaed4f8 100644 --- a/WordPressAuthenticator/Extensions/UIImage+Assets.swift +++ b/WordPressAuthenticator/Extensions/UIImage+Assets.swift @@ -1,6 +1,5 @@ import Foundation - // MARK: - Named Assets // extension UIImage { diff --git a/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift b/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift index 5665be7b1..b8cb4b5ec 100644 --- a/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift +++ b/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift @@ -11,7 +11,7 @@ extension UIPasteboard { case .success(let detections): guard detections.isEmpty == false else { DispatchQueue.main.async { - completion(.success([UIPasteboard.DetectionPattern : Any]())) + completion(.success([UIPasteboard.DetectionPattern: Any]())) } return } diff --git a/WordPressAuthenticator/Extensions/UIStoryboard+Helpers.swift b/WordPressAuthenticator/Extensions/UIStoryboard+Helpers.swift index 12a3195f6..f9a2bec4f 100644 --- a/WordPressAuthenticator/Extensions/UIStoryboard+Helpers.swift +++ b/WordPressAuthenticator/Extensions/UIStoryboard+Helpers.swift @@ -1,13 +1,12 @@ import Foundation - -// MARK - Storyboard enum +// MARK: - Storyboard enum enum Storyboard: String { case login = "Login" case signup = "Signup" case getStarted = "GetStarted" case unifiedSignup = "UnifiedSignup" - case unifiedLoginMagicLink = "LoginMagicLink" + case unifiedLoginMagicLink = "LoginMagicLink" case emailMagicLink = "EmailMagicLink" case siteAddress = "SiteAddress" case googleAuth = "GoogleAuth" diff --git a/WordPressAuthenticator/Extensions/UIView+AuthHelpers.swift b/WordPressAuthenticator/Extensions/UIView+AuthHelpers.swift index 0f5dab914..36e29efa3 100644 --- a/WordPressAuthenticator/Extensions/UIView+AuthHelpers.swift +++ b/WordPressAuthenticator/Extensions/UIView+AuthHelpers.swift @@ -1,6 +1,5 @@ import UIKit - /// UIView class methods /// extension UIView { diff --git a/WordPressAuthenticator/Extensions/UIViewController+Dismissal.swift b/WordPressAuthenticator/Extensions/UIViewController+Dismissal.swift index 32edb5313..0e3505f8f 100644 --- a/WordPressAuthenticator/Extensions/UIViewController+Dismissal.swift +++ b/WordPressAuthenticator/Extensions/UIViewController+Dismissal.swift @@ -10,7 +10,7 @@ extension UIViewController { var isBeingDismissedInAnyWay: Bool { isMovingFromParent || isBeingDismissed || (navigationController?.isBeingDismissed ?? false) } - + /// Depending on how a VC is presented we need to check different things to know whether it's being presented or not. /// A VC presented as the first VC in a navigation controller needs to check if the navigation controller is being presented. /// A VC added to an existing navigation controller is presented when `isMovingToParent` is `true`. diff --git a/WordPressAuthenticator/Extensions/UIViewController+Helpers.swift b/WordPressAuthenticator/Extensions/UIViewController+Helpers.swift index a8c0df46c..730866d38 100644 --- a/WordPressAuthenticator/Extensions/UIViewController+Helpers.swift +++ b/WordPressAuthenticator/Extensions/UIViewController+Helpers.swift @@ -1,7 +1,6 @@ import Foundation - -// MARK - UIViewController Helpers +// MARK: - UIViewController Helpers extension UIViewController { /// Convenience method to instantiate a view controller from a storyboard. diff --git a/WordPressAuthenticator/Extensions/WPStyleGuide+Login.swift b/WordPressAuthenticator/Extensions/WPStyleGuide+Login.swift index 5954200fd..1bcfa3da7 100644 --- a/WordPressAuthenticator/Extensions/WPStyleGuide+Login.swift +++ b/WordPressAuthenticator/Extensions/WPStyleGuide+Login.swift @@ -30,7 +30,7 @@ extension WPStyleGuide { class var hairlineBorderWidth: CGFloat { return 1.0 / UIScreen.main.scale } - + /// Common view style for signin view controllers. /// /// - Parameters: @@ -76,7 +76,7 @@ extension WPStyleGuide { onePasswordButton.sizeToFit() onePasswordButton.setContentHuggingPriority(.required, for: .horizontal) onePasswordButton.setContentCompressionResistancePriority(.required, for: .horizontal) - + onePasswordButton.accessibilityTraits = .button onePasswordButton.accessibilityLabel = NSLocalizedString("One Password button", comment: "Accessibility label for 1 password button") onePasswordButton.accessibilityHint = NSLocalizedString("Opens One Password manager", comment: "Accessibility hint for 1 password button") @@ -168,11 +168,11 @@ extension WPStyleGuide { /// - Returns: A properly styled NSAttributedString /// class func formattedGoogleString(forHyperlink: Bool = false) -> NSAttributedString { - + let googleAttachment = NSTextAttachment() let googleIcon = UIImage.googleIcon googleAttachment.image = googleIcon - + if forHyperlink { // Create an attributed string that contains the Google icon. let font = WPStyleGuide.mediumWeightFont(forStyle: .subheadline) @@ -196,7 +196,7 @@ extension WPStyleGuide { return buttonString } } - + /// Creates an attributed string that includes the Apple logo. /// /// - Returns: A properly styled NSAttributedString to be displayed on a NUXButton. @@ -219,37 +219,37 @@ extension WPStyleGuide { return NSAttributedString(attributedString: attributedString) } - + /// Creates a button for Self-hosted Login /// /// - Returns: A properly styled UIButton /// class func selfHostedLoginButton(alignment: UIControl.NaturalContentHorizontalAlignment = .leading) -> UIButton { - + let style = WordPressAuthenticator.shared.style - + let button: UIButton if WordPressAuthenticator.shared.configuration.showLoginOptions { let baseString = NSLocalizedString("Or log in by _entering your site address_.", comment: "Label for button to log in using site address. Underscores _..._ denote underline.") - + let attrStrNormal = baseString.underlined(color: style.subheadlineColor, underlineColor: style.textButtonColor) let attrStrHighlight = baseString.underlined(color: style.subheadlineColor, underlineColor: style.textButtonHighlightColor) let font = WPStyleGuide.mediumWeightFont(forStyle: .subheadline) - + button = textButton(normal: attrStrNormal, highlighted: attrStrHighlight, font: font, alignment: alignment) } else { let baseString = NSLocalizedString("Enter the address of the WordPress site you'd like to connect.", comment: "Label for button to log in using your site address.") - - let attrStrNormal = selfHostedButtonString(baseString, linkColor: style.textButtonColor) + + let attrStrNormal = selfHostedButtonString(baseString, linkColor: style.textButtonColor) let attrStrHighlight = selfHostedButtonString(baseString, linkColor: style.textButtonHighlightColor) let font = WPStyleGuide.mediumWeightFont(forStyle: .subheadline) - + button = textButton(normal: attrStrNormal, highlighted: attrStrHighlight, font: font) } - + button.accessibilityIdentifier = "Self Hosted Login Button" - + return button } @@ -294,7 +294,7 @@ extension WPStyleGuide { let baseString = WordPressAuthenticator.shared.displayStrings.signupTermsOfService let textColor = unifiedStyle?.textSubtleColor ?? originalStyle.subheadlineColor let linkColor = unifiedStyle?.textButtonColor ?? originalStyle.textButtonColor - + let attrStrNormal = baseString.underlined(color: textColor, underlineColor: linkColor) let attrStrHighlight = baseString.underlined(color: textColor, underlineColor: linkColor) let font = WPStyleGuide.mediumWeightFont(forStyle: .footnote) @@ -303,7 +303,7 @@ extension WPStyleGuide { button.titleLabel?.textAlignment = .center return button } - + private class func textButton(normal normalString: NSAttributedString, highlighted highlightString: NSAttributedString, font: UIFont, alignment: UIControl.NaturalContentHorizontalAlignment = .leading, forUnified: Bool = false) -> UIButton { let button = SubheadlineButton() button.clipsToBounds = true @@ -318,7 +318,7 @@ extension WPStyleGuide { // These constraints work around some issues with multiline buttons and // vertical layout. Without them the button's height may not account // for the titleLabel's height. - + let verticalLabelSpacing = forUnified ? 0 : Constants.verticalLabelSpacing button.titleLabel?.topAnchor.constraint(equalTo: button.topAnchor, constant: verticalLabelSpacing).isActive = true button.titleLabel?.bottomAnchor.constraint(equalTo: button.bottomAnchor, constant: -verticalLabelSpacing).isActive = true diff --git a/WordPressAuthenticator/Logging/CocoaLumberjack.swift b/WordPressAuthenticator/Logging/CocoaLumberjack.swift index 6bb12dd97..8c1b09a79 100644 --- a/WordPressAuthenticator/Logging/CocoaLumberjack.swift +++ b/WordPressAuthenticator/Logging/CocoaLumberjack.swift @@ -31,7 +31,7 @@ extension DDLogFlag { self = DDLogFlag(rawValue: logLevel.rawValue) } - ///returns the log level, or the lowest equivalant. + /// returns the log level, or the lowest equivalant. public func toLogLevel() -> DDLogLevel { if let ourValid = DDLogLevel(rawValue: rawValue) { return ourValid diff --git a/WordPressAuthenticator/Model/LoginFields+Validation.swift b/WordPressAuthenticator/Model/LoginFields+Validation.swift index 33cd2c4db..a22cd6cb1 100644 --- a/WordPressAuthenticator/Model/LoginFields+Validation.swift +++ b/WordPressAuthenticator/Model/LoginFields+Validation.swift @@ -17,7 +17,7 @@ extension LoginFields { guard let url = URL(string: NSURL.idnEncodedURL(siteAddress)) else { return false } - + return !url.absoluteString.isEmpty } diff --git a/WordPressAuthenticator/Model/LoginFields.swift b/WordPressAuthenticator/Model/LoginFields.swift index 5ff237b7f..fdcb03bf3 100644 --- a/WordPressAuthenticator/Model/LoginFields.swift +++ b/WordPressAuthenticator/Model/LoginFields.swift @@ -2,7 +2,6 @@ import Foundation import GoogleSignIn import WordPressKit - /// LoginFields is a state container for user textfield input on the login screens /// as well as other meta data regarding the nature of a login attempt. /// @@ -48,13 +47,13 @@ public class LoginFields: NSObject { storedCredentials?.storedUserameHash = usernameHash storedCredentials?.storedPasswordHash = passwordHash } - + class func makeForWPCom(username: String, password: String) -> LoginFields { let loginFields = LoginFields() - + loginFields.username = username loginFields.password = password - + return loginFields } } diff --git a/WordPressAuthenticator/Model/WordPressComSiteInfo.swift b/WordPressAuthenticator/Model/WordPressComSiteInfo.swift index 2cbae4f47..579237b25 100644 --- a/WordPressAuthenticator/Model/WordPressComSiteInfo.swift +++ b/WordPressAuthenticator/Model/WordPressComSiteInfo.swift @@ -1,6 +1,5 @@ import Foundation - // MARK: - WordPress.com Site Info // public class WordPressComSiteInfo { @@ -32,7 +31,7 @@ public class WordPressComSiteInfo { /// URL of the Site's Blavatar. /// public let icon: String - + /// Indicates whether the site is WordPressDotCom, or not. /// public let isWPCom: Bool @@ -45,8 +44,6 @@ public class WordPressComSiteInfo { /// public let exists: Bool - - /// Initializes the current SiteInfo instance with a raw dictionary. /// public init(remote: [AnyHashable: Any]) { diff --git a/WordPressAuthenticator/NUX/NUXButton.swift b/WordPressAuthenticator/NUX/NUXButton.swift index e6aff3bb3..6d21d5e51 100644 --- a/WordPressAuthenticator/NUX/NUXButton.swift +++ b/WordPressAuthenticator/NUX/NUXButton.swift @@ -30,7 +30,7 @@ import WordPressKit }() var titleFont = WPStyleGuide.mediumWeightFont(forStyle: .title3) - + override open func layoutSubviews() { super.layoutSubviews() @@ -49,16 +49,14 @@ import WordPressKit super.tintColorDidChange() configureBackgrounds() configureTitleColors() - + if socialService == .apple { setAttributedTitle(WPStyleGuide.formattedAppleString(), for: .normal) } } - // MARK: - Instance Methods - /// Toggles the visibility of the activity indicator. When visible the button /// title is hidden. /// @@ -76,7 +74,7 @@ import WordPressKit func didChangePreferredContentSize() { titleLabel?.adjustsFontForContentSizeCategory = true } - + func customizeFont(_ font: UIFont) { titleFont = font } diff --git a/WordPressAuthenticator/NUX/NUXButtonViewController.swift b/WordPressAuthenticator/NUX/NUXButtonViewController.swift index 0111940b1..262b246f0 100644 --- a/WordPressAuthenticator/NUX/NUXButtonViewController.swift +++ b/WordPressAuthenticator/NUX/NUXButtonViewController.swift @@ -41,7 +41,7 @@ open class NUXButtonViewController: UIViewController { @IBOutlet var tertiaryButton: NUXButton? @IBOutlet var buttonHolder: UIView? - open var delegate: NUXButtonViewControllerDelegate? + open weak var delegate: NUXButtonViewControllerDelegate? open var backgroundColor: UIColor? private var topButtonConfig: NUXButtonConfig? @@ -65,13 +65,13 @@ open class NUXButtonViewController: UIViewController { configure(button: bottomButton, withConfig: bottomButtonConfig) configure(button: topButton, withConfig: topButtonConfig) configure(button: tertiaryButton, withConfig: tertiaryButtonConfig) - + buttonHolder?.backgroundColor = backgroundColor } private func configure(button: NUXButton?, withConfig buttonConfig: NUXButtonConfig?) { if let buttonConfig = buttonConfig, let button = button { - + if let attributedTitle = buttonConfig.attributedTitle { button.setAttributedTitle(attributedTitle, for: .normal) button.socialService = buttonConfig.socialService @@ -120,7 +120,7 @@ open class NUXButtonViewController: UIViewController { func setupTopButtonFor(socialService: SocialServiceName, onTap callback: @escaping CallBackType) { topButtonConfig = buttonConfigFor(socialService: socialService, onTap: callback) } - + func setupBottomButton(title: String, isPrimary: Bool = false, configureBodyFontForTitle: Bool = false, accessibilityIdentifier: String? = nil, onTap callback: @escaping CallBackType) { bottomButtonConfig = NUXButtonConfig(title: title, isPrimary: isPrimary, configureBodyFontForTitle: configureBodyFontForTitle, accessibilityIdentifier: accessibilityIdentifier, callback: callback) } diff --git a/WordPressAuthenticator/NUX/NUXKeyboardResponder.swift b/WordPressAuthenticator/NUX/NUXKeyboardResponder.swift index 698c890d4..262807e6f 100644 --- a/WordPressAuthenticator/NUX/NUXKeyboardResponder.swift +++ b/WordPressAuthenticator/NUX/NUXKeyboardResponder.swift @@ -34,7 +34,6 @@ public extension NUXKeyboardResponder where Self: NUXViewController { NotificationCenter.default.addObserver(self, selector: keyboardWillHideAction, name: UIResponder.keyboardWillHideNotification, object: nil) } - /// Unregisters the receiver from keyboard events. /// func unregisterForKeyboardEvents() { @@ -42,7 +41,6 @@ public extension NUXKeyboardResponder where Self: NUXViewController { NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil) } - /// Returns the vertical offset to apply to the sign in form. /// /// - Returns: NUXKeyboardDefaultFormVerticalOffset unless a conforming controller provides its own implementation. @@ -51,7 +49,6 @@ public extension NUXKeyboardResponder where Self: NUXViewController { return NUXKeyboardDefaultFormVerticalOffset } - /// Adjusts constraint constants to adapt the view for a visible keyboard. /// /// - Parameter visibleKeyboard: Whether to configure for a visible keyboard or without a keyboard. @@ -66,7 +63,6 @@ public extension NUXKeyboardResponder where Self: NUXViewController { } } - /// Process the passed NSNotification from a UIKeyboardWillShowNotification. /// /// - Parameter notification: the NSNotification object from a UIKeyboardWillShowNotification. @@ -93,7 +89,6 @@ public extension NUXKeyboardResponder where Self: NUXViewController { completion: nil) } - /// Process the passed NSNotification from a UIKeyboardWillHideNotification. /// /// - Parameter notification: the NSNotification object from a UIKeyboardWillHideNotification. @@ -119,7 +114,6 @@ public extension NUXKeyboardResponder where Self: NUXViewController { completion: nil) } - /// Retrieves the keyboard frame and the animation duration from a keyboard /// notificaiton. /// @@ -138,7 +132,6 @@ public extension NUXKeyboardResponder where Self: NUXViewController { return (keyboardFrame: frame, animationDuration: duration) } - func heightDeltaFromKeyboardFrame(_ keyboardFrame: CGRect) -> CGFloat { // If an external keyboard is connected, the ending keyboard frame's maxY // will exceed the height of the view controller's view. diff --git a/WordPressAuthenticator/NUX/NUXLinkAuthViewController.swift b/WordPressAuthenticator/NUX/NUXLinkAuthViewController.swift index e2c89a399..cb8110a3a 100644 --- a/WordPressAuthenticator/NUX/NUXLinkAuthViewController.swift +++ b/WordPressAuthenticator/NUX/NUXLinkAuthViewController.swift @@ -9,7 +9,7 @@ import WordPressShared /// class NUXLinkAuthViewController: LoginViewController { @IBOutlet weak var statusLabel: UILabel? - + enum Flow { case signup case login @@ -22,14 +22,14 @@ class NUXLinkAuthViewController: LoginViewController { override func configureStatusLabel(_ message: String) { statusLabel?.text = message } - + func syncAndContinue(authToken: String, flow: Flow, isJetpackConnect: Bool) { let wpcom = WordPressComCredentials(authToken: authToken, isJetpackLogin: isJetpackConnect, multifactor: false, siteURL: "https://wordpress.com") let credentials = AuthenticatorCredentials(wpcom: wpcom) - + syncWPComAndPresentEpilogue(credentials: credentials) { self.tracker.track(step: .success) - + switch flow { case .signup: // This stat is part of a funnel that provides critical information. Before diff --git a/WordPressAuthenticator/NUX/NUXLinkMailViewController.swift b/WordPressAuthenticator/NUX/NUXLinkMailViewController.swift index d042f4903..eb61fe315 100644 --- a/WordPressAuthenticator/NUX/NUXLinkMailViewController.swift +++ b/WordPressAuthenticator/NUX/NUXLinkMailViewController.swift @@ -1,7 +1,6 @@ import UIKit import WordPressShared - /// Step two in the auth link flow. This VC prompts the user to open their email /// app to look for the emailed authentication link. /// @@ -21,8 +20,6 @@ class NUXLinkMailViewController: LoginViewController { } } - - // MARK: - Lifecycle Methods override func viewDidLoad() { diff --git a/WordPressAuthenticator/NUX/NUXNavigationController.swift b/WordPressAuthenticator/NUX/NUXNavigationController.swift index 1d34d1995..3f3d7ac38 100644 --- a/WordPressAuthenticator/NUX/NUXNavigationController.swift +++ b/WordPressAuthenticator/NUX/NUXNavigationController.swift @@ -1,7 +1,6 @@ import UIKit import WordPressUI - /// Simple subclass of UINavigationController to facilitate a customized /// appearance as part of the sign in flow. /// diff --git a/WordPressAuthenticator/NUX/NUXViewController.swift b/WordPressAuthenticator/NUX/NUXViewController.swift index d8d8314d1..632fab1b9 100644 --- a/WordPressAuthenticator/NUX/NUXViewController.swift +++ b/WordPressAuthenticator/NUX/NUXViewController.swift @@ -1,6 +1,5 @@ import WordPressUI - // MARK: - NUXViewController /// Base class to use for NUX view controllers that aren't a table view /// Note: shares most of its code with NUXTableViewController. Look to make @@ -46,7 +45,7 @@ open class NUXViewController: UIViewController, NUXViewControllerBase, UIViewCon submitButton?.setTitle(primaryTitle, for: .highlighted) submitButton?.accessibilityIdentifier = "Continue Button" } - + open func enableSubmit(animating: Bool) -> Bool { return !animating } diff --git a/WordPressAuthenticator/NUX/NUXViewControllerBase.swift b/WordPressAuthenticator/NUX/NUXViewControllerBase.swift index 8ec2050c4..07d703f44 100644 --- a/WordPressAuthenticator/NUX/NUXViewControllerBase.swift +++ b/WordPressAuthenticator/NUX/NUXViewControllerBase.swift @@ -3,7 +3,7 @@ import WordPressUI private enum Constants { static let helpButtonInsets = UIEdgeInsets(top: 0.0, left: 5.0, bottom: 0.0, right: 5.0) - //Button Item: Custom view wrapping the Help UIbutton + // Button Item: Custom view wrapping the Help UIbutton static let helpButtonItemMarginSpace = CGFloat(-8) static let helpButtonItemMinimumSize = CGSize(width: 44.0, height: 44.0) @@ -54,7 +54,7 @@ extension NUXViewControllerBase where Self: UIViewController, Self: UIViewContro } let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: nil, action: nil) - cancelButton.on() { [weak self] (control: UIBarButtonItem) in + cancelButton.on { [weak self] (_: UIBarButtonItem) in self?.handleCancelButtonTapped() } navigationItem.leftBarButtonItem = cancelButton @@ -120,7 +120,7 @@ extension NUXViewControllerBase where Self: UIViewController, Self: UIViewContro func setupBackgroundTapGestureRecognizer() { let tgr = UITapGestureRecognizer() - tgr.on() { [weak self] gestureRecognizer in + tgr.on { [weak self] _ in self?.handleBackgroundTapGesture() } view.addGestureRecognizer(tgr) @@ -135,11 +135,10 @@ extension NUXViewControllerBase where Self: UIViewController, Self: UIViewContro // func handleHelpButtonTapped(_ sender: AnyObject) { AuthenticatorAnalyticsTracker.shared.track(click: .showHelp) - + displaySupportViewController(from: sourceTag) } - // MARK: - Navbar Help and App Logo methods func styleNavigationBar(forUnified: Bool = false) { @@ -147,7 +146,7 @@ extension NUXViewControllerBase where Self: UIViewController, Self: UIViewContro var buttonTextColor: UIColor var titleTextColor: UIColor var hideBottomBorder: Bool - + if forUnified { // Unified nav bar style backgroundColor = WordPressAuthenticator.shared.unifiedStyle?.navBarBackgroundColor ?? @@ -167,17 +166,17 @@ extension NUXViewControllerBase where Self: UIViewController, Self: UIViewContro setupNavBarIcon(showIcon: !forUnified) setHelpButtonTextColor(forUnified: forUnified) - + let buttonItemAppearance = UIBarButtonItem.appearance(whenContainedInInstancesOf: [LoginNavigationController.self]) buttonItemAppearance.tintColor = buttonTextColor buttonItemAppearance.setTitleTextAttributes([.foregroundColor: buttonTextColor], for: .normal) - + if #available(iOS 13.0, *) { let appearance = UINavigationBarAppearance() appearance.shadowColor = hideBottomBorder ? .clear : .separator appearance.backgroundColor = backgroundColor appearance.titleTextAttributes = [.foregroundColor: titleTextColor] - + UINavigationBar.appearance(whenContainedInInstancesOf: [LoginNavigationController.self]).standardAppearance = appearance UINavigationBar.appearance(whenContainedInInstancesOf: [LoginNavigationController.self]).compactAppearance = appearance UINavigationBar.appearance(whenContainedInInstancesOf: [LoginNavigationController.self]).scrollEdgeAppearance = appearance @@ -187,13 +186,13 @@ extension NUXViewControllerBase where Self: UIViewController, Self: UIViewContro appearance.titleTextAttributes = [.foregroundColor: titleTextColor] } } - + /// Add/remove the nav bar app logo. /// func setupNavBarIcon(showIcon: Bool = true) { showIcon ? addAppLogoToNavController() : removeAppLogoFromNavController() } - + /// Adds the app logo to the nav controller /// public func addAppLogoToNavController() { @@ -207,7 +206,7 @@ extension NUXViewControllerBase where Self: UIViewController, Self: UIViewContro public func removeAppLogoFromNavController() { navigationItem.titleView = nil } - + /// Whenever the WordPressAuthenticator Delegate returns true, when `shouldDisplayHelpButton` is queried, we'll proceed /// and attach the Help Button to the navigationController. /// @@ -232,7 +231,7 @@ extension NUXViewControllerBase where Self: UIViewController, Self: UIViewContro } return WordPressAuthenticator.shared.style.navButtonTextColor }() - + helpButton.setTitleColor(navButtonTextColor, for: .normal) helpButton.setTitleColor(navButtonTextColor.withAlphaComponent(0.4), for: .highlighted) } @@ -268,7 +267,7 @@ extension NUXViewControllerBase where Self: UIViewController, Self: UIViewContro private func addHelpButton(to superView: UIView) { helpButton.setTitle(NSLocalizedString("Help", comment: "Help button"), for: .normal) setHelpButtonTextColor(forUnified: false) - + helpButton.on(.touchUpInside) { [weak self] control in self?.handleHelpButtonTapped(control) } @@ -316,7 +315,6 @@ extension NUXViewControllerBase where Self: UIViewController, Self: UIViewContro ]) } - // MARK: - UIViewControllerTransitioningDelegate /// Displays the support vc. diff --git a/WordPressAuthenticator/NUX/WPHelpIndicatorView.swift b/WordPressAuthenticator/NUX/WPHelpIndicatorView.swift index d5368b6e3..da5d85824 100644 --- a/WordPressAuthenticator/NUX/WPHelpIndicatorView.swift +++ b/WordPressAuthenticator/NUX/WPHelpIndicatorView.swift @@ -7,22 +7,22 @@ open class WPHelpIndicatorView: UIView { static let defaultInsets = UIEdgeInsets.zero static let defaultBackgroundColor = WordPressAuthenticator.shared.style.navBarBadgeColor } - + var insets: UIEdgeInsets = Constants.defaultInsets { didSet { setNeedsDisplay() } } - + override public init(frame: CGRect) { super.init(frame: frame) commonSetup() } - + public required init(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + func commonSetup() { layer.masksToBounds = true layer.cornerRadius = 6.0 diff --git a/WordPressAuthenticator/Navigation/NavigateToEnterAccount.swift b/WordPressAuthenticator/Navigation/NavigateToEnterAccount.swift index 7ad727220..7ba62acda 100644 --- a/WordPressAuthenticator/Navigation/NavigateToEnterAccount.swift +++ b/WordPressAuthenticator/Navigation/NavigateToEnterAccount.swift @@ -9,7 +9,6 @@ public struct NavigateToEnterAccount: NavigationCommand { } } - private extension NavigateToEnterAccount { private func continueWithDotCom(navigationController: UINavigationController?) { guard let vc = GetStartedViewController.instantiate(from: .getStarted) else { diff --git a/WordPressAuthenticator/Navigation/NavigateToEnterSite.swift b/WordPressAuthenticator/Navigation/NavigateToEnterSite.swift index d2c27dc58..c2b886840 100644 --- a/WordPressAuthenticator/Navigation/NavigateToEnterSite.swift +++ b/WordPressAuthenticator/Navigation/NavigateToEnterSite.swift @@ -1,7 +1,5 @@ - import Foundation - /// Navigates to the unified site address login flow. /// public struct NavigateToEnterSite: NavigationCommand { diff --git a/WordPressAuthenticator/Navigation/NavigateToRoot.swift b/WordPressAuthenticator/Navigation/NavigateToRoot.swift index 38356af32..a4c6fd48e 100644 --- a/WordPressAuthenticator/Navigation/NavigateToRoot.swift +++ b/WordPressAuthenticator/Navigation/NavigateToRoot.swift @@ -1,6 +1,5 @@ import Foundation - /// Navigates to the root of the unified login flow. /// public struct NavigateToRoot: NavigationCommand { diff --git a/WordPressAuthenticator/Navigation/NavigationCommand.swift b/WordPressAuthenticator/Navigation/NavigationCommand.swift index 1f78aa104..969b6922b 100644 --- a/WordPressAuthenticator/Navigation/NavigationCommand.swift +++ b/WordPressAuthenticator/Navigation/NavigationCommand.swift @@ -1,4 +1,3 @@ - import Foundation /// NavigationCommand abstracts logic necessary provide clients of this library diff --git a/WordPressAuthenticator/Services/LoginFacade.swift b/WordPressAuthenticator/Services/LoginFacade.swift index c117f519f..4ffb649f1 100644 --- a/WordPressAuthenticator/Services/LoginFacade.swift +++ b/WordPressAuthenticator/Services/LoginFacade.swift @@ -4,16 +4,16 @@ extension LoginFacade { private var tracker: AuthenticatorAnalyticsTracker { AuthenticatorAnalyticsTracker.shared } - + func requestOneTimeCode(with loginFields: LoginFields) { wordpressComOAuthClientFacade.requestOneTimeCode( - withUsername: loginFields.username, + withUsername: loginFields.username, password: loginFields.password, success: { [weak self] in guard let self = self else { return } - + if self.tracker.shouldUseLegacyTracker() { WordPressAuthenticator.track(.twoFactorSentSMS) } @@ -26,7 +26,7 @@ extension LoginFacade { guard let nonce = loginFields.nonceInfo?.nonceSMS else { return } - + wordpressComOAuthClientFacade.requestSocial2FACode( withUserID: loginFields.nonceUserID, nonce: nonce, @@ -34,22 +34,22 @@ extension LoginFacade { guard let self = self else { return } - + if let newNonce = newNonce { loginFields.nonceInfo?.nonceSMS = newNonce } - + if self.tracker.shouldUseLegacyTracker() { WordPressAuthenticator.track(.twoFactorSentSMS) } - }) { (error, newNonce) in + }) { (_, newNonce) in if let newNonce = newNonce { loginFields.nonceInfo?.nonceSMS = newNonce } - DDLogError("Failed to request one time code"); + DDLogError("Failed to request one time code") } } - + @objc public func trackSuccess() { tracker.track(step: .success) diff --git a/WordPressAuthenticator/Services/OnePasswordFacade.swift b/WordPressAuthenticator/Services/OnePasswordFacade.swift index ed162c6e8..de9c6282a 100644 --- a/WordPressAuthenticator/Services/OnePasswordFacade.swift +++ b/WordPressAuthenticator/Services/OnePasswordFacade.swift @@ -2,8 +2,6 @@ import Foundation import UIKit import OnePasswordExtension - - // MARK: - This protocol is a Facade that hides some of the implementation details for interacting with 1Password. // class OnePasswordFacade { @@ -125,7 +123,6 @@ enum OnePasswordDefaults { static let passwordTitle = "WordPress" } - // MARK: - OnePasswordError // enum OnePasswordError: Error { diff --git a/WordPressAuthenticator/Services/OnePasswordResultsFetcher.swift b/WordPressAuthenticator/Services/OnePasswordResultsFetcher.swift index d7b20c783..ea67573fd 100644 --- a/WordPressAuthenticator/Services/OnePasswordResultsFetcher.swift +++ b/WordPressAuthenticator/Services/OnePasswordResultsFetcher.swift @@ -5,4 +5,3 @@ protocol OnePasswordResultsFetcher { success: @escaping (_ username: String, _ password: String, _ otp: String?) -> Void, failure: @escaping (OnePasswordError) -> Void) } - diff --git a/WordPressAuthenticator/Services/SafariCredentialsService.swift b/WordPressAuthenticator/Services/SafariCredentialsService.swift index f8696bdc7..5115a2278 100644 --- a/WordPressAuthenticator/Services/SafariCredentialsService.swift +++ b/WordPressAuthenticator/Services/SafariCredentialsService.swift @@ -3,8 +3,7 @@ class SafariCredentialsService { @objc static let LoginSharedWebCredentialFQDN: CFString = "wordpress.com" as CFString - typealias SharedWebCredentialsCallback = (_ credentialsFound: Bool, _ username: String?, _ password: String?) -> () - + typealias SharedWebCredentialsCallback = (_ credentialsFound: Bool, _ username: String?, _ password: String?) -> Void /// Update safari stored credentials. /// diff --git a/WordPressAuthenticator/Services/SignupService.swift b/WordPressAuthenticator/Services/SignupService.swift index 9662cb22b..8fbd01ccb 100644 --- a/WordPressAuthenticator/Services/SignupService.swift +++ b/WordPressAuthenticator/Services/SignupService.swift @@ -3,7 +3,6 @@ import CocoaLumberjack import WordPressShared import WordPressKit - /// SignupService: Responsible for creating a new WPCom user and blog. /// class SignupService { @@ -38,7 +37,7 @@ class SignupService { failure(error ?? SignupError.unknown) }) } - + /// Create a new WPcom account using Apple ID /// /// - Parameters: @@ -58,7 +57,7 @@ class SignupService { _ wpcomToken: String) -> Void, failure: @escaping (_ error: Error) -> Void) { let remote = WordPressComServiceRemote(wordPressComRestApi: anonymousAPI) - + remote.createWPComAccount(withApple: token, andEmail: email, andFullName: fullName, @@ -70,7 +69,7 @@ class SignupService { failure(SignupError.unknown) return } - + let createdAccount = (response?[ResponseKeys.createdAccount] as? Int ?? 0) == 1 success(createdAccount, false, false, username, bearer_token) }, failure: { error in @@ -82,7 +81,7 @@ class SignupService { } if (error.userInfo[ErrorKeys.errorCode] as? String ?? "") == ErrorKeys.existingNonSocialUser { - + // If an account already exists, the account email should be returned in the Error response. // Extract it and return it. var existingEmail = "" @@ -91,7 +90,7 @@ class SignupService { let email = emailDict?.value ?? "" existingEmail = email } - + success(false, true, false, existingEmail, "") return } @@ -100,9 +99,8 @@ class SignupService { failure(error ?? SignupError.unknown) }) } - -} +} // MARK: - Private // @@ -131,7 +129,6 @@ private extension SignupService { } } - // MARK: - Errors // enum SignupError: Error { diff --git a/WordPressAuthenticator/Services/SocialService.swift b/WordPressAuthenticator/Services/SocialService.swift index fee855eae..0b256a4eb 100644 --- a/WordPressAuthenticator/Services/SocialService.swift +++ b/WordPressAuthenticator/Services/SocialService.swift @@ -7,7 +7,7 @@ public enum SocialService { /// Google's Signup Linked Account /// case google(user: GIDGoogleUser) - + /// Apple's Signup Linked Account /// case apple(user: AppleUser) diff --git a/WordPressAuthenticator/Services/WordPressComAccountService.swift b/WordPressAuthenticator/Services/WordPressComAccountService.swift index 1abdbd7a6..9f4629e6e 100644 --- a/WordPressAuthenticator/Services/WordPressComAccountService.swift +++ b/WordPressAuthenticator/Services/WordPressComAccountService.swift @@ -1,7 +1,6 @@ import Foundation import WordPressKit - // MARK: - WordPressComAccountService // class WordPressComAccountService { @@ -24,7 +23,7 @@ class WordPressComAccountService { func connect(wpcomAuthToken: String, serviceName: SocialServiceName, serviceToken: String, - connectParameters: [String:AnyObject]? = nil, + connectParameters: [String: AnyObject]? = nil, success: @escaping () -> Void, failure: @escaping (Error) -> Void) { let loggedAPI = WordPressComRestApi(oAuthToken: wpcomAuthToken, @@ -47,7 +46,7 @@ class WordPressComAccountService { /// func requestAuthenticationLink(for email: String, jetpackLogin: Bool, success: @escaping () -> Void, failure: @escaping (Error) -> Void) { let remote = AccountServiceRemoteREST(wordPressComRestApi: anonymousAPI) - + remote.requestWPComAuthLink(forEmail: email, clientID: configuration.wpcomClientId, clientSecret: configuration.wpcomSecret, @@ -91,7 +90,6 @@ class WordPressComAccountService { } } - // MARK: - Nested Types // extension WordPressComAccountService { diff --git a/WordPressAuthenticator/Services/WordPressComBlogService.swift b/WordPressAuthenticator/Services/WordPressComBlogService.swift index 4065226cc..5b08f585b 100644 --- a/WordPressAuthenticator/Services/WordPressComBlogService.swift +++ b/WordPressAuthenticator/Services/WordPressComBlogService.swift @@ -1,7 +1,6 @@ import Foundation import WordPressKit - // MARK: - WordPress.com BlogService // class WordPressComBlogService { @@ -14,7 +13,6 @@ class WordPressComBlogService { return WordPressComRestApi(oAuthToken: nil, userAgent: userAgent, baseUrlString: baseUrl) } - /// Retrieves the WordPressComSiteInfo instance associated to a WordPress.com Site Address. /// func fetchSiteInfo(for address: String, success: @escaping (WordPressComSiteInfo) -> Void, failure: @escaping (Error) -> Void) { @@ -34,7 +32,7 @@ class WordPressComBlogService { failure(result) }) } - + func fetchUnauthenticatedSiteInfoForAddress(for address: String, success: @escaping (WordPressComSiteInfo) -> Void, failure: @escaping (Error) -> Void) { let remote = BlogServiceRemoteREST(wordPressComRestApi: anonymousAPI, siteID: 0) remote.fetchUnauthenticatedSiteInfo(forAddress: address, success: { response in @@ -42,17 +40,16 @@ class WordPressComBlogService { failure(ServiceError.unknown) return } - + let site = WordPressComSiteInfo(remote: response) success(site) }, failure: { error in let result = error ?? ServiceError.unknown failure(result) - }) + }) } } - // MARK: - Nested Types // extension WordPressComBlogService { diff --git a/WordPressAuthenticator/Signin/AppleAuthenticator.swift b/WordPressAuthenticator/Signin/AppleAuthenticator.swift index 81ee1aadf..7332343c9 100644 --- a/WordPressAuthenticator/Signin/AppleAuthenticator.swift +++ b/WordPressAuthenticator/Signin/AppleAuthenticator.swift @@ -61,13 +61,13 @@ private extension AppleAuthenticator { let provider = ASAuthorizationAppleIDProvider() let request = provider.createRequest() request.requestedScopes = [.fullName, .email] - + let controller = ASAuthorizationController(authorizationRequests: [request]) controller.delegate = self controller.presentationContextProvider = self controller.performRequests() - + } } @@ -80,19 +80,19 @@ private extension AppleAuthenticator { DDLogError("Apple Authenticator: invalid Apple credentials.") return } - + tracker.set(flow: .signupWithApple) tracker.track(step: .start) { track(.createAccountInitiated) } - + SVProgressHUD.show(withStatus: NSLocalizedString("Continuing with Apple", comment: "Shown while logging in with Apple and the app waits for the site creation process to complete.")) - + let email = appleCredentials.email ?? "" let name = fullName(from: appleCredentials.fullName) updateLoginFields(email: email, fullName: name, token: token) - + let service = SignupService() service.createWPComUserWithApple(token: token, email: email, fullName: name, success: { [weak self] accountCreated, @@ -104,10 +104,10 @@ private extension AppleAuthenticator { // Notify host app of successful Apple authentication self?.authenticationDelegate.userAuthenticatedWithAppleUserID(appleCredentials.user) - + guard !existingNonSocialAccount else { self?.tracker.set(flow: .loginWithApple) - + if existing2faAccount { self?.show2FA() return @@ -140,26 +140,26 @@ private extension AppleAuthenticator { // This stat is part of a funnel that provides critical information. Before // making ANY modification to this stat please refer to: p4qSXL-35X-p2 track(.createdAccount) - + tracker.track(step: .success) { track(.signupSocialSuccess) } - + showSignupEpilogue(for: credentials) } - + func loginSuccessful(with credentials: AuthenticatorCredentials) { // This stat is part of a funnel that provides critical information. Please // consult with your lead before removing this event. track(.signedIn) - + tracker.track(step: .success) { track(.loginSocialSuccess) } - + showLoginEpilogue(for: credentials) } - + func showSignupEpilogue(for credentials: AuthenticatorCredentials) { guard let navigationController = showFromViewController?.navigationController else { fatalError() @@ -171,7 +171,7 @@ private extension AppleAuthenticator { authenticationDelegate.presentSignupEpilogue(in: navigationController, for: credentials, service: service) } - + func showLoginEpilogue(for credentials: AuthenticatorCredentials) { guard let navigationController = showFromViewController?.navigationController else { fatalError() @@ -179,7 +179,7 @@ private extension AppleAuthenticator { authenticationDelegate.presentLoginEpilogue(in: navigationController, for: credentials) {} } - + func signupFailed(with error: Error) { DDLogError("Apple Authenticator: Signup failed. error: \(error.localizedDescription)") @@ -189,37 +189,37 @@ private extension AppleAuthenticator { let properties = ["error": errorMessage] track(.signupSocialFailure, properties: properties) } - + delegate?.authFailedWithError(message: error.localizedDescription) } - + func logInInstead() { tracker.set(flow: .loginWithApple) tracker.track(step: .start) { track(.signupSocialToLogin) track(.loginSocialSuccess) } - + delegate?.showWPComLogin(loginFields: loginFields) } - + func show2FA() { if tracker.shouldUseLegacyTracker() { track(.signupSocialToLogin) } - + delegate?.showApple2FA(loginFields: loginFields) } - + // MARK: - Helpers - + func fullName(from components: PersonNameComponents?) -> String { guard let name = components else { return "" } return PersonNameComponentsFormatter().string(from: name) } - + func updateLoginFields(email: String, fullName: String, token: String) { updateLoginEmail(email) loginFields.meta.socialServiceIDToken = token @@ -246,13 +246,13 @@ extension AppleAuthenticator: ASAuthorizationControllerDelegate { } func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) { - + // Don't show error if user cancelled authentication. if let authorizationError = error as? ASAuthorizationError, authorizationError.code == .canceled { return } - + DDLogError("Apple Authenticator: didCompleteWithError: \(error.localizedDescription)") let message = NSLocalizedString("Apple authentication failed.\nPlease make sure you are signed in to iCloud with an Apple ID that uses two-factor authentication.", comment: "Message shown when Apple authentication fails.") delegate?.authFailedWithError(message: message) diff --git a/WordPressAuthenticator/Signin/Login2FAViewController.swift b/WordPressAuthenticator/Signin/Login2FAViewController.swift index 5aa3f8d4f..b8bf3ab90 100644 --- a/WordPressAuthenticator/Signin/Login2FAViewController.swift +++ b/WordPressAuthenticator/Signin/Login2FAViewController.swift @@ -27,7 +27,6 @@ class Login2FAViewController: LoginViewController, NUXKeyboardResponder, UITextF // MARK: - Lifecycle Methods - override func viewDidLoad() { super.viewDidLoad() @@ -43,7 +42,6 @@ class Login2FAViewController: LoginViewController, NUXKeyboardResponder, UITextF styleSendCodeButton() } - override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) @@ -57,7 +55,6 @@ class Login2FAViewController: LoginViewController, NUXKeyboardResponder, UITextF WordPressAuthenticator.track(.loginTwoFactorFormViewed) } - override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) unregisterForKeyboardEvents() @@ -69,8 +66,7 @@ class Login2FAViewController: LoginViewController, NUXKeyboardResponder, UITextF verificationCodeField.text = "" } - - /// MARK: Dynamic Type + // MARK: Dynamic Type override func didChangePreferredContentSize() { super.didChangePreferredContentSize() styleSendCodeButton() @@ -84,7 +80,6 @@ class Login2FAViewController: LoginViewController, NUXKeyboardResponder, UITextF // MARK: Configuration Methods - /// Assigns localized strings to various UIControl defined in the storyboard. /// @objc func localizeControls() { @@ -128,7 +123,6 @@ class Login2FAViewController: LoginViewController, NUXKeyboardResponder, UITextF ) } - /// Configure the view's loading state. /// /// - Parameter loading: True if the form should be configured to a "loading" state. @@ -140,7 +134,6 @@ class Login2FAViewController: LoginViewController, NUXKeyboardResponder, UITextF navigationItem.hidesBackButton = loading } - /// Configure the view for an editing state. Should only be called from viewWillAppear /// as this method skips animating any change in height. /// @@ -152,10 +145,8 @@ class Login2FAViewController: LoginViewController, NUXKeyboardResponder, UITextF } } - // MARK: - Instance Methods - /// Validates what is entered in the various form fields and, if valid, /// proceeds with the submit action. /// @@ -185,7 +176,7 @@ class Login2FAViewController: LoginViewController, NUXKeyboardResponder, UITextF // consult with your lead before removing this event. WordPressAuthenticator.track(.signedIn) - var properties = [AnyHashable:Any]() + var properties = [AnyHashable: Any]() if let service = loginFields.meta.socialService?.rawValue { properties["source"] = service } @@ -255,17 +246,15 @@ class Login2FAViewController: LoginViewController, NUXKeyboardResponder, UITextF validateForm() } - @IBAction func handleSubmitButtonTapped(_ sender: UIButton) { tracker.track(click: .submit) - + validateForm() } - @IBAction func handleSendVerificationButtonTapped(_ sender: UIButton) { self.tracker.track(click: .sendCodeWithText) - + let message = NSLocalizedString("SMS Sent", comment: "One Time Code has been sent via SMS") SVProgressHUD.showSuccess(withStatus: message) SVProgressHUD.dismiss(withDelay: Constants.headsUpDismissDelay) @@ -278,16 +267,12 @@ class Login2FAViewController: LoginViewController, NUXKeyboardResponder, UITextF } } - - // MARK: - Handle application state changes. - @objc func applicationBecameInactive() { pasteboardChangeCountBeforeBackground = UIPasteboard.general.changeCount } - @objc func applicationBecameActive() { let emptyField = verificationCodeField.text?.isEmpty ?? true guard emptyField, @@ -296,7 +281,7 @@ class Login2FAViewController: LoginViewController, NUXKeyboardResponder, UITextF } if #available(iOS 14.0, *) { - UIPasteboard.general.detectAuthenticatorCode() { [weak self] result in + UIPasteboard.general.detectAuthenticatorCode { [weak self] result in switch result { case .success(let authenticatorCode): self?.handle(code: authenticatorCode) @@ -322,21 +307,17 @@ class Login2FAViewController: LoginViewController, NUXKeyboardResponder, UITextF } } - // MARK: - Keyboard Notifications - @objc func handleKeyboardWillShow(_ notification: Foundation.Notification) { keyboardWillShow(notification) } - @objc func handleKeyboardWillHide(_ notification: Foundation.Notification) { keyboardWillHide(notification) } } - extension Login2FAViewController { override func displayRemoteError(_ error: Error) { diff --git a/WordPressAuthenticator/Signin/LoginEmailViewController.swift b/WordPressAuthenticator/Signin/LoginEmailViewController.swift index da4208098..67c597188 100644 --- a/WordPressAuthenticator/Signin/LoginEmailViewController.swift +++ b/WordPressAuthenticator/Signin/LoginEmailViewController.swift @@ -2,7 +2,6 @@ import UIKit import WordPressShared import WordPressKit - /// This is the first screen following the log in prologue screen if the user chooses to log in. /// open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { @@ -35,10 +34,8 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { static let keyboardThreshold: CGFloat = 100.0 } - // MARK: Lifecycle Methods - override open func viewDidLoad() { super.viewDidLoad() @@ -88,7 +85,6 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { errorToPresent = nil } - override open func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) unregisterForKeyboardEvents() @@ -108,9 +104,8 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { navigationController?.pushViewController(vc, animated: true) } - - // MARK: - Setup and Configuration + // MARK: - Setup and Configuration /// Hides the self-hosted login option. /// @@ -119,7 +114,6 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { selfHostedLoginButton?.isHidden = loginFields.restrictToWPCom } - /// Assigns localized strings to various UIControl defined in the storyboard. /// func localizeControls() { @@ -139,7 +133,6 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { submitButton?.accessibilityIdentifier = "Login Email Next Button" } - /// Sets up a 1Password button if 1Password is available. /// func setupOnePasswordButtonIfNeeded() { @@ -162,7 +155,7 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { stackView.addConstraints([ button.leadingAnchor.constraint(equalTo: instructionLabel.leadingAnchor), - button.trailingAnchor.constraint(equalTo: instructionLabel.trailingAnchor), + button.trailingAnchor.constraint(equalTo: instructionLabel.trailingAnchor) ]) googleLoginButton = button @@ -182,7 +175,7 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { stackView.addConstraints([ button.leadingAnchor.constraint(equalTo: instructionLabel.leadingAnchor), - button.trailingAnchor.constraint(equalTo: instructionLabel.trailingAnchor), + button.trailingAnchor.constraint(equalTo: instructionLabel.trailingAnchor) ]) selfHostedLoginButton = button @@ -203,7 +196,7 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { // Tapping the Sign up text link in "Don't have an account? _Sign up_" // will present the 3 button view for signing up. - button.on(.touchUpInside) { [weak self] (button) in + button.on(.touchUpInside) { [weak self] (_) in guard let vc = LoginPrologueSignupMethodViewController.instantiate(from: .login) else { DDLogError("Failed to navigate to LoginPrologueSignupMethodViewController") return @@ -230,9 +223,9 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { guard let self = self else { return } - + self.tracker.track(click: .signupWithGoogle) - + guard WordPressAuthenticator.shared.configuration.enableUnifiedAuth else { self.presentGoogleSignupView() return @@ -250,7 +243,7 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { stackView.addConstraints([ button.leadingAnchor.constraint(equalTo: instructionLabel.leadingAnchor), - button.trailingAnchor.constraint(equalTo: instructionLabel.trailingAnchor), + button.trailingAnchor.constraint(equalTo: instructionLabel.trailingAnchor) ]) wpcomSignupButton = button @@ -277,7 +270,6 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { submitButton?.isEnabled = canSubmit() } - /// Sets the view's state to loading or not loading. /// /// - Parameter loading: True if the form should be configured to a "loading" state. @@ -290,7 +282,6 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { submitButton?.showActivityIndicator(loading) } - /// Configure the view for an editing state. Should only be called from viewWillAppear /// as this method skips animating any change in height. /// @@ -302,10 +293,8 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { } } - // MARK: - Instance Methods - /// Makes the call to retrieve Safari shared credentials if they exist. /// func fetchSharedWebCredentialsIfAvailable() { @@ -315,7 +304,6 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { } } - /// Handles Safari shared credentials if any where found. /// /// - Parameters: @@ -342,7 +330,6 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { WordPressAuthenticator.track(.loginAutoFillCredentialsFilled) } - /// Displays the wpcom sign in form, optionally telling it to immedately make /// the call to authenticate with the available credentials. /// @@ -383,7 +370,6 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { navigationController?.pushViewController(vc, animated: true) } - /// Validates what is entered in the various form fields and, if valid, /// proceeds with the submit action. Empties loginFields.meta.socialService as /// social signin does not require form validation. @@ -468,19 +454,16 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { // MARK: - Actions - @IBAction func handleSubmitForm() { if canSubmit() { validateForm() } } - @IBAction func handleSubmitButtonTapped(_ sender: UIButton) { validateForm() } - @objc func handleOnePasswordButtonTapped(_ sender: UIButton) { view.endEditing(true) @@ -501,7 +484,7 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { @objc func googleTapped() { self.tracker.track(click: .loginWithGoogle) - + guard WordPressAuthenticator.shared.configuration.enableUnifiedAuth else { GoogleAuthenticator.sharedInstance.loginDelegate = self GoogleAuthenticator.sharedInstance.showFrom(viewController: self, loginFields: loginFields, for: .login) @@ -517,7 +500,7 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { DDLogError("Failed to navigate to GoogleAuthViewController from LoginPrologueVC") return } - + navigationController?.pushViewController(toVC, animated: true) } @@ -543,24 +526,20 @@ open class LoginEmailViewController: LoginViewController, NUXKeyboardResponder { } } - @IBAction func handleTextFieldEditingDidBegin(_ sender: UITextField) { if !didRequestSafariSharedCredentials { fetchSharedWebCredentialsIfAvailable() } } - // MARK: - Keyboard Notifications - @objc func handleKeyboardWillShow(_ notification: Foundation.Notification) { keyboardWillShow(notification) adjustAlternativeLogInElementsVisibility(true) } - @objc func handleKeyboardWillHide(_ notification: Foundation.Notification) { keyboardWillHide(notification) @@ -629,7 +608,7 @@ extension LoginEmailViewController: GoogleAuthenticatorLoginDelegate { func googleNeedsMultifactorCode(loginFields: LoginFields) { self.loginFields = loginFields configureViewLoading(false) - + guard let vc = Login2FAViewController.instantiate(from: .login) else { DDLogError("Failed to navigate from LoginViewController to Login2FAViewController") return @@ -645,7 +624,7 @@ extension LoginEmailViewController: GoogleAuthenticatorLoginDelegate { func googleExistingUserNeedsConnection(loginFields: LoginFields) { self.loginFields = loginFields configureViewLoading(false) - + guard let vc = LoginWPComViewController.instantiate(from: .login) else { DDLogError("Failed to navigate from Google Login to LoginWPComViewController (password VC)") return diff --git a/WordPressAuthenticator/Signin/LoginLinkRequestViewController.swift b/WordPressAuthenticator/Signin/LoginLinkRequestViewController.swift index d64a85e86..bad209d6b 100644 --- a/WordPressAuthenticator/Signin/LoginLinkRequestViewController.swift +++ b/WordPressAuthenticator/Signin/LoginLinkRequestViewController.swift @@ -2,7 +2,6 @@ import UIKit import CocoaLumberjack import WordPressShared - /// Step one in the auth link flow. This VC displays a form to request a "magic" /// authentication link be emailed to the user. Allows the user to signin via /// email instead of their password. @@ -18,7 +17,6 @@ class LoginLinkRequestViewController: LoginViewController { } } - // MARK: - Lifecycle Methods override func viewDidLoad() { @@ -86,7 +84,6 @@ class LoginLinkRequestViewController: LoginViewController { WPStyleGuide.configureTextButton(usePasswordButton) } - // MARK: - Instance Methods /// Makes the call to request a magic authentication link be emailed to the user. @@ -133,7 +130,6 @@ class LoginLinkRequestViewController: LoginViewController { // MARK: - Actions - @IBAction func handleUsePasswordTapped(_ sender: UIButton) { guard let vc = LoginWPComViewController.instantiate(from: .login) else { DDLogError("Failed to navigate from LoginLinkRequestViewController to LoginWPComViewController") diff --git a/WordPressAuthenticator/Signin/LoginNavigationController.swift b/WordPressAuthenticator/Signin/LoginNavigationController.swift index fa54703d3..3afac060e 100644 --- a/WordPressAuthenticator/Signin/LoginNavigationController.swift +++ b/WordPressAuthenticator/Signin/LoginNavigationController.swift @@ -2,7 +2,6 @@ import UIKit import WordPressShared import WordPressUI - public class LoginNavigationController: RotationAwareNavigationViewController { public override var preferredStatusBarStyle: UIStatusBarStyle { @@ -13,7 +12,7 @@ public class LoginNavigationController: RotationAwareNavigationViewController { // By default, the back button label uses the previous view's title. // To override that, reset the label when pushing a new view controller. self.viewControllers.last?.navigationItem.backBarButtonItem = UIBarButtonItem(title: NSLocalizedString("Back", comment: "Back button title."), style: .plain, target: nil, action: nil) - + super.pushViewController(viewController, animated: animated) } diff --git a/WordPressAuthenticator/Signin/LoginPrologueLoginMethodViewController.swift b/WordPressAuthenticator/Signin/LoginPrologueLoginMethodViewController.swift index 11f1dcc47..d7008633b 100644 --- a/WordPressAuthenticator/Signin/LoginPrologueLoginMethodViewController.swift +++ b/WordPressAuthenticator/Signin/LoginPrologueLoginMethodViewController.swift @@ -1,7 +1,6 @@ import WordPressUI import WordPressShared - /// This class houses the "3 button view": /// Continue with WordPress.com, Continue with Google, Continue with Apple /// and a text link - Or log in by entering your site address. @@ -21,7 +20,7 @@ class LoginPrologueLoginMethodViewController: NUXViewController { private var tracker: AuthenticatorAnalyticsTracker { AuthenticatorAnalyticsTracker.shared } - + /// The big transparent (dismiss) button behind the buttons @IBOutlet private weak var dismissButton: UIButton! @@ -48,14 +47,14 @@ class LoginPrologueLoginMethodViewController: NUXViewController { guard let buttonViewController = buttonViewController else { return } - + let wordpressTitle = NSLocalizedString("Log in or sign up 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 - + guard let self = self else { return } - + self.tracker.set(flow: .wpCom) self.dismiss(animated: true) self.emailTapped?() @@ -84,10 +83,10 @@ class LoginPrologueLoginMethodViewController: NUXViewController { @IBAction func handleSelfHostedButtonTapped(_ sender: UIButton) { dismiss(animated: true) - + tracker.set(flow: .loginWithSiteAddress) tracker.track(click: .loginWithSiteAddress) - + selfHostedTapped?() } @@ -96,7 +95,7 @@ class LoginPrologueLoginMethodViewController: NUXViewController { tracker.track(click: .loginWithApple, ifTrackingNotEnabled: { WordPressAuthenticator.track(.loginSocialButtonClick, properties: ["source": "apple"]) }) - + dismiss(animated: true) appleTapped?() } @@ -104,11 +103,11 @@ class LoginPrologueLoginMethodViewController: NUXViewController { @objc func handleGoogleButtonTapped() { tracker.set(flow: .loginWithGoogle) tracker.track(click: .loginWithGoogle) - + dismiss(animated: true) googleTapped?() } - + // MARK: - Accessibility private func configureForAccessibility() { diff --git a/WordPressAuthenticator/Signin/LoginProloguePageViewController.swift b/WordPressAuthenticator/Signin/LoginProloguePageViewController.swift index 511858a6b..5e48708c7 100644 --- a/WordPressAuthenticator/Signin/LoginProloguePageViewController.swift +++ b/WordPressAuthenticator/Signin/LoginProloguePageViewController.swift @@ -1,7 +1,6 @@ import UIKit import WordPressShared - class LoginProloguePageViewController: UIPageViewController { @objc var pages: [UIViewController] = [] fileprivate var pageControl: UIPageControl? @@ -47,7 +46,6 @@ class LoginProloguePageViewController: UIPageViewController { newControl.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true newControl.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: Constants.pagerHeight).isActive = true - newControl.numberOfPages = pages.count newControl.addTarget(self, action: #selector(handlePageControlValueChanged(sender:)), for: .valueChanged) pageControl = newControl diff --git a/WordPressAuthenticator/Signin/LoginProloguePromoViewController.swift b/WordPressAuthenticator/Signin/LoginProloguePromoViewController.swift index af0758560..c9fc81cac 100644 --- a/WordPressAuthenticator/Signin/LoginProloguePromoViewController.swift +++ b/WordPressAuthenticator/Signin/LoginProloguePromoViewController.swift @@ -2,7 +2,6 @@ import UIKit import Lottie import WordPressShared - class LoginProloguePromoViewController: UIViewController { fileprivate let type: PromoType fileprivate let stackView: UIStackView @@ -135,7 +134,6 @@ class LoginProloguePromoViewController: UIViewController { } } - // MARK: layout private func setupLayout() { diff --git a/WordPressAuthenticator/Signin/LoginPrologueSignupMethodViewController.swift b/WordPressAuthenticator/Signin/LoginPrologueSignupMethodViewController.swift index e2448de03..0a16bf883 100644 --- a/WordPressAuthenticator/Signin/LoginPrologueSignupMethodViewController.swift +++ b/WordPressAuthenticator/Signin/LoginPrologueSignupMethodViewController.swift @@ -2,7 +2,6 @@ import SafariServices import WordPressUI import WordPressShared - class LoginPrologueSignupMethodViewController: NUXViewController { /// Buttons at bottom of screen private var buttonViewController: NUXButtonViewController? @@ -13,7 +12,7 @@ class LoginPrologueSignupMethodViewController: NUXViewController { open var emailTapped: (() -> Void)? open var googleTapped: (() -> Void)? open var appleTapped: (() -> Void)? - + private var tracker: AuthenticatorAnalyticsTracker { AuthenticatorAnalyticsTracker.shared } @@ -47,9 +46,9 @@ class LoginPrologueSignupMethodViewController: NUXViewController { let loginTitle = NSLocalizedString("Sign up with Email", comment: "Button title. Tapping begins our normal sign up process.") buttonViewController.setupTopButton(title: loginTitle, isPrimary: false, accessibilityIdentifier: "Sign up with Email Button") { [weak self] in - + self?.tracker.set(flow: .wpCom) - + defer { WordPressAuthenticator.track(.signupEmailButtonTapped) } @@ -60,7 +59,7 @@ class LoginPrologueSignupMethodViewController: NUXViewController { buttonViewController.setupButtomButtonFor(socialService: .google, onTap: handleGoogleButtonTapped) let termsButton = WPStyleGuide.termsButton() - termsButton.on(.touchUpInside) { [weak self] button in + termsButton.on(.touchUpInside) { [weak self] _ in defer { self?.tracker.track(click: .termsOfService, ifTrackingNotEnabled: { WordPressAuthenticator.track(.signupTermsButtonTapped) @@ -94,7 +93,7 @@ class LoginPrologueSignupMethodViewController: NUXViewController { tracker.track(click: .signupWithApple, ifTrackingNotEnabled: { WordPressAuthenticator.track(.signupSocialButtonTapped, properties: ["source": "apple"]) }) - + dismiss(animated: true) appleTapped?() } @@ -108,7 +107,7 @@ class LoginPrologueSignupMethodViewController: NUXViewController { dismiss(animated: true) googleTapped?() } - + private func trackCancellationAndThenDismiss() { WordPressAuthenticator.track(.signupCancelled) dismiss(animated: true) diff --git a/WordPressAuthenticator/Signin/LoginPrologueViewController.swift b/WordPressAuthenticator/Signin/LoginPrologueViewController.swift index d201b1626..58dd366b4 100644 --- a/WordPressAuthenticator/Signin/LoginPrologueViewController.swift +++ b/WordPressAuthenticator/Signin/LoginPrologueViewController.swift @@ -59,7 +59,7 @@ class LoginPrologueViewController: LoginViewController { topContainerChildViewController.view.translatesAutoresizingMaskIntoConstraints = false topContainerView.pinSubviewToAllEdges(topContainerChildViewController.view) } - + defaultButtonViewMargin = buttonViewLeadingConstraint?.constant ?? 0 } @@ -68,20 +68,20 @@ class LoginPrologueViewController: LoginViewController { super.styleBackground() return } - + view.backgroundColor = unifiedBackgroundColor } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - + configureButtonVC() navigationController?.setNavigationBarHidden(true, animated: false) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - + // We've found some instances where the iCloud Keychain login flow was being started // when the device was idle and the app was logged out and in the background. I couldn't // find precise reproduction steps for this issue but my guess is that some background @@ -93,7 +93,7 @@ class LoginPrologueViewController: LoginViewController { guard UIApplication.shared.applicationState != .background else { return } - + WordPressAuthenticator.track(.loginPrologueViewed) tracker.set(flow: .prologue) @@ -104,7 +104,7 @@ class LoginPrologueViewController: LoginViewController { } else { tracker.set(step: .prologue) } - + showiCloudKeychainLoginFlow() } @@ -117,19 +117,19 @@ class LoginPrologueViewController: LoginViewController { override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return UIDevice.isPad() ? .all : .portrait } - + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) setButtonViewMargins(forWidth: view.frame.width) } - + override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) setButtonViewMargins(forWidth: size.width) } - + // MARK: - iCloud Keychain Login - + /// Starts the iCloud Keychain login flow if the conditions are given. /// private func showiCloudKeychainLoginFlow() { @@ -199,15 +199,15 @@ class LoginPrologueViewController: LoginViewController { let displayStrings = WordPressAuthenticator.shared.displayStrings let loginTitle = displayStrings.continueWithWPButtonTitle let siteAddressTitle = displayStrings.enterYourSiteAddressButtonTitle - + if configuration.continueWithSiteAddressFirst { buildUnifiedPrologueButtonsWithSiteAddressFirst(buttonViewController, loginTitle: loginTitle, siteAddressTitle: siteAddressTitle) return } - + buildDefaultUnifiedPrologueButtons(buttonViewController, loginTitle: loginTitle, siteAddressTitle: siteAddressTitle) } - + private func buildDefaultUnifiedPrologueButtons(_ buttonViewController: NUXButtonViewController, loginTitle: String, siteAddressTitle: String) { setButtonViewMargins(forWidth: view.frame.width) @@ -222,23 +222,23 @@ class LoginPrologueViewController: LoginViewController { setButtonViewControllerBackground(buttonViewController) } - + private func buildUnifiedPrologueButtonsWithSiteAddressFirst(_ buttonViewController: NUXButtonViewController, loginTitle: String, siteAddressTitle: String) { guard configuration.enableUnifiedAuth == true else { return } - + setButtonViewMargins(forWidth: view.frame.width) buttonViewController.setupTopButton(title: siteAddressTitle, isPrimary: true, accessibilityIdentifier: "Prologue Self Hosted Button", onTap: siteAddressTapCallback()) - - buttonViewController.setupBottomButton(title: loginTitle, isPrimary: false, accessibilityIdentifier: "Prologue Continue Button", onTap:loginTapCallback()) - + + buttonViewController.setupBottomButton(title: loginTitle, isPrimary: false, accessibilityIdentifier: "Prologue Continue Button", onTap: loginTapCallback()) + showCancelIfNeccessary(buttonViewController) setButtonViewControllerBackground(buttonViewController) } - + private func siteAddressTapCallback() -> NUXButtonViewController.CallBackType { return { [weak self] in self?.siteAddressTapped() @@ -250,12 +250,12 @@ class LoginPrologueViewController: LoginViewController { guard let self = self else { return } - + self.tracker.track(click: .continueWithWordPressCom) self.continueWithDotCom() } } - + private func showCancelIfNeccessary(_ buttonViewController: NUXButtonViewController) { if showCancel { let cancelTitle = NSLocalizedString("Cancel", comment: "Button title. Tapping it cancels the login flow.") @@ -264,7 +264,7 @@ class LoginPrologueViewController: LoginViewController { } } } - + private func setButtonViewControllerBackground(_ buttonViewController: NUXButtonViewController) { // Fallback to setting the button background color to clear so the blur effect blurs the Prologue background color. let buttonsBackgroundColor = WordPressAuthenticator.shared.unifiedStyle?.prologueButtonsBackgroundColor ?? .clear @@ -330,7 +330,7 @@ class LoginPrologueViewController: LoginViewController { /// private func signupTapped() { tracker.set(source: .default) - + // This stat is part of a funnel that provides critical information. // Before making ANY modification to this stat please refer to: p4qSXL-35X-p2 WordPressAuthenticator.track(.signupButtonTapped) @@ -362,7 +362,7 @@ class LoginPrologueViewController: LoginViewController { guard let self = self else { return } - + guard self.configuration.enableUnifiedAuth else { self.presentGoogleSignupView() return @@ -389,7 +389,7 @@ class LoginPrologueViewController: LoginViewController { GoogleAuthenticator.sharedInstance.showFrom(viewController: self, loginFields: loginFields, for: .login) return } - + presentUnifiedGoogleView() } @@ -454,7 +454,7 @@ class LoginPrologueViewController: LoginViewController { DDLogError("Failed to navigate to GoogleAuthViewController from LoginPrologueVC") return } - + navigationController?.pushViewController(toVC, animated: true) } @@ -473,20 +473,20 @@ class LoginPrologueViewController: LoginViewController { DDLogError("Failed to navigate from LoginPrologueViewController to LoginWPComViewController") return } - + vc.loginFields = self.loginFields vc.dismissBlock = dismissBlock vc.errorToPresent = errorToPresent - + navigationController?.pushViewController(vc, animated: true) } - + private func presentUnifiedPassword() { guard let vc = PasswordViewController.instantiate(from: .password) else { DDLogError("Failed to navigate from LoginPrologueViewController to PasswordViewController") return } - + vc.loginFields = loginFields navigationController?.pushViewController(vc, animated: true) } @@ -525,7 +525,7 @@ extension LoginPrologueViewController: AppleAuthenticatorDelegate { self.loginFields = loginFields signInAppleAccount() } - + func authFailedWithError(message: String) { displayErrorAlert(message, sourceTag: .loginApple) } @@ -592,28 +592,28 @@ private extension LoginPrologueViewController { /// Used only in unified views. /// func setButtonViewMargins(forWidth viewWidth: CGFloat) { - + guard configuration.enableUnifiedAuth else { return } - + guard traitCollection.horizontalSizeClass == .regular && traitCollection.verticalSizeClass == .regular else { buttonViewLeadingConstraint?.constant = defaultButtonViewMargin buttonViewTrailingConstraint?.constant = defaultButtonViewMargin return } - + let marginMultiplier = UIDevice.current.orientation.isLandscape ? ButtonViewMarginMultipliers.ipadLandscape : ButtonViewMarginMultipliers.ipadPortrait - + let margin = viewWidth * marginMultiplier - + buttonViewLeadingConstraint?.constant = margin buttonViewTrailingConstraint?.constant = margin } - + private enum ButtonViewMarginMultipliers { static let ipadPortrait: CGFloat = 0.1667 static let ipadLandscape: CGFloat = 0.25 diff --git a/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift b/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift index 7798de651..b71897290 100644 --- a/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift +++ b/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift @@ -26,7 +26,6 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { } } - // MARK: - Lifecycle Methods override func viewDidLoad() { @@ -39,7 +38,6 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { configureForAcessibility() } - override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) @@ -53,7 +51,6 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { setupNavBarIcon() } - override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) @@ -63,17 +60,13 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { WordPressAuthenticator.track(.loginUsernamePasswordFormViewed) } - override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) unregisterForKeyboardEvents() } - - // MARK: - Setup and Configuration - /// Assigns localized strings to various UIControl defined in the storyboard. /// @objc func localizeControls() { @@ -90,7 +83,6 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { forgotPasswordButton.titleLabel?.numberOfLines = 0 } - /// Sets up necessary accessibility labels and attributes for the all the UI elements in self. /// private func configureForAcessibility() { @@ -110,7 +102,6 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { forgotPasswordButton.accessibilityTraits = .link } - /// Sets up a 1Password button if 1Password is available. /// @objc func setupOnePasswordButtonIfNeeded() { @@ -119,7 +110,6 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { selector: #selector(handleOnePasswordButtonTapped(_:))) } - /// Configures the content of the text fields based on what is saved in `loginFields`. /// @objc func configureTextFields() { @@ -129,7 +119,6 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { usernameField.contentInsets = WPStyleGuide.edgeInsetForLoginTextFields() } - /// Configures the appearance and state of the forgot password button. /// @objc func configureForgotPasswordButton() { @@ -137,7 +126,6 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { WPStyleGuide.configureTextButton(forgotPasswordButton) } - /// Configures the appearance and state of the submit button. /// override func configureSubmitButton(animating: Bool) { @@ -150,7 +138,6 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { ) } - /// Sets the view's state to loading or not loading. /// /// - Parameter loading: True if the form should be configured to a "loading" state. @@ -164,7 +151,6 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { navigationItem.hidesBackButton = loading } - /// Configure the view for an editing state. Should only be called from viewWillAppear /// as this method skips animating any change in height. /// @@ -176,7 +162,6 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { } } - /// Configure the site header. /// @objc func configureHeader() { @@ -187,7 +172,6 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { } } - /// Configure the site header to show the BlogDetailsHeaderView /// func configureBlogDetailHeaderView(siteInfo: WordPressComSiteInfo) { @@ -200,7 +184,6 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { siteHeaderView.downloadBlavatar(at: siteInfo.icon) } - /// Configure the site header to show the site address label. /// @objc func configureSiteAddressHeader() { @@ -211,7 +194,6 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { siteHeaderView.blavatarImage = .linkFieldImage } - /// Sanitize and format the site address we show to users. /// @objc func sanitizedSiteAddress(siteAddress: String) -> String { @@ -222,10 +204,8 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { return siteAddress } - // MARK: - Instance Methods - /// Validates what is entered in the various form fields and, if valid, /// proceeds with the submit action. /// @@ -233,7 +213,6 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { validateFormAndLogin() } - // MARK: - Actions @IBAction func handleTextFieldDidChange(_ sender: UITextField) { @@ -244,12 +223,10 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { configureSubmitButton(animating: false) } - @IBAction func handleSubmitButtonTapped(_ sender: UIButton) { validateForm() } - @objc func handleOnePasswordButtonTapped(_ sender: UIButton) { view.endEditing(true) @@ -267,18 +244,15 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { // MARK: - Keyboard Notifications - @objc func handleKeyboardWillShow(_ notification: Foundation.Notification) { keyboardWillShow(notification) } - @objc func handleKeyboardWillHide(_ notification: Foundation.Notification) { keyboardWillHide(notification) } } - extension LoginSelfHostedViewController { func finishedLogin(withUsername username: String, password: String, xmlrpc: String, options: [AnyHashable: Any]) { @@ -297,12 +271,10 @@ extension LoginSelfHostedViewController { } } - func displayLoginMessage(_ message: String) { configureForgotPasswordButton() } - override func displayRemoteError(_ error: Error) { displayLoginMessage("") configureViewLoading(false) @@ -317,7 +289,6 @@ extension LoginSelfHostedViewController { } } - extension LoginSelfHostedViewController: UITextFieldDelegate { func textFieldShouldReturn(_ textField: UITextField) -> Bool { if textField == usernameField { diff --git a/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift b/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift index 6e0c696f7..d83661b4e 100644 --- a/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift +++ b/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift @@ -3,7 +3,6 @@ import WordPressShared import WordPressKit import WordPressUI - class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder { @IBOutlet weak var siteURLField: WPWalkthroughTextField! @IBOutlet var siteAddressHelpButton: UIButton! @@ -15,7 +14,6 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder } } - override var loginFields: LoginFields { didSet { // Clear the site url and site info (if any) from LoginFields @@ -23,12 +21,12 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder loginFields.meta.siteInfo = nil } } - + // MARK: - URL Validation - + private lazy var urlErrorDebouncer = Debouncer(delay: 2) { [weak self] in let errorMessage = NSLocalizedString("Please enter a complete website address, like example.com.", comment: "Error message shown when a URL is invalid.") - + self?.displayError(message: errorMessage) } @@ -40,7 +38,6 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder configureForAccessibility() } - override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) @@ -55,7 +52,6 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder navigationController?.setNavigationBarHidden(false, animated: false) } - override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) @@ -64,7 +60,6 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder WordPressAuthenticator.track(.loginURLFormViewed) } - override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) unregisterForKeyboardEvents() @@ -72,7 +67,6 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder // MARK: Setup and Configuration - /// Assigns localized strings to various UIControl defined in the storyboard. /// @objc func localizeControls() { @@ -105,7 +99,6 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder siteURLField.text = loginFields.siteAddress } - /// Configures the appearance and state of the submit button. /// override func configureSubmitButton(animating: Bool) { @@ -116,7 +109,6 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder ) } - /// Sets the view's state to loading or not loading. /// /// - Parameter loading: True if the form should be configured to a "loading" state. @@ -128,7 +120,6 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder navigationItem.hidesBackButton = loading } - /// Configure the view for an editing state. Should only be called from viewWillAppear /// as this method skips animating any change in height. /// @@ -144,17 +135,15 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder WPStyleGuide.configureTextButton(siteAddressHelpButton) } - // MARK: - Instance Methods - /// Validates what is entered in the various form fields and, if valid, /// proceeds with the submit action. /// @objc func validateForm() { view.endEditing(true) displayError(message: "") - + // We need to to this here because before this point we need the URL to be pre-validated // exactly as the user inputs it, and after this point we need the URL to be the base site URL. // This isn't really great, but it's the only sane solution I could come up with given the current @@ -200,7 +189,7 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder } }) } - + @objc func fetchSiteInfo() { let baseSiteUrl = WordPressAuthenticator.baseSiteURL(string: loginFields.siteAddress) let service = WordPressComBlogService() @@ -216,7 +205,7 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder } self.presentNextControllerIfPossible(siteInfo: siteInfo) } - service.fetchUnauthenticatedSiteInfoForAddress(for: baseSiteUrl, success: successBlock, failure: { [weak self] error in + service.fetchUnauthenticatedSiteInfoForAddress(for: baseSiteUrl, success: successBlock, failure: { [weak self] _ in self?.configureViewLoading(false) guard let self = self else { return @@ -235,11 +224,11 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder self.showSelfHostedUsernamePassword() } - self.showWPUsernamePassword() + self.showWPUsernamePassword() case .presentEmailController: // This case is only used for UL&S break - case .injectViewController(_): + case .injectViewController: // This case is only used for UL&S break } @@ -252,7 +241,7 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder } return err } - + /// Here we will continue with the self-hosted flow. /// @objc func showSelfHostedUsernamePassword() { @@ -300,9 +289,9 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder alertController.addDefaultActionWithTitle(acceptActionTitle) present(alertController, animated: true) } - + // MARK: - URL Validation - + /// Does a local / quick Site Address validation and refreshes the UI with an error /// if necessary. /// @@ -310,7 +299,7 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder /// private func refreshSiteAddressError(immediate: Bool) { let showError = !loginFields.siteAddress.isEmpty && !loginFields.validateSiteForSignin() - + if showError { urlErrorDebouncer.call(immediate: immediate) } else { @@ -349,15 +338,13 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder @IBAction func handleEditingDidEnd(_ sender: UITextField) { refreshSiteAddressError(immediate: true) } - - // MARK: - Keyboard Notifications + // MARK: - Keyboard Notifications @objc func handleKeyboardWillShow(_ notification: Foundation.Notification) { keyboardWillShow(notification) } - @objc func handleKeyboardWillHide(_ notification: Foundation.Notification) { keyboardWillHide(notification) } diff --git a/WordPressAuthenticator/Signin/LoginSocialErrorCell.swift b/WordPressAuthenticator/Signin/LoginSocialErrorCell.swift index 8fe7cdd92..0b495f762 100644 --- a/WordPressAuthenticator/Signin/LoginSocialErrorCell.swift +++ b/WordPressAuthenticator/Signin/LoginSocialErrorCell.swift @@ -1,6 +1,5 @@ import WordPressShared - open class LoginSocialErrorCell: UITableViewCell { private let errorTitle: String private let errorDescription: String @@ -10,7 +9,7 @@ open class LoginSocialErrorCell: UITableViewCell { private let labelStack: UIStackView private var forUnified: Bool = false - + private struct Constants { static let labelSpacing: CGFloat = 15.0 static let labelVerticalMargin: CGFloat = 20.0 @@ -84,12 +83,12 @@ open class LoginSocialErrorCell: UITableViewCell { } else { descriptionLabel.text = errorDescription } - + guard let unifiedBackgroundColor = WordPressAuthenticator.shared.unifiedStyle?.viewControllerBackgroundColor else { backgroundColor = WordPressAuthenticator.shared.style.viewControllerBackgroundColor return } - + backgroundColor = forUnified ? unifiedBackgroundColor : WordPressAuthenticator.shared.style.viewControllerBackgroundColor } } diff --git a/WordPressAuthenticator/Signin/LoginSocialErrorViewController.swift b/WordPressAuthenticator/Signin/LoginSocialErrorViewController.swift index fa4952a99..d301db33b 100644 --- a/WordPressAuthenticator/Signin/LoginSocialErrorViewController.swift +++ b/WordPressAuthenticator/Signin/LoginSocialErrorViewController.swift @@ -2,7 +2,6 @@ import Foundation import Gridicons import WordPressShared - @objc protocol LoginSocialErrorViewControllerDelegate { func retryWithEmail() @@ -15,12 +14,12 @@ protocol LoginSocialErrorViewControllerDelegate { class LoginSocialErrorViewController: NUXTableViewController { fileprivate var errorTitle: String fileprivate var errorDescription: String - @objc var delegate: LoginSocialErrorViewControllerDelegate? - + @objc weak var delegate: LoginSocialErrorViewControllerDelegate? + private var forUnified: Bool = false private var actionButtonTapped: Bool = false private let unifiedAuthEnabled = WordPressAuthenticator.shared.configuration.enableUnifiedAuth - + fileprivate enum Sections: Int { case titleAndDescription = 0 case buttons = 1 @@ -77,7 +76,7 @@ class LoginSocialErrorViewController: NUXTableViewController { delegate?.errorDismissed() } } - + private func styleBackground() { guard let unifiedBackgroundColor = WordPressAuthenticator.shared.unifiedStyle?.viewControllerBackgroundColor else { view.backgroundColor = WordPressAuthenticator.shared.style.viewControllerBackgroundColor @@ -86,7 +85,7 @@ class LoginSocialErrorViewController: NUXTableViewController { view.backgroundColor = forUnified ? unifiedBackgroundColor : WordPressAuthenticator.shared.style.viewControllerBackgroundColor } - + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { guard indexPath.section == Sections.buttons.rawValue, let delegate = delegate else { @@ -94,7 +93,7 @@ class LoginSocialErrorViewController: NUXTableViewController { } actionButtonTapped = true - + switch indexPath.row { case Buttons.tryEmail.rawValue: delegate.retryWithEmail() @@ -112,7 +111,6 @@ class LoginSocialErrorViewController: NUXTableViewController { } } - // MARK: UITableViewDelegate methods extension LoginSocialErrorViewController { @@ -130,14 +128,13 @@ extension LoginSocialErrorViewController { } } - // MARK: UITableViewDataSource methods extension LoginSocialErrorViewController { private func numberOfButtonsToShow() -> Int { - + var buttonCount = loginFields.restrictToWPCom ? Buttons.count - 1 : Buttons.count - + // Don't show the Signup Retry if showing unified social flows. // At this point, we've already tried signup and are past it. let unifiedGoogle = unifiedAuthEnabled && loginFields.meta.socialService == .google @@ -146,7 +143,7 @@ extension LoginSocialErrorViewController { if unifiedGoogle || unifiedApple { buttonCount -= 1 } - + return buttonCount } diff --git a/WordPressAuthenticator/Signin/LoginUsernamePasswordViewController.swift b/WordPressAuthenticator/Signin/LoginUsernamePasswordViewController.swift index e48a11647..44dcd3bc4 100644 --- a/WordPressAuthenticator/Signin/LoginUsernamePasswordViewController.swift +++ b/WordPressAuthenticator/Signin/LoginUsernamePasswordViewController.swift @@ -26,7 +26,6 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo } } - // MARK: - Lifecycle Methods override func viewDidLoad() { @@ -38,7 +37,6 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo displayLoginMessage("") } - override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) @@ -52,7 +50,6 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo setupNavBarIcon() } - override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) @@ -62,17 +59,13 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo WordPressAuthenticator.track(.loginUsernamePasswordFormViewed) } - override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) unregisterForKeyboardEvents() } - - // MARK: - Setup and Configuration - /// Assigns localized strings to various UIControl defined in the storyboard. /// @objc func localizeControls() { @@ -91,7 +84,6 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo forgotPasswordButton.titleLabel?.numberOfLines = 0 } - /// Sets up a 1Password button if 1Password is available. /// @objc func setupOnePasswordButtonIfNeeded() { @@ -100,7 +92,6 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo selector: #selector(handleOnePasswordButtonTapped(_:))) } - /// Configures the content of the text fields based on what is saved in `loginFields`. /// @objc func configureTextFields() { @@ -110,7 +101,6 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo usernameField.contentInsets = WPStyleGuide.edgeInsetForLoginTextFields() } - /// Configures the appearance and state of the forgot password button. /// @objc func configureForgotPasswordButton() { @@ -118,7 +108,6 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo WPStyleGuide.configureTextButton(forgotPasswordButton) } - /// Configures the appearance and state of the submit button. /// override func configureSubmitButton(animating: Bool) { @@ -131,7 +120,6 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo ) } - /// Sets the view's state to loading or not loading. /// /// - Parameter loading: True if the form should be configured to a "loading" state. @@ -145,7 +133,6 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo navigationItem.hidesBackButton = loading } - /// Configure the view for an editing state. Should only be called from viewWillAppear /// as this method skips animating any change in height. /// @@ -157,7 +144,6 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo } } - /// Configure the site header. /// @objc func configureHeader() { @@ -168,7 +154,6 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo } } - /// Configure the site header to show the BlogDetailsHeaderView /// func configureBlogDetailHeaderView(siteInfo: WordPressComSiteInfo) { @@ -181,7 +166,6 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo siteHeaderView.downloadBlavatar(at: siteInfo.icon) } - /// Configure the site header to show the site address label. /// @objc func configureSiteAddressHeader() { @@ -192,7 +176,6 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo siteHeaderView.blavatarImage = .linkFieldImage } - /// Sanitize and format the site address we show to users. /// @objc func sanitizedSiteAddress(siteAddress: String) -> String { @@ -203,7 +186,6 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo return siteAddress } - // MARK: - Instance Methods /// Validates what is entered in the various form fields and, if valid, @@ -213,7 +195,6 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo validateFormAndLogin() } - // MARK: - Actions @IBAction func handleTextFieldDidChange(_ sender: UITextField) { @@ -224,12 +205,10 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo configureSubmitButton(animating: false) } - @IBAction func handleSubmitButtonTapped(_ sender: UIButton) { validateForm() } - @objc func handleOnePasswordButtonTapped(_ sender: UIButton) { view.endEditing(true) @@ -247,25 +226,21 @@ class LoginUsernamePasswordViewController: LoginViewController, NUXKeyboardRespo // MARK: - Keyboard Notifications - @objc func handleKeyboardWillShow(_ notification: Foundation.Notification) { keyboardWillShow(notification) } - @objc func handleKeyboardWillHide(_ notification: Foundation.Notification) { keyboardWillHide(notification) } } - extension LoginUsernamePasswordViewController { func displayLoginMessage(_ message: String) { configureForgotPasswordButton() } - override func displayRemoteError(_ error: Error) { displayLoginMessage("") configureViewLoading(false) @@ -278,7 +253,6 @@ extension LoginUsernamePasswordViewController { } } - extension LoginUsernamePasswordViewController: UITextFieldDelegate { func textFieldShouldReturn(_ textField: UITextField) -> Bool { if textField == usernameField { @@ -289,4 +263,3 @@ extension LoginUsernamePasswordViewController: UITextFieldDelegate { return true } } - diff --git a/WordPressAuthenticator/Signin/LoginViewController.swift b/WordPressAuthenticator/Signin/LoginViewController.swift index 0075ab48a..a4ab01190 100644 --- a/WordPressAuthenticator/Signin/LoginViewController.swift +++ b/WordPressAuthenticator/Signin/LoginViewController.swift @@ -2,12 +2,11 @@ import WordPressShared import WordPressKit import GoogleSignIn - /// View Controller for login-specific screens open class LoginViewController: NUXViewController, LoginFacadeDelegate { @IBOutlet var instructionLabel: UILabel? @objc var errorToPresent: Error? - + let tracker = AuthenticatorAnalyticsTracker.shared /// Constraints on the table view container. @@ -15,7 +14,7 @@ open class LoginViewController: NUXViewController, LoginFacadeDelegate { @IBOutlet var tableViewLeadingConstraint: NSLayoutConstraint? @IBOutlet var tableViewTrailingConstraint: NSLayoutConstraint? var defaultTableViewMargin: CGFloat = 0 - + lazy var loginFacade: LoginFacade = { let configuration = WordPressAuthenticator.shared.configuration let facade = LoginFacade(dotcomClientID: configuration.wpcomClientId, @@ -106,9 +105,9 @@ open class LoginViewController: NUXViewController, LoginFacadeDelegate { errorLabel?.isHidden = true return } - + tracker.track(failure: message) - + errorLabel?.isHidden = false errorLabel?.text = message errorToPresent = nil @@ -126,7 +125,6 @@ open class LoginViewController: NUXViewController, LoginFacadeDelegate { return isSignUp && authenticationDelegate.shouldPresentSignupEpilogue() } - // MARK: - Epilogue func showSignupEpilogue(for credentials: AuthenticatorCredentials) { @@ -171,7 +169,6 @@ open class LoginViewController: NUXViewController, LoginFacadeDelegate { loginFacade.signIn(with: loginFields) } - // MARK: SigninWPComSyncHandler methods dynamic open func finishedLogin(withAuthToken authToken: String, requiredMultifactorCode: Bool) { let wpcom = WordPressComCredentials(authToken: authToken, isJetpackLogin: isJetpackLogin, multifactor: requiredMultifactorCode, siteURL: loginFields.siteAddress) @@ -206,21 +203,21 @@ open class LoginViewController: NUXViewController, LoginFacadeDelegate { if tracker.shouldUseLegacyTracker() { WordPressAuthenticator.track(.twoFactorCodeRequested) } - + let unifiedAuthEnabled = WordPressAuthenticator.shared.configuration.enableUnifiedAuth let unifiedGoogle = unifiedAuthEnabled && loginFields.meta.socialService == .google let unifiedApple = unifiedAuthEnabled && loginFields.meta.socialService == .apple let unifiedSiteAddress = unifiedAuthEnabled && !loginFields.siteAddress.isEmpty let unifiedWordPress = unifiedAuthEnabled && loginFields.meta.userIsDotCom - - guard (unifiedGoogle || unifiedApple || unifiedSiteAddress || unifiedWordPress) else { + + guard unifiedGoogle || unifiedApple || unifiedSiteAddress || unifiedWordPress else { presentLogin2FA() return } - + presentUnified2FA() } - + private enum LocalizedText { static let loginError = NSLocalizedString("Whoops, something went wrong and we couldn't log you in. Please try again!", comment: "An error message shown when a wpcom user provides the wrong password.") static let missingInfoError = NSLocalizedString("Please fill out all the fields", comment: "A short prompt asking the user to properly fill out all login fields.") @@ -250,17 +247,17 @@ extension LoginViewController { /// func syncWPComAndPresentEpilogue( credentials: AuthenticatorCredentials, - completion: (() -> ())? = nil) { - + completion: (() -> Void)? = nil) { + configureStatusLabel(LocalizedText.gettingAccountInfo) - + syncWPCom(credentials: credentials) { [weak self] in guard let self = self else { return } - + completion?() - + self.presentEpilogue(credentials: credentials) self.configureStatusLabel("") self.configureViewLoading(false) @@ -270,7 +267,7 @@ extension LoginViewController { /// Signals the Main App to synchronize the specified WordPress.com account. /// - func syncWPCom(credentials: AuthenticatorCredentials, completion: (() -> ())? = nil) { + func syncWPCom(credentials: AuthenticatorCredentials, completion: (() -> Void)? = nil) { authenticationDelegate.sync(credentials: credentials) { completion?() } @@ -300,14 +297,14 @@ extension LoginViewController { guard let serviceName = loginFields.meta.socialService, let serviceToken = loginFields.meta.socialServiceIDToken else { return } - - let appleConnectParameters:[String:AnyObject]? = { + + let appleConnectParameters: [String: AnyObject]? = { if let appleUser = loginFields.meta.appleUser { return AccountServiceRemoteREST.appleSignInParameters(email: appleUser.email, fullName: appleUser.fullName) } return nil }() - + linkSocialService(serviceName: serviceName, serviceToken: serviceToken, wpcomAuthToken: wpcomAuthToken, @@ -319,7 +316,7 @@ extension LoginViewController { func linkSocialService(serviceName: SocialServiceName, serviceToken: String, wpcomAuthToken: String, - appleConnectParameters: [String:AnyObject]? = nil) { + appleConnectParameters: [String: AnyObject]? = nil) { let service = WordPressComAccountService() service.connect(wpcomAuthToken: wpcomAuthToken, serviceName: serviceName, @@ -330,7 +327,7 @@ extension LoginViewController { // consult with your lead before removing this event. let source = appleConnectParameters != nil ? "apple" : "google" WordPressAuthenticator.track(.signedIn, properties: ["source": source]) - + if AuthenticatorAnalyticsTracker.shared.shouldUseLegacyTracker() { WordPressAuthenticator.track(.loginSocialConnectSuccess) WordPressAuthenticator.track(.loginSocialSuccess) @@ -350,11 +347,10 @@ extension LoginViewController { } } - // MARK: - Handle View Changes // extension LoginViewController { - + open override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) @@ -362,11 +358,11 @@ extension LoginViewController { if previousTraitCollection?.preferredContentSizeCategory != traitCollection.preferredContentSizeCategory { didChangePreferredContentSize() } - + // Update Table View size setTableViewMargins(forWidth: view.frame.width) } - + open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) setTableViewMargins(forWidth: size.width) @@ -397,12 +393,12 @@ extension LoginViewController { tableViewLeadingConstraint.constant = margin tableViewTrailingConstraint.constant = margin } - + private enum TableViewMarginMultipliers { static let ipadPortrait: CGFloat = 0.1667 static let ipadLandscape: CGFloat = 0.25 } - + } // MARK: - Social Sign In Handling @@ -413,7 +409,7 @@ extension LoginViewController { // Remove the Waiting for Google view so it doesn't reappear when backing through the navigation stack. navigationController?.viewControllers.removeAll(where: { $0 is GoogleAuthViewController }) } - + func signInAppleAccount() { guard let token = loginFields.meta.socialServiceIDToken else { WordPressAuthenticator.track(.loginSocialButtonFailure, properties: ["source": SocialServiceName.apple.rawValue]) @@ -423,7 +419,7 @@ extension LoginViewController { loginFacade.loginToWordPressDotCom(withSocialIDToken: token, service: SocialServiceName.apple.rawValue) } - + /// Updates the LoginFields structure, with the specified Google User + Token + Email. /// func updateLoginFields(googleUser: GIDGoogleUser, googleToken: String, googleEmail: String) { @@ -432,7 +428,7 @@ extension LoginViewController { loginFields.meta.socialServiceIDToken = googleToken loginFields.meta.googleUser = googleUser } - + // Used by SIWA when logging with with a passwordless, 2FA account. // func socialNeedsMultifactorCode(forUserID userID: Int, andNonceInfo nonceInfo: SocialLogin2FANonceInfo) { @@ -446,36 +442,36 @@ extension LoginViewController { presentUnified2FA() } - + private func presentLogin2FA() { - var properties = [AnyHashable:Any]() + var properties = [AnyHashable: Any]() if let service = loginFields.meta.socialService?.rawValue { properties["source"] = service } - + if tracker.shouldUseLegacyTracker() { WordPressAuthenticator.track(.loginSocial2faNeeded, properties: properties) } - + guard let vc = Login2FAViewController.instantiate(from: .login) else { DDLogError("Failed to navigate from LoginViewController to Login2FAViewController") return } - + vc.loginFields = loginFields vc.dismissBlock = dismissBlock vc.errorToPresent = errorToPresent - + navigationController?.pushViewController(vc, animated: true) } - + private func presentUnified2FA() { - + guard let vc = TwoFAViewController.instantiate(from: .twoFA) else { DDLogError("Failed to navigate from LoginViewController to TwoFAViewController") return } - + vc.loginFields = loginFields navigationController?.pushViewController(vc, animated: true) } @@ -485,36 +481,36 @@ extension LoginViewController { // MARK: - LoginSocialError delegate methods extension LoginViewController: LoginSocialErrorViewControllerDelegate { - + func retryWithEmail() { loginFields.username = "" cleanupAfterSocialErrors() navigationController?.popToRootViewController(animated: true) } - + func retryWithAddress() { cleanupAfterSocialErrors() loginToSelfHostedSite() } - + func retryAsSignup() { cleanupAfterSocialErrors() - + if let controller = SignupEmailViewController.instantiate(from: .signup) { controller.loginFields = loginFields navigationController?.pushViewController(controller, animated: true) } } - + func errorDismissed() { loginFields.username = "" navigationController?.popToRootViewController(animated: true) } - + private func cleanupAfterSocialErrors() { dismiss(animated: true) {} } - + /// Displays the self-hosted login form. /// @objc func loginToSelfHostedSite() { @@ -522,10 +518,10 @@ extension LoginViewController: LoginSocialErrorViewControllerDelegate { presentSelfHostedView() return } - + presentUnifiedSiteAddressView() } - + /// Navigates to the unified site address login flow. /// func presentUnifiedSiteAddressView() { @@ -551,5 +547,5 @@ extension LoginViewController: LoginSocialErrorViewControllerDelegate { navigationController?.pushViewController(vc, animated: true) } - + } diff --git a/WordPressAuthenticator/Signin/LoginWPComViewController.swift b/WordPressAuthenticator/Signin/LoginWPComViewController.swift index c7a8a7fce..b8bf4d6bc 100644 --- a/WordPressAuthenticator/Signin/LoginWPComViewController.swift +++ b/WordPressAuthenticator/Signin/LoginWPComViewController.swift @@ -26,10 +26,8 @@ class LoginWPComViewController: LoginViewController, NUXKeyboardResponder { } } - // MARK: - Lifecycle Methods - override func viewDidLoad() { super.viewDidLoad() @@ -50,7 +48,6 @@ class LoginWPComViewController: LoginViewController, NUXKeyboardResponder { configureViewForEditingIfNeeded() } - override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) @@ -61,11 +58,10 @@ class LoginWPComViewController: LoginViewController, NUXKeyboardResponder { WordPressAuthenticator.track(.loginPasswordFormViewed) } - override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) unregisterForKeyboardEvents() - + if isMovingFromParent { // There was a bug that was causing iOS's update password prompt to come up // when this VC was being dismissed pressing the "< Back" button. The following @@ -78,7 +74,6 @@ class LoginWPComViewController: LoginViewController, NUXKeyboardResponder { } } - // MARK: Setup and Configuration /// Sets up a 1Password button if 1Password is available. @@ -113,7 +108,6 @@ class LoginWPComViewController: LoginViewController, NUXKeyboardResponder { navigationItem.hidesBackButton = loading } - /// Configure the view for an editing state. Should only be called from viewWillAppear /// as this method skips animating any change in height. /// @@ -153,11 +147,11 @@ class LoginWPComViewController: LoginViewController, NUXKeyboardResponder { guard let service = loginFields.meta.socialService else { return NSLocalizedString("Enter the password for your WordPress.com account.", comment: "Instructional text shown when requesting the user's password for login.") } - + if service == SocialServiceName.google { return NSLocalizedString("To proceed with this Google account, please first log in with your WordPress.com password. This will only be asked once.", comment: "") } - + return NSLocalizedString("Please enter the password for your WordPress.com account to log in with your Apple ID.", comment: "") }() @@ -175,7 +169,6 @@ class LoginWPComViewController: LoginViewController, NUXKeyboardResponder { forgotPasswordButton?.titleLabel?.numberOfLines = 0 } - // MARK: - Instance Methods /// Validates what is entered in the various form fields and, if valid, @@ -226,7 +219,7 @@ class LoginWPComViewController: LoginViewController, NUXKeyboardResponder { let allowUsernameChange = (loginFields.meta.socialService == nil) WordPressAuthenticator.fetchOnePasswordCredentials(self, sourceView: sender, loginFields: loginFields, allowUsernameChange: allowUsernameChange) { [weak self] (loginFields) in - + self?.emailLabel?.text = loginFields.username self?.passwordField?.text = loginFields.password self?.validateForm() @@ -263,7 +256,6 @@ class LoginWPComViewController: LoginViewController, NUXKeyboardResponder { keyboardWillHide(notification) } - // MARK: Keyboard Events @objc func signinFormVerticalOffset() -> CGFloat { diff --git a/WordPressAuthenticator/Signup/SignupEmailViewController.swift b/WordPressAuthenticator/Signup/SignupEmailViewController.swift index be69e52a4..7e2623d92 100644 --- a/WordPressAuthenticator/Signup/SignupEmailViewController.swift +++ b/WordPressAuthenticator/Signup/SignupEmailViewController.swift @@ -2,7 +2,6 @@ import UIKit import WordPressShared import WordPressKit - class SignupEmailViewController: LoginViewController, NUXKeyboardResponder { // MARK: - NUXKeyboardResponder Properties @@ -121,7 +120,7 @@ class SignupEmailViewController: LoginViewController, NUXKeyboardResponder { return } - checkEmailAvailability() { available in + checkEmailAvailability { available in if available { self.loginFields.username = self.loginFields.emailAddress self.loginFields.meta.emailMagicLinkSource = .signup @@ -137,7 +136,7 @@ class SignupEmailViewController: LoginViewController, NUXKeyboardResponder { // MARK: - Email Availability - private func checkEmailAvailability(completion:@escaping (Bool) -> ()) { + private func checkEmailAvailability(completion:@escaping (Bool) -> Void) { let remote = AccountServiceRemoteREST( wordPressComRestApi: WordPressComRestApi(baseUrlString: WordPressAuthenticator.shared.configuration.wpcomAPIBaseURL)) @@ -169,9 +168,9 @@ class SignupEmailViewController: LoginViewController, NUXKeyboardResponder { completion(false) return } - + DDLogError("Error checking email availability: \(error.localizedDescription)") - + switch error { case AccountServiceRemoteError.emailAddressInvalid: self.displayError(message: error.localizedDescription) @@ -197,7 +196,7 @@ class SignupEmailViewController: LoginViewController, NUXKeyboardResponder { self?.didRequestSignupLink() self?.configureSubmitButton(animating: false) - }, failure: { [weak self] (error: Error) in + }, failure: { [weak self] (_: Error) in DDLogError("Request for signup link email failed.") WordPressAuthenticator.track(.signupMagicLinkFailed) self?.displayError(message: ErrorMessage.magicLinkRequestFail.description()) diff --git a/WordPressAuthenticator/Signup/SignupGoogleViewController.swift b/WordPressAuthenticator/Signup/SignupGoogleViewController.swift index f3b94dfa1..1a64ec6dd 100644 --- a/WordPressAuthenticator/Signup/SignupGoogleViewController.swift +++ b/WordPressAuthenticator/Signup/SignupGoogleViewController.swift @@ -1,4 +1,3 @@ - /// View controller that handles the google signup flow /// class SignupGoogleViewController: LoginViewController { @@ -61,12 +60,12 @@ extension SignupGoogleViewController: GoogleAuthenticatorSignupDelegate { self.loginFields = loginFields showSignupEpilogue(for: credentials) } - + func googleLoggedInInstead(credentials: AuthenticatorCredentials, loginFields: LoginFields) { self.loginFields = loginFields showLoginEpilogue(for: credentials) } - + func googleSignupFailed(error: Error, loginFields: LoginFields) { self.loginFields = loginFields titleLabel?.textColor = WPStyleGuide.errorRed() diff --git a/WordPressAuthenticator/Signup/SignupNavigationController.swift b/WordPressAuthenticator/Signup/SignupNavigationController.swift index 3907dcea1..2bdab164f 100644 --- a/WordPressAuthenticator/Signup/SignupNavigationController.swift +++ b/WordPressAuthenticator/Signup/SignupNavigationController.swift @@ -1,7 +1,6 @@ import UIKit import WordPressUI - class SignupNavigationController: RotationAwareNavigationViewController { override func viewDidLoad() { super.viewDidLoad() diff --git a/WordPressAuthenticator/UI/CircularImageView.swift b/WordPressAuthenticator/UI/CircularImageView.swift index 325ba037a..584c43f14 100644 --- a/WordPressAuthenticator/UI/CircularImageView.swift +++ b/WordPressAuthenticator/UI/CircularImageView.swift @@ -1,6 +1,5 @@ import Foundation - /// UIImageView with a circular shape. /// class CircularImageView: UIImageView { diff --git a/WordPressAuthenticator/UI/LoginTextField.swift b/WordPressAuthenticator/UI/LoginTextField.swift index 83fec889a..b19859470 100644 --- a/WordPressAuthenticator/UI/LoginTextField.swift +++ b/WordPressAuthenticator/UI/LoginTextField.swift @@ -38,7 +38,7 @@ open class LoginTextField: WPWalkthroughTextField { return } - let attributes: [NSAttributedString.Key : Any] = [ + let attributes: [NSAttributedString.Key: Any] = [ .foregroundColor: WordPressAuthenticator.shared.style.placeholderColor, .font: font ] diff --git a/WordPressAuthenticator/UI/SearchTableViewCell.swift b/WordPressAuthenticator/UI/SearchTableViewCell.swift index 2d48bd542..37b05e5dc 100644 --- a/WordPressAuthenticator/UI/SearchTableViewCell.swift +++ b/WordPressAuthenticator/UI/SearchTableViewCell.swift @@ -1,14 +1,12 @@ import UIKit import WordPressShared - // MARK: - SearchTableViewCellDelegate // public protocol SearchTableViewCellDelegate: class { func startSearch(for: String) } - // MARK: - SearchTableViewCell // open class SearchTableViewCell: UITableViewCell { @@ -36,7 +34,6 @@ open class SearchTableViewCell: UITableViewCell { } } - public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } @@ -53,7 +50,6 @@ open class SearchTableViewCell: UITableViewCell { } } - // MARK: - Settings // private extension SearchTableViewCell { @@ -62,7 +58,6 @@ private extension SearchTableViewCell { } } - // MARK: - UITextFieldDelegate // extension SearchTableViewCell: UITextFieldDelegate { diff --git a/WordPressAuthenticator/UI/SiteInfoHeaderView.swift b/WordPressAuthenticator/UI/SiteInfoHeaderView.swift index a6741f8d4..220c10495 100644 --- a/WordPressAuthenticator/UI/SiteInfoHeaderView.swift +++ b/WordPressAuthenticator/UI/SiteInfoHeaderView.swift @@ -1,7 +1,6 @@ import UIKit import WordPressShared - // MARK: - SiteInfoHeaderView // class SiteInfoHeaderView: UIView { @@ -62,7 +61,6 @@ class SiteInfoHeaderView: UIView { } } - /// Downloads the Blavatar Image at the specified URL. /// func downloadBlavatar(at path: String) { @@ -73,7 +71,6 @@ class SiteInfoHeaderView: UIView { } } - // MARK: - Overriden Methods override func awakeFromNib() { @@ -81,7 +78,6 @@ class SiteInfoHeaderView: UIView { refreshLabelStyles() } - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) @@ -93,7 +89,6 @@ class SiteInfoHeaderView: UIView { } } - // MARK: - Private // private extension SiteInfoHeaderView { diff --git a/WordPressAuthenticator/Unified Auth/GoogleAuthenticator.swift b/WordPressAuthenticator/Unified Auth/GoogleAuthenticator.swift index 0ff8dcb8c..80ee30605 100644 --- a/WordPressAuthenticator/Unified Auth/GoogleAuthenticator.swift +++ b/WordPressAuthenticator/Unified Auth/GoogleAuthenticator.swift @@ -3,7 +3,6 @@ import GoogleSignIn import WordPressKit import SVProgressHUD - /// Contains delegate methods for Google authentication unified auth flow. /// Both Login and Signup are handled via this delegate. /// @@ -16,7 +15,7 @@ protocol GoogleAuthenticatorDelegate: class { // Google account login was successful, but a WP password is required. func googleExistingUserNeedsConnection(loginFields: LoginFields) - + // Google account login failed. func googleLoginFailed(errorTitle: String, errorDescription: String, loginFields: LoginFields, unknownUser: Bool) @@ -57,7 +56,7 @@ protocol GoogleAuthenticatorLoginDelegate: class { // Google account login was successful, but a WP password is required. func googleExistingUserNeedsConnection(loginFields: LoginFields) - + // Google account login failed. func googleLoginFailed(errorTitle: String, errorDescription: String, loginFields: LoginFields) } @@ -91,11 +90,11 @@ class GoogleAuthenticator: NSObject { private var loginFields = LoginFields() private let authConfig = WordPressAuthenticator.shared.configuration private var authType: GoogleAuthType = .login - + private var tracker: AuthenticatorAnalyticsTracker { AuthenticatorAnalyticsTracker.shared } - + private lazy var loginFacade: LoginFacade = { let facade = LoginFacade(dotcomClientID: authConfig.wpcomClientId, dotcomSecret: authConfig.wpcomSecret, @@ -104,7 +103,7 @@ class GoogleAuthenticator: NSObject { return facade }() - private lazy var authenticationDelegate: WordPressAuthenticatorDelegate = { + private lazy weak var authenticationDelegate: WordPressAuthenticatorDelegate = { guard let delegate = WordPressAuthenticator.shared.delegate else { fatalError() } @@ -112,7 +111,7 @@ class GoogleAuthenticator: NSObject { }() // MARK: - Start Authentication - + /// Public method to initiate the Google auth process. /// - Parameters: /// - viewController: The UIViewController that Google is being presented from. @@ -127,7 +126,7 @@ class GoogleAuthenticator: NSObject { self.authType = authType requestAuthorization(from: viewController) } - + /// Public method to create a WP account with a Google account. /// - Parameters: /// - loginFields: LoginFields from the calling view controller. @@ -174,7 +173,7 @@ private extension GoogleAuthenticator { // This has no effect since we don't use Google UI, but presentingViewController is required, so here we are. googleInstance.presentingViewController = viewController - + googleInstance.delegate = self googleInstance.clientID = authConfig.googleLoginClientId googleInstance.serverClientID = authConfig.googleLoginServerClientId @@ -188,7 +187,7 @@ private extension GoogleAuthenticator { trackProperties["source"] = "google" WordPressAuthenticator.track(event, properties: trackProperties) } - + enum LocalizedText { static let googleConnected = NSLocalizedString("Connected But…", comment: "Title shown when a user logs in with Google but no matching WordPress.com account is found") static let googleConnectedError = NSLocalizedString("The Google account \"%@\" doesn't match any account on WordPress.com", comment: "Description shown when a user logs in with Google but no matching WordPress.com account is found") @@ -207,10 +206,10 @@ extension GoogleAuthenticator: GIDSignInDelegate { guard let user = user, let token = user.authentication.idToken, let email = user.profile.email else { - + // The Google SignIn may have been cancelled. let failure = error?.localizedDescription ?? "Unknown error" - + tracker.track(failure: failure, ifTrackingNotEnabled: { let properties = ["error": failure] @@ -225,10 +224,10 @@ extension GoogleAuthenticator: GIDSignInDelegate { // Notify the delegates so the Google Auth view can be dismissed. signupDelegate?.googleSignupCancelled() delegate?.googleAuthCancelled() - + return } - + // Save account information to pass back to delegate later. loginFields.emailAddress = email loginFields.username = email @@ -252,7 +251,7 @@ extension GoogleAuthenticator: GIDSignInDelegate { SVProgressHUD.show() loginFacade.loginToWordPressDotCom(withSocialIDToken: token, service: SocialServiceName.google.rawValue) } - + } // MARK: - LoginFacadeDelegate @@ -263,15 +262,15 @@ extension GoogleAuthenticator: LoginFacadeDelegate { func finishedLogin(withGoogleIDToken googleIDToken: String, authToken: String) { SVProgressHUD.dismiss() GIDSignIn.sharedInstance().disconnect() - + // This stat is part of a funnel that provides critical information. Please // consult with your lead before removing this event. track(.signedIn) - + if tracker.shouldUseLegacyTracker() { track(.loginSocialSuccess) } - + let wpcom = WordPressComCredentials(authToken: authToken, isJetpackLogin: loginFields.meta.jetpackLogin, multifactor: false, @@ -293,7 +292,7 @@ extension GoogleAuthenticator: LoginFacadeDelegate { if tracker.shouldUseLegacyTracker() { track(.loginSocial2faNeeded) } - + loginDelegate?.googleNeedsMultifactorCode(loginFields: loginFields) delegate?.googleNeedsMultifactorCode(loginFields: loginFields) } @@ -305,11 +304,11 @@ extension GoogleAuthenticator: LoginFacadeDelegate { loginFields.username = email loginFields.emailAddress = email - + if tracker.shouldUseLegacyTracker() { track(.loginSocialAccountsNeedConnecting) } - + loginDelegate?.googleExistingUserNeedsConnection(loginFields: loginFields) delegate?.googleExistingUserNeedsConnection(loginFields: loginFields) } @@ -326,7 +325,7 @@ extension GoogleAuthenticator: LoginFacadeDelegate { if unknownUser { errorTitle = LocalizedText.googleConnected errorDescription = String(format: LocalizedText.googleConnectedError, loginFields.username) - + if tracker.shouldUseLegacyTracker() { track(.loginSocialErrorUnknownUser) } @@ -338,7 +337,7 @@ extension GoogleAuthenticator: LoginFacadeDelegate { loginDelegate?.googleLoginFailed(errorTitle: errorTitle, errorDescription: errorDescription, loginFields: loginFields) delegate?.googleLoginFailed(errorTitle: errorTitle, errorDescription: errorDescription, loginFields: loginFields, unknownUser: unknownUser) } - + } // MARK: - Sign Up Methods @@ -381,16 +380,16 @@ private extension GoogleAuthenticator { self?.signupFailed(error: error) }) } - + func accountCreated(credentials: AuthenticatorCredentials) { // This stat is part of a funnel that provides critical information. Before // making ANY modification to this stat please refer to: p4qSXL-35X-p2 track(.createdAccount) - + // This stat is part of a funnel that provides critical information. Please // consult with your lead before removing this event. track(.signedIn) - + tracker.track(step: .success, ifTrackingNotEnabled: { track(.signupSocialSuccess) }) @@ -398,14 +397,14 @@ private extension GoogleAuthenticator { signupDelegate?.googleFinishedSignup(credentials: credentials, loginFields: loginFields) delegate?.googleFinishedSignup(credentials: credentials, loginFields: loginFields) } - + func logInInstead(credentials: AuthenticatorCredentials) { tracker.set(flow: .loginWithGoogle) - + // This stat is part of a funnel that provides critical information. Please // consult with your lead before removing this event. track(.signedIn) - + tracker.track(step: .start) { track(.signupSocialToLogin) track(.loginSocialSuccess) @@ -414,7 +413,7 @@ private extension GoogleAuthenticator { signupDelegate?.googleLoggedInInstead(credentials: credentials, loginFields: loginFields) delegate?.googleLoggedInInstead(credentials: credentials, loginFields: loginFields) } - + func signupFailed(error: Error) { tracker.track(failure: error.localizedDescription, ifTrackingNotEnabled: { track(.signupSocialFailure, properties: ["error": error.localizedDescription]) diff --git a/WordPressAuthenticator/Unified Auth/StoredCredentialsAuthenticator.swift b/WordPressAuthenticator/Unified Auth/StoredCredentialsAuthenticator.swift index aeb2fe5ce..c6603f850 100644 --- a/WordPressAuthenticator/Unified Auth/StoredCredentialsAuthenticator.swift +++ b/WordPressAuthenticator/Unified Auth/StoredCredentialsAuthenticator.swift @@ -11,14 +11,14 @@ import SVProgressHUD class StoredCredentialsAuthenticator: NSObject { // MARK: - Delegates - + private var authenticationDelegate: WordPressAuthenticatorDelegate { guard let delegate = WordPressAuthenticator.shared.delegate else { fatalError() } return delegate } - + // MARK: - Configuration private var authConfig: WordPressAuthenticatorConfiguration { @@ -26,7 +26,7 @@ class StoredCredentialsAuthenticator: NSObject { } // MARK: - Login Support - + private lazy var loginFacade: LoginFacade = { let facade = LoginFacade(dotcomClientID: authConfig.wpcomClientId, dotcomSecret: authConfig.wpcomSecret, @@ -34,49 +34,49 @@ class StoredCredentialsAuthenticator: NSObject { facade.delegate = self return facade }() - + // MARK: - Cancellation - + private let onCancel: (() -> Void)? - + // MARK: - UI - + private let picker = StoredCredentialsPicker() private var navigationController: UINavigationController? - + // MARK: - Tracking Support private var tracker: AuthenticatorAnalyticsTracker { AuthenticatorAnalyticsTracker.shared } - + // MARK: - Login Fields - + private var loginFields: LoginFields? - + // MARK: - Initialization - + init(onCancel: (() -> Void)? = nil) { self.onCancel = onCancel } - + // MARK: - Picker - + /// Shows the UI for picking stored credentials for the user to log into their account. /// func showPicker(from navigationController: UINavigationController) { self.navigationController = navigationController - + guard let window = navigationController.view.window else { DDLogError("Can't obtain window for navigation controller") return } - + picker.show(in: window) { [weak self] result in guard let self = self else { return } - + switch result { case .success(let authorization): self.pickerSuccess(authorization) @@ -85,7 +85,7 @@ class StoredCredentialsAuthenticator: NSObject { } } } - + /// The selection of credentials and subsequent authorization by the OS succeeded. This method processes the credentials /// and proceeds with the login operation. /// @@ -96,7 +96,7 @@ class StoredCredentialsAuthenticator: NSObject { tracker.track(step: .start) tracker.set(flow: .loginWithiCloudKeychain) SVProgressHUD.show() - + switch authorization.credential { case _ as ASAuthorizationAppleIDCredential: // No-op for now, but we can decide to implement AppleID login through this authenticator @@ -112,7 +112,7 @@ class StoredCredentialsAuthenticator: NSObject { break } } - + /// The selection of credentials or the subsequent authorization by the OS failed. This method processes the failure. /// /// - Parameters: @@ -143,15 +143,15 @@ extension StoredCredentialsAuthenticator: LoginFacadeDelegate { func displayRemoteError(_ error: Error) { tracker.track(failure: error.localizedDescription) SVProgressHUD.dismiss() - + guard authConfig.enableUnifiedAuth else { presentLoginEmailView(error: error) return } - + presentGetStartedView(error: error) } - + func needsMultifactorCode() { SVProgressHUD.dismiss() presentTwoFactorAuthenticationView() @@ -164,7 +164,7 @@ extension StoredCredentialsAuthenticator: LoginFacadeDelegate { multifactor: requiredMultifactorCode, siteURL: "") let credentials = AuthenticatorCredentials(wpcom: wpcom) - + authenticationDelegate.sync(credentials: credentials) { [weak self] in SVProgressHUD.dismiss() self?.presentLoginEpilogue(credentials: credentials) @@ -181,10 +181,10 @@ extension StoredCredentialsAuthenticator { DDLogError("No navigation controller to present the login epilogue from") return } - + authenticationDelegate.presentLoginEpilogue(in: navigationController, for: credentials, onDismiss: {}) } - + /// Presents the login email screen, displaying the specified error. This is useful /// for example for iCloud Keychain in the case where there's an error logging the user /// in with the stored credentials for whatever reason. @@ -194,7 +194,7 @@ extension StoredCredentialsAuthenticator { DDLogError("Failed to navigate to LoginEmailVC from LoginPrologueVC") return } - + if let loginFields = loginFields { toVC.loginFields = loginFields } @@ -212,7 +212,7 @@ extension StoredCredentialsAuthenticator { DDLogError("Failed to navigate to GetStartedViewController") return } - + if let loginFields = loginFields { toVC.loginFields = loginFields } @@ -220,12 +220,12 @@ extension StoredCredentialsAuthenticator { toVC.errorMessage = error.localizedDescription navigationController?.pushViewController(toVC, animated: true) } - + private func presentTwoFactorAuthenticationView() { guard let loginFields = loginFields else { return } - + guard let vc = TwoFAViewController.instantiate(from: .twoFA) else { DDLogError("Failed to navigate from LoginViewController to TwoFAViewController") return diff --git a/WordPressAuthenticator/Unified Auth/StoredCredentialsPicker.swift b/WordPressAuthenticator/Unified Auth/StoredCredentialsPicker.swift index a0c40d575..2d3c544f3 100644 --- a/WordPressAuthenticator/Unified Auth/StoredCredentialsPicker.swift +++ b/WordPressAuthenticator/Unified Auth/StoredCredentialsPicker.swift @@ -9,26 +9,26 @@ import AuthenticationServices /// @available(iOS 13, *) class StoredCredentialsPicker: NSObject { - - typealias CompletionClosure = (Result) -> () - + + typealias CompletionClosure = (Result) -> Void + /// The closure that will be executed once the credentials are picked and returned by the OS, /// or once there's an Error. /// private var onComplete: CompletionClosure! - + /// The window where the quick authentication flow will be shown. /// private var window: UIWindow! func show(in window: UIWindow, onComplete: @escaping CompletionClosure) { - + self.onComplete = onComplete self.window = window - + let requests = [ASAuthorizationPasswordProvider().createRequest()] let controller = ASAuthorizationController(authorizationRequests: requests) - + controller.delegate = self controller.presentationContextProvider = self controller.performRequests() diff --git a/WordPressAuthenticator/Unified Auth/View Related/2FA/TwoFAViewController.swift b/WordPressAuthenticator/Unified Auth/View Related/2FA/TwoFAViewController.swift index 8242e6710..e4310ebaf 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/2FA/TwoFAViewController.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/2FA/TwoFAViewController.swift @@ -7,14 +7,14 @@ import SVProgressHUD final class TwoFAViewController: LoginViewController { // MARK: - Properties - + @IBOutlet private weak var tableView: UITableView! @IBOutlet var bottomContentConstraint: NSLayoutConstraint? private weak var codeField: UITextField? - + private var rows = [Row]() private var errorMessage: String? - private var pasteboardChangeCountBeforeBackground: Int? = nil + private var pasteboardChangeCountBeforeBackground: Int? private var shouldChangeVoiceOverFocus: Bool = false override var sourceTag: WordPressSupportSourceTag { @@ -27,49 +27,49 @@ final class TwoFAViewController: LoginViewController { var verticalCenterConstraint: NSLayoutConstraint? // MARK: - View - + override func viewDidLoad() { super.viewDidLoad() removeGoogleWaitingView() - + navigationItem.title = WordPressAuthenticator.shared.displayStrings.logInTitle styleNavigationBar(forUnified: true) defaultTableViewMargin = tableViewLeadingConstraint?.constant ?? 0 setTableViewMargins(forWidth: view.frame.width) - + localizePrimaryButton() registerTableViewCells() loadRows() configureForAccessibility() } - + override func viewDidAppear(_ animated: Bool) { - + super.viewDidAppear(animated) - + if isMovingToParent { tracker.track(step: .twoFactorAuthentication) } else { tracker.set(step: .twoFactorAuthentication) } - + registerForKeyboardEvents(keyboardWillShowAction: #selector(handleKeyboardWillShow(_:)), keyboardWillHideAction: #selector(handleKeyboardWillHide(_:))) - + configureSubmitButton(animating: false) configureViewForEditingIfNeeded() - + let nc = NotificationCenter.default nc.addObserver(self, selector: #selector(applicationBecameInactive), name: UIApplication.willResignActiveNotification, object: nil) nc.addObserver(self, selector: #selector(applicationBecameActive), name: UIApplication.didBecomeActiveNotification, object: nil) } - + override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) unregisterForKeyboardEvents() - + // Multifactor codes are time sensitive, so clear the stored code if the // user dismisses the view. They'll need to reenter it upon return. loginFields.multifactorCode = "" @@ -86,7 +86,7 @@ final class TwoFAViewController: LoginViewController { view.backgroundColor = unifiedBackgroundColor } - + override var preferredStatusBarStyle: UIStatusBarStyle { return WordPressAuthenticator.shared.unifiedStyle?.statusBarStyle ?? WordPressAuthenticator.shared.style.statusBarStyle @@ -111,7 +111,7 @@ final class TwoFAViewController: LoginViewController { super.configureViewLoading(loading) codeField?.isEnabled = !loading } - + override func displayRemoteError(_ error: Error) { displayError(message: "") @@ -130,20 +130,20 @@ final class TwoFAViewController: LoginViewController { displayError(error as NSError, sourceTag: sourceTag) } } - + override func displayError(message: String, moveVoiceOverFocus: Bool = false) { if errorMessage != message { if !message.isEmpty { tracker.track(failure: message) } - + errorMessage = message shouldChangeVoiceOverFocus = moveVoiceOverFocus loadRows() tableView.reloadData() } } - + } // MARK: - Validation and Login @@ -168,7 +168,7 @@ private extension TwoFAViewController { loginFacade.requestOneTimeCode(with: loginFields) } } - + // MARK: - Login /// Validates what is entered in the various form fields and, if valid, @@ -188,15 +188,15 @@ private extension TwoFAViewController { let (authType, nonce) = nonceInfo.authTypeAndNonce(for: code) loginFacade.loginToWordPressDotCom(withUser: loginFields.nonceUserID, authType: authType, twoStepCode: code, twoStepNonce: nonce) } - + func finishedLogin(withNonceAuthToken authToken: String) { let wpcom = WordPressComCredentials(authToken: authToken, isJetpackLogin: isJetpackLogin, multifactor: true, siteURL: loginFields.siteAddress) let credentials = AuthenticatorCredentials(wpcom: wpcom) syncWPComAndPresentEpilogue(credentials: credentials) } - + // MARK: - Code Validation - + enum CodeValidation { case invalid(nonNumbers: Bool) case valid(String) @@ -216,17 +216,17 @@ private extension TwoFAViewController { if isOnlyNumbers { return .invalid(nonNumbers: false) } - + return .invalid(nonNumbers: true) } - + // MARK: - Text Field Handling - + func handleTextFieldDidChange(_ sender: UITextField) { loginFields.multifactorCode = codeField?.nonNilTrimmedText() ?? "" configureSubmitButton(animating: false) } - + } // MARK: - UITextFieldDelegate @@ -239,7 +239,7 @@ extension TwoFAViewController: UITextFieldDelegate { guard let fieldText = textField.text as NSString? else { return true } - + let resultString = fieldText.replacingCharacters(in: range, with: replacementString) switch isValidCode(code: resultString) { @@ -259,7 +259,7 @@ extension TwoFAViewController: UITextFieldDelegate { return false } - + func textFieldShouldReturn(_ textField: UITextField) -> Bool { validateForm() return true @@ -287,7 +287,7 @@ extension TwoFAViewController: UITableViewDataSource { // MARK: - Keyboard Notifications extension TwoFAViewController: NUXKeyboardResponder { - + @objc func handleKeyboardWillShow(_ notification: Foundation.Notification) { keyboardWillShow(notification) } @@ -305,12 +305,12 @@ private extension TwoFAViewController { @objc func applicationBecameInactive() { pasteboardChangeCountBeforeBackground = UIPasteboard.general.changeCount } - + @objc func applicationBecameActive() { guard let codeField = codeField else { return } - + let emptyField = codeField.text?.isEmpty ?? true guard emptyField, pasteboardChangeCountBeforeBackground != UIPasteboard.general.changeCount else { @@ -318,7 +318,7 @@ private extension TwoFAViewController { } if #available(iOS 14.0, *) { - UIPasteboard.general.detectAuthenticatorCode() { [weak self] result in + UIPasteboard.general.detectAuthenticatorCode { [weak self] result in switch result { case .success(let authenticatorCode): self?.handle(code: authenticatorCode, textField: codeField) @@ -358,7 +358,7 @@ private extension TwoFAViewController { TextFieldTableViewCell.reuseIdentifier: TextFieldTableViewCell.loadNib(), TextLinkButtonTableViewCell.reuseIdentifier: TextLinkButtonTableViewCell.loadNib() ] - + for (reuseIdentifier, nib) in cells { tableView.register(nib, forCellReuseIdentifier: reuseIdentifier) } @@ -392,7 +392,7 @@ private extension TwoFAViewController { DDLogError("Error: Unidentified tableViewCell type found.") } } - + /// Configure the instruction cell. /// func configureInstructionLabel(_ cell: TextLabelTableViewCell) { @@ -423,7 +423,7 @@ private extension TwoFAViewController { cell.actionHandler = { [weak self] in guard let self = self else { return } - + self.tracker.track(click: .sendCodeWithText) self.requestCode() } @@ -460,7 +460,7 @@ private extension TwoFAViewController { UIAccessibility.post(notification: .screenChanged, argument: codeField) } - + /// Rows listed in the order they were created. /// enum Row { diff --git a/WordPressAuthenticator/Unified Auth/View Related/Get Started/GetStartedViewController.swift b/WordPressAuthenticator/Unified Auth/View Related/Get Started/GetStartedViewController.swift index 04edfd5d4..115898be6 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/Get Started/GetStartedViewController.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/Get Started/GetStartedViewController.swift @@ -5,7 +5,7 @@ import WordPressKit class GetStartedViewController: LoginViewController { // MARK: - Properties - + @IBOutlet private weak var tableView: UITableView! @IBOutlet private weak var leadingDividerLine: UIView! @IBOutlet private weak var leadingDividerLineWidth: NSLayoutConstraint! @@ -17,10 +17,10 @@ class GetStartedViewController: LoginViewController { // This is to contain the password selected by password auto-fill. // When it is populated, login is attempted. @IBOutlet private weak var hiddenPasswordField: UITextField? - + // This is public so it can be set from StoredCredentialsAuthenticator. var errorMessage: String? - + private var rows = [Row]() private var buttonViewController: NUXButtonViewController? private let configuration = WordPressAuthenticator.shared.configuration @@ -30,25 +30,25 @@ class GetStartedViewController: LoginViewController { private let continueButton: NUXButton = { let button = NUXButton() button.isPrimary = true - + let title = WordPressAuthenticator.shared.displayStrings.continueButtonTitle button.setTitle(title, for: .normal) button.setTitle(title, for: .highlighted) - + return button }() - + override open var sourceTag: WordPressSupportSourceTag { get { return .loginEmail } } - + // MARK: - View - + override func viewDidLoad() { super.viewDidLoad() - + configureNavBar() setupTable() registerTableViewCells() @@ -61,52 +61,52 @@ class GetStartedViewController: LoginViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) configureSubmitButton(animating: false) - + if errorMessage != nil { shouldChangeVoiceOverFocus = true } } - + override open func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - + tracker.set(flow: .wpCom) - + if isMovingToParent { tracker.track(step: .start) } else { tracker.set(step: .start) } - + errorMessage = nil hiddenPasswordField?.text = nil hiddenPasswordField?.isAccessibilityElement = false } // MARK: - Overrides - + override func styleBackground() { guard let unifiedBackgroundColor = WordPressAuthenticator.shared.unifiedStyle?.viewControllerBackgroundColor else { super.styleBackground() return } - + view.backgroundColor = unifiedBackgroundColor } - + override var preferredStatusBarStyle: UIStatusBarStyle { return WordPressAuthenticator.shared.unifiedStyle?.statusBarStyle ?? WordPressAuthenticator.shared.style.statusBarStyle } - + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { super.prepare(for: segue, sender: sender) - + if let vc = segue.destination as? NUXButtonViewController { buttonViewController = vc } } - + override func configureViewLoading(_ loading: Bool) { configureContinueButton(animating: loading) navigationItem.hidesBackButton = loading @@ -121,18 +121,18 @@ class GetStartedViewController: LoginViewController { // MARK: - UITableViewDataSource extension GetStartedViewController: UITableViewDataSource { - + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return rows.count } - + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let row = rows[indexPath.row] let cell = tableView.dequeueReusableCell(withIdentifier: row.reuseIdentifier, for: indexPath) configure(cell, for: row, at: indexPath) return cell } - + } // MARK: - Private methods @@ -140,12 +140,12 @@ extension GetStartedViewController: UITableViewDataSource { private extension GetStartedViewController { // MARK: - Configuration - + func configureNavBar() { navigationItem.title = WordPressAuthenticator.shared.displayStrings.getStartedTitle styleNavigationBar(forUnified: true) } - + func setupTable() { defaultTableViewMargin = tableViewLeadingConstraint?.constant ?? 0 setTableViewMargins(forWidth: view.frame.width) @@ -173,22 +173,22 @@ private extension GetStartedViewController { dividerLabel.textColor = color dividerLabel.text = NSLocalizedString("Or", comment: "Divider on initial auth view separating auth options.").localizedUppercase } - + // MARK: - Continue Button Action - + @IBAction func handleSubmitButtonTapped(_ sender: UIButton) { tracker.track(click: .submit) validateForm() } - + // MARK: - Hidden Password Field Action - + @IBAction func handlePasswordFieldDidChange(_ sender: UITextField) { attemptAutofillLogin() } - + // MARK: - Table Management - + /// Registers all of the available TableViewCells. /// func registerTableViewCells() { @@ -198,12 +198,12 @@ private extension GetStartedViewController { TextWithLinkTableViewCell.reuseIdentifier: TextWithLinkTableViewCell.loadNib(), SpacerTableViewCell.reuseIdentifier: SpacerTableViewCell.loadNib() ] - + for (reuseIdentifier, nib) in cells { tableView.register(nib, forCellReuseIdentifier: reuseIdentifier) } } - + /// Describes how the tableView rows should be rendered. /// func loadRows() { @@ -219,7 +219,7 @@ private extension GetStartedViewController { rows.append(.errorMessage) } } - + /// Configure cells. /// func configure(_ cell: UITableViewCell, for row: Row, at indexPath: IndexPath) { @@ -238,13 +238,13 @@ private extension GetStartedViewController { DDLogError("Error: Unidentified tableViewCell type found.") } } - + /// Configure the instruction cell. /// func configureInstructionLabel(_ cell: TextLabelTableViewCell) { cell.configureLabel(text: WordPressAuthenticator.shared.displayStrings.getStartedInstructions) } - + /// Configure the email cell. /// func configureEmailField(_ cell: TextFieldTableViewCell) { @@ -253,12 +253,12 @@ private extension GetStartedViewController { text: loginFields.username) cell.textField.delegate = self emailField = cell.textField - + cell.onChangeSelectionHandler = { [weak self] textfield in self?.loginFields.username = textfield.nonNilTrimmedText() self?.configureContinueButton(animating: false) } - + cell.onePasswordHandler = { [weak self] in guard let self = self, let sourceView = self.emailField else { @@ -272,18 +272,18 @@ private extension GetStartedViewController { self?.validateFormAndLogin() } } - + if UIAccessibility.isVoiceOverRunning { // Quiet repetitive elements in VoiceOver. emailField?.placeholder = nil } } - + /// Configure the link cell. /// func configureTextWithLink(_ cell: TextWithLinkTableViewCell) { cell.configureButton(markedText: WordPressAuthenticator.shared.displayStrings.loginTermsOfService) - + cell.actionHandler = { [weak self] in self?.termsTapped() } @@ -293,12 +293,12 @@ private extension GetStartedViewController { /// func configureErrorLabel(_ cell: TextLabelTableViewCell) { cell.configureLabel(text: errorMessage, style: .error) - + if shouldChangeVoiceOverFocus { UIAccessibility.post(notification: .layoutChanged, argument: cell) } } - + /// Rows listed in the order they were created. /// enum Row { @@ -307,7 +307,7 @@ private extension GetStartedViewController { case tos case spacer case errorMessage - + var reuseIdentifier: String { switch self { case .instructions, .errorMessage: @@ -321,18 +321,18 @@ private extension GetStartedViewController { } } } - + enum Constants { static let footerFrame = CGRect(x: 0, y: 0, width: 0, height: 44) static let footerButtonInsets = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16) } - + } // MARK: - Validation private extension GetStartedViewController { - + /// Configures appearance of the submit button. /// func configureContinueButton(animating: Bool) { @@ -351,7 +351,7 @@ private extension GetStartedViewController { /// social signin does not require form validation. /// func validateForm() { - + loginFields.meta.socialService = nil displayError(message: "") @@ -379,7 +379,7 @@ private extension GetStartedViewController { self.handleLoginError(error) }) } - + /// Show the Password entry view. /// func showPasswordView() { @@ -387,10 +387,10 @@ private extension GetStartedViewController { DDLogError("Failed to navigate to PasswordViewController from GetStartedViewController") return } - + vc.loginFields = loginFields vc.trackAsPasswordChallenge = false - + navigationController?.pushViewController(vc, animated: true) } @@ -411,7 +411,7 @@ private extension GetStartedViewController { self.displayError(error as NSError, sourceTag: self.sourceTag) } } - + // MARK: - Send email /// Makes the call to request a magic signup link be emailed to the user. @@ -430,11 +430,11 @@ private extension GetStartedViewController { }, failure: { [weak self] (error: Error) in DDLogError("Request for signup link email failed.") - + guard let self = self else { return } - + self.tracker.track(failure: error.localizedDescription) self.displayError(error as NSError, sourceTag: self.sourceTag) self.configureSubmitButton(animating: false) @@ -452,7 +452,7 @@ private extension GetStartedViewController { navigationController?.pushViewController(vc, animated: true) } - + /// Makes the call to request a magic authentication link be emailed to the user. /// func requestAuthenticationLink() { @@ -476,7 +476,7 @@ private extension GetStartedViewController { guard let self = self else { return } - + self.tracker.track(failure: error.localizedDescription) self.displayError(error as NSError, sourceTag: self.sourceTag) @@ -496,7 +496,7 @@ private extension GetStartedViewController { vc.loginFields.restrictToWPCom = true navigationController?.pushViewController(vc, animated: true) } - + /// Build the alert message when the email address is invalid. /// func buildInvalidEmailAlert() -> UIAlertController { @@ -520,27 +520,27 @@ private extension GetStartedViewController { return alert } - + /// When password autofill has entered a password on this screen, attempt to login immediately /// func attemptAutofillLogin() { // Even though there was no explicit submit action by the user, we'll interpret // the credentials selection as such. tracker.track(click: .submit) - + loginFields.password = hiddenPasswordField?.text ?? "" loginFields.meta.socialService = nil displayError(message: "") validateFormAndLogin() } - + /// Configures loginFields to log into wordpress.com and navigates to the selfhosted username/password form. /// Displays the specified error message when the new view controller appears. /// func showSelfHostedWithError(_ error: Error) { loginFields.siteAddress = "https://wordpress.com" errorToPresent = error - + tracker.track(failure: error.localizedDescription) guard let vc = SiteCredentialsViewController.instantiate(from: .siteAddress) else { @@ -554,51 +554,51 @@ private extension GetStartedViewController { navigationController?.pushViewController(vc, animated: true) } - + } // MARK: - Social Button Management private extension GetStartedViewController { - + func configureSocialButtons() { guard let buttonViewController = buttonViewController else { return } - + buttonViewController.hideShadowView() - + if WordPressAuthenticator.shared.configuration.enableSignInWithApple { if #available(iOS 13.0, *) { buttonViewController.setupTopButtonFor(socialService: .apple, onTap: appleTapped) } } - + buttonViewController.setupButtomButtonFor(socialService: .google, onTap: googleTapped) - + let termsButton = WPStyleGuide.signupTermsButton() buttonViewController.stackView?.addArrangedSubview(termsButton) termsButton.addTarget(self, action: #selector(termsTapped), for: .touchUpInside) } - + @objc func appleTapped() { tracker.track(click: .loginWithApple) - + AppleAuthenticator.sharedInstance.delegate = self AppleAuthenticator.sharedInstance.showFrom(viewController: self) } - + @objc func googleTapped() { tracker.track(click: .loginWithGoogle) - + guard let toVC = GoogleAuthViewController.instantiate(from: .googleAuth) else { DDLogError("Failed to navigate to GoogleAuthViewController from GetStartedViewController") return } - + navigationController?.pushViewController(toVC, animated: true) } - + @objc func termsTapped() { tracker.track(click: .termsOfService) @@ -606,7 +606,7 @@ private extension GetStartedViewController { DDLogError("GetStartedViewController: wpcomTermsOfServiceURL unavailable.") return } - + let safariViewController = SFSafariViewController(url: url) safariViewController.modalPresentationStyle = .pageSheet safariViewController.delegate = self @@ -629,35 +629,35 @@ extension GetStartedViewController: SFSafariViewControllerDelegate { // MARK: - AppleAuthenticatorDelegate extension GetStartedViewController: AppleAuthenticatorDelegate { - + func showWPComLogin(loginFields: LoginFields) { self.loginFields = loginFields showPasswordView() } - + func showApple2FA(loginFields: LoginFields) { self.loginFields = loginFields signInAppleAccount() } - + func authFailedWithError(message: String) { displayErrorAlert(message, sourceTag: .loginApple) tracker.set(flow: .wpCom) } - + } // MARK: - LoginFacadeDelegate extension GetStartedViewController { - + // Used by SIWA when logging with with a passwordless, 2FA account. // func needsMultifactorCode(forUserID userID: Int, andNonceInfo nonceInfo: SocialLogin2FANonceInfo) { configureViewLoading(false) socialNeedsMultifactorCode(forUserID: userID, andNonceInfo: nonceInfo) } - + } // MARK: - UITextFieldDelegate @@ -667,7 +667,7 @@ extension GetStartedViewController: UITextFieldDelegate { func textFieldDidBeginEditing(_ textField: UITextField) { tracker.track(click: .selectEmailField) } - + func textFieldShouldReturn(_ textField: UITextField) -> Bool { if canSubmit() { validateForm() diff --git a/WordPressAuthenticator/Unified Auth/View Related/Google/GoogleAuthViewController.swift b/WordPressAuthenticator/Unified Auth/View Related/Google/GoogleAuthViewController.swift index 5b7b567f6..3f73c1320 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/Google/GoogleAuthViewController.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/Google/GoogleAuthViewController.swift @@ -34,7 +34,7 @@ class GoogleAuthViewController: LoginViewController { AuthenticatorAnalyticsTracker.shared.track(click: .dismiss) } } - + // MARK: - Overrides /// Style individual ViewController backgrounds, for now. diff --git a/WordPressAuthenticator/Unified Auth/View Related/Google/GoogleSignupConfirmationViewController.swift b/WordPressAuthenticator/Unified Auth/View Related/Google/GoogleSignupConfirmationViewController.swift index 37a6c47c0..83e57aea4 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/Google/GoogleSignupConfirmationViewController.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/Google/GoogleSignupConfirmationViewController.swift @@ -3,7 +3,7 @@ import UIKit class GoogleSignupConfirmationViewController: LoginViewController { // MARK: - Properties - + @IBOutlet private weak var tableView: UITableView! private var rows = [Row]() private var errorMessage: String? @@ -14,14 +14,14 @@ class GoogleSignupConfirmationViewController: LoginViewController { return .wpComAuthGoogleSignupConfirmation } } - + // MARK: - View override func viewDidLoad() { super.viewDidLoad() - + removeGoogleWaitingView() - + navigationItem.title = WordPressAuthenticator.shared.displayStrings.signUpTitle styleNavigationBar(forUnified: true) @@ -33,12 +33,12 @@ class GoogleSignupConfirmationViewController: LoginViewController { loadRows() configureForAccessibility() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) tracker.set(flow: .signupWithGoogle) - + if isBeingPresentedInAnyWay { tracker.track(step: .start) } else { @@ -79,7 +79,7 @@ class GoogleSignupConfirmationViewController: LoginViewController { tableView.reloadData() } } - + } // MARK: - UITableViewDataSource @@ -106,20 +106,20 @@ extension GoogleSignupConfirmationViewController: UITableViewDataSource { // MARK: - Private Extension private extension GoogleSignupConfirmationViewController { - + // MARK: - Button Handling @IBAction func handleSubmit() { tracker.track(click: .submit) tracker.track(click: .createAccount) - + configureSubmitButton(animating: true) GoogleAuthenticator.sharedInstance.delegate = self GoogleAuthenticator.sharedInstance.createGoogleAccount(loginFields: loginFields) } // MARK: - Table Management - + /// Registers all of the available TableViewCells. /// func registerTableViewCells() { @@ -190,7 +190,7 @@ private extension GoogleSignupConfirmationViewController { UIAccessibility.post(notification: .screenChanged, argument: tableView) } - + // MARK: - Private Constants /// Rows listed in the order they were created. @@ -215,9 +215,9 @@ private extension GoogleSignupConfirmationViewController { // MARK: - GoogleAuthenticatorDelegate extension GoogleSignupConfirmationViewController: GoogleAuthenticatorDelegate { - + // MARK: - Signup - + func googleFinishedSignup(credentials: AuthenticatorCredentials, loginFields: LoginFields) { self.loginFields = loginFields showSignupEpilogue(for: credentials) @@ -227,27 +227,27 @@ extension GoogleSignupConfirmationViewController: GoogleAuthenticatorDelegate { self.loginFields = loginFields showLoginEpilogue(for: credentials) } - + func googleSignupFailed(error: Error, loginFields: LoginFields) { configureSubmitButton(animating: false) self.loginFields = loginFields displayError(message: error.localizedDescription, moveVoiceOverFocus: true) } - + // MARK: - Login func googleFinishedLogin(credentials: AuthenticatorCredentials, loginFields: LoginFields) { // Here for protocol compliance. } - + func googleNeedsMultifactorCode(loginFields: LoginFields) { // Here for protocol compliance. } - + func googleExistingUserNeedsConnection(loginFields: LoginFields) { // Here for protocol compliance. } - + func googleLoginFailed(errorTitle: String, errorDescription: String, loginFields: LoginFields, unknownUser: Bool) { // Here for protocol compliance. } diff --git a/WordPressAuthenticator/Unified Auth/View Related/Login/LoginMagicLinkViewController.swift b/WordPressAuthenticator/Unified Auth/View Related/Login/LoginMagicLinkViewController.swift index 6762d3f71..84a74d9d4 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/Login/LoginMagicLinkViewController.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/Login/LoginMagicLinkViewController.swift @@ -1,6 +1,5 @@ import UIKit - /// Unified LoginMagicLinkViewController: login to .com with a magic link /// final class LoginMagicLinkViewController: LoginViewController { @@ -11,7 +10,7 @@ final class LoginMagicLinkViewController: LoginViewController { private var rows = [Row]() private var errorMessage: String? private var shouldChangeVoiceOverFocus: Bool = false - + override var sourceTag: WordPressSupportSourceTag { get { return .loginMagicLink @@ -22,7 +21,7 @@ final class LoginMagicLinkViewController: LoginViewController { @IBAction func handleContinueButtonTapped(_ sender: NUXButton) { tracker.track(click: .openEmailClient) tracker.track(step: .emailOpened) - + let linkMailPresenter = LinkMailPresenter(emailAddress: loginFields.username) let appSelector = AppSelector(sourceView: sender) linkMailPresenter.presentEmailClients(on: self, appSelector: appSelector) @@ -43,19 +42,19 @@ final class LoginMagicLinkViewController: LoginViewController { registerTableViewCells() loadRows() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) tracker.set(flow: .loginWithMagicLink) - + if isMovingToParent { tracker.track(step: .magicLinkRequested) } else { tracker.set(step: .magicLinkRequested) } } - + override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(true) } @@ -87,7 +86,6 @@ final class LoginMagicLinkViewController: LoginViewController { } } - // MARK: - UITableViewDataSource extension LoginMagicLinkViewController: UITableViewDataSource { /// Returns the number of rows in a section. @@ -107,7 +105,6 @@ extension LoginMagicLinkViewController: UITableViewDataSource { } } - // MARK: - Private Methods private extension LoginMagicLinkViewController { /// Registers all of the available TableViewCells. diff --git a/WordPressAuthenticator/Unified Auth/View Related/Password/PasswordViewController.swift b/WordPressAuthenticator/Unified Auth/View Related/Password/PasswordViewController.swift index 4a6fa119b..d9a0ae767 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/Password/PasswordViewController.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/Password/PasswordViewController.swift @@ -4,18 +4,18 @@ import WordPressKit /// PasswordViewController: view to enter WP account password. /// class PasswordViewController: LoginViewController { - + // MARK: - Properties - + @IBOutlet private weak var tableView: UITableView! @IBOutlet var bottomContentConstraint: NSLayoutConstraint? - + private weak var passwordField: UITextField? private var rows = [Row]() private var errorMessage: String? private var shouldChangeVoiceOverFocus: Bool = false private var loginLinkCell: TextLinkButtonTableViewCell? - + /// Depending on where we're coming from, this screen needs to track a password challenge /// (if logging on with a Social account) or not (if logging in through WP.com). /// @@ -26,26 +26,26 @@ class PasswordViewController: LoginViewController { loginFields.password = "" } } - + override var sourceTag: WordPressSupportSourceTag { get { return .loginWPComPassword } } - + // Required for `NUXKeyboardResponder` but unused here. var verticalCenterConstraint: NSLayoutConstraint? - + // MARK: - View - + override func viewDidLoad() { super.viewDidLoad() removeGoogleWaitingView() - + navigationItem.title = WordPressAuthenticator.shared.displayStrings.logInTitle styleNavigationBar(forUnified: true) - + defaultTableViewMargin = tableViewLeadingConstraint?.constant ?? 0 setTableViewMargins(forWidth: view.frame.width) @@ -54,18 +54,18 @@ class PasswordViewController: LoginViewController { loadRows() configureForAccessibility() } - + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - + loginFields.meta.userIsDotCom = true configureSubmitButton(animating: false) loginLinkCell?.enableButton(true) } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - + if trackAsPasswordChallenge { if isMovingToParent { tracker.track(step: .passwordChallenge) @@ -74,41 +74,41 @@ class PasswordViewController: LoginViewController { } } else { tracker.set(flow: .loginWithPassword) - + if isMovingToParent { tracker.track(step: .start) } else { tracker.set(step: .start) } } - + registerForKeyboardEvents(keyboardWillShowAction: #selector(handleKeyboardWillShow(_:)), keyboardWillHideAction: #selector(handleKeyboardWillHide(_:))) configureViewForEditingIfNeeded() } - + override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) unregisterForKeyboardEvents() } - + // MARK: - Overrides - + override func styleBackground() { guard let unifiedBackgroundColor = WordPressAuthenticator.shared.unifiedStyle?.viewControllerBackgroundColor else { super.styleBackground() return } - + view.backgroundColor = unifiedBackgroundColor } - + override var preferredStatusBarStyle: UIStatusBarStyle { return WordPressAuthenticator.shared.unifiedStyle?.statusBarStyle ?? WordPressAuthenticator.shared.style.statusBarStyle } - + override func configureViewLoading(_ loading: Bool) { super.configureViewLoading(loading) passwordField?.isEnabled = !loading @@ -116,14 +116,14 @@ class PasswordViewController: LoginViewController { override func displayRemoteError(_ error: Error) { configureViewLoading(false) - + let nsError = error as NSError let errorCode = nsError.code let errorDomain = nsError.domain - + if errorDomain == WordPressComOAuthClient.WordPressComOAuthErrorDomain, errorCode == WordPressComOAuthError.invalidRequest.rawValue { - + // The only difference between an incorrect password error and exceeded login limit error // is the actual error string. So check for "password" in the error string, and show the custom // error message. Otherwise, show the actual response error. @@ -146,7 +146,7 @@ class PasswordViewController: LoginViewController { if !message.isEmpty { tracker.track(failure: message) } - + configureViewLoading(false) if errorMessage != message { @@ -178,12 +178,12 @@ class PasswordViewController: LoginViewController { // MARK: - Validation and Continue private extension PasswordViewController { - + // MARK: - Button Actions - + @IBAction func handleContinueButtonTapped(_ sender: NUXButton) { tracker.track(click: .submit) - + configureViewLoading(true) validateForm() } @@ -209,24 +209,24 @@ extension PasswordViewController: UITextFieldDelegate { // MARK: - UITableViewDataSource extension PasswordViewController: UITableViewDataSource { - + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return rows.count } - + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let row = rows[indexPath.row] let cell = tableView.dequeueReusableCell(withIdentifier: row.reuseIdentifier, for: indexPath) configure(cell, for: row, at: indexPath) return cell } - + } // MARK: - Keyboard Notifications extension PasswordViewController: NUXKeyboardResponder { - + @objc func handleKeyboardWillShow(_ notification: Foundation.Notification) { keyboardWillShow(notification) } @@ -240,7 +240,7 @@ extension PasswordViewController: NUXKeyboardResponder { // MARK: - Table Management private extension PasswordViewController { - + /// Registers all of the available TableViewCells. /// func registerTableViewCells() { @@ -250,32 +250,32 @@ private extension PasswordViewController { TextFieldTableViewCell.reuseIdentifier: TextFieldTableViewCell.loadNib(), TextLinkButtonTableViewCell.reuseIdentifier: TextLinkButtonTableViewCell.loadNib() ] - + for (reuseIdentifier, nib) in cells { tableView.register(nib, forCellReuseIdentifier: reuseIdentifier) } } - + /// Describes how the tableView rows should be rendered. /// func loadRows() { rows = [.gravatarEmail] - + // Instructions only for social accounts if loginFields.meta.socialService != nil { rows.append(.instructions) } - + rows.append(.password) - + if let errorText = errorMessage, !errorText.isEmpty { rows.append(.errorMessage) } - + rows.append(.forgotPassword) rows.append(.sendMagicLink) } - + /// Configure cells. /// func configure(_ cell: UITableViewCell, for row: Row, at indexPath: IndexPath) { @@ -301,7 +301,7 @@ private extension PasswordViewController { /// func configureGravatarEmail(_ cell: GravatarEmailTableViewCell) { cell.configure(withEmail: loginFields.username) - + cell.onChangeSelectionHandler = { [weak self] textfield in // The email can only be changed via a password manager. // In this case, don't update username for social accounts. @@ -312,21 +312,21 @@ private extension PasswordViewController { self?.loginFields.username = textfield.nonNilTrimmedText() self?.loginFields.emailAddress = textfield.nonNilTrimmedText() } - + self?.configureSubmitButton(animating: false) } - + cell.onePasswordHandler = { [weak self] sourceView in guard let self = self else { return } - + self.view.endEditing(true) - + // Don't update username for social accounts. // This prevents inadvertent account linking. let allowUsernameChange = (self.loginFields.meta.socialService == nil) - + WordPressAuthenticator.fetchOnePasswordCredentials(self, sourceView: sourceView, loginFields: self.loginFields, allowUsernameChange: allowUsernameChange) { [weak self] (loginFields) in cell.updateEmailAddress(loginFields.username) self?.passwordField?.text = loginFields.password @@ -334,7 +334,7 @@ private extension PasswordViewController { } } } - + /// Configure the instruction cell. /// func configureInstructionLabel(_ cell: TextLabelTableViewCell) { @@ -349,7 +349,7 @@ private extension PasswordViewController { cell.configureLabel(text: instructions) } - + /// Configure the password textfield cell. /// func configurePasswordTextField(_ cell: TextFieldTableViewCell) { @@ -359,20 +359,20 @@ private extension PasswordViewController { // Save a reference to the first textField so it can becomeFirstResponder. passwordField = cell.textField cell.textField.delegate = self - + cell.onChangeSelectionHandler = { [weak self] textfield in self?.loginFields.password = textfield.nonNilTrimmedText() self?.configureSubmitButton(animating: false) } - + SigninEditingState.signinEditingStateActive = true - + if UIAccessibility.isVoiceOverRunning { // Quiet repetitive VoiceOver elements. passwordField?.placeholder = nil } } - + /// Configure the forgot password link cell. /// func configureForgotPasswordButton(_ cell: TextLinkButtonTableViewCell) { @@ -383,7 +383,7 @@ private extension PasswordViewController { guard let self = self else { return } - + self.tracker.track(click: .forgottenPassword) // If information is currently processing, ignore button tap. @@ -402,22 +402,22 @@ private extension PasswordViewController { accessibilityTrait: .link, showBorder: true) cell.accessibilityIdentifier = "Get Login Link Button" - + // Save reference to the login link cell so it can be enabled/disabled. loginLinkCell = cell - + cell.actionHandler = { [weak self] in guard let self = self else { return } - + cell.enableButton(false) - + self.tracker.track(click: .requestMagicLink) self.requestAuthenticationLink() } } - + /// Configure the error message cell. /// func configureErrorLabel(_ cell: TextLabelTableViewCell) { @@ -427,7 +427,7 @@ private extension PasswordViewController { UIAccessibility.post(notification: .layoutChanged, argument: cell) } } - + /// Configure the view for an editing state. /// func configureViewForEditingIfNeeded() { @@ -437,7 +437,7 @@ private extension PasswordViewController { passwordField?.becomeFirstResponder() } } - + /// Sets up accessibility elements in the order which they should be read aloud /// and chooses which element to focus on at the beginning. /// @@ -476,7 +476,7 @@ private extension PasswordViewController { guard let self = self else { return } - + self.tracker.track(failure: error.localizedDescription) self.displayError(error as NSError, sourceTag: self.sourceTag) @@ -520,7 +520,7 @@ private extension PasswordViewController { return alert } - + /// Rows listed in the order they were created. /// enum Row { @@ -530,7 +530,7 @@ private extension PasswordViewController { case forgotPassword case sendMagicLink case errorMessage - + var reuseIdentifier: String { switch self { case .gravatarEmail: diff --git a/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/GravatarEmailTableViewCell.swift b/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/GravatarEmailTableViewCell.swift index d1fa8bacd..92c568d4a 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/GravatarEmailTableViewCell.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/GravatarEmailTableViewCell.swift @@ -1,6 +1,5 @@ import UIKit - /// GravatarEmailTableViewCell: Gravatar image + Email address in a UITableViewCell. /// class GravatarEmailTableViewCell: UITableViewCell { @@ -16,15 +15,15 @@ class GravatarEmailTableViewCell: UITableViewCell { // When iOS12 support is removed, the emailStackView can be removed as it only facilitates 1Password. @IBOutlet private weak var emailLabel: UITextField? @IBOutlet private weak var emailStackView: UIStackView? - + private let gridiconSize = CGSize(width: 48, height: 48) - + /// Public properties /// public static let reuseIdentifier = "GravatarEmailTableViewCell" public var onePasswordHandler: ((_ sourceView: UITextField) -> Void)? public var onChangeSelectionHandler: ((_ sender: UITextField) -> Void)? - + /// Public Methods /// public func configure(withEmail email: String?, andPlaceholder placeholderImage: UIImage? = nil) { @@ -34,9 +33,9 @@ class GravatarEmailTableViewCell: UITableViewCell { emailLabel?.text = email setupOnePasswordButtonIfNeeded() - + let gridicon = UIImage.gridicon(.userCircle, size: gridiconSize) - + guard let email = email, email.isValidEmail() else { gravatarImageView?.image = gridicon @@ -55,13 +54,13 @@ class GravatarEmailTableViewCell: UITableViewCell { // MARK: - Password Manager Handling private extension GravatarEmailTableViewCell { - + // MARK: - 1Password /// Sets up a 1Password button if 1Password is available and user is on iOS 12. /// func setupOnePasswordButtonIfNeeded() { - + if #available(iOS 13, *) { // no-op, we rely on the key icon in the keyboard to initiate a password manager. } else { @@ -69,13 +68,13 @@ private extension GravatarEmailTableViewCell { !(emailStackView.arrangedSubviews.last is UIButton) else { return } - + WPStyleGuide.configureOnePasswordButtonForStackView(emailStackView, target: self, selector: #selector(onePasswordTapped(_:))) } } - + @objc func onePasswordTapped(_ sender: UIButton) { guard let emailTextField = emailLabel else { return @@ -83,9 +82,9 @@ private extension GravatarEmailTableViewCell { onePasswordHandler?(emailTextField) } - + // MARK: - All Password Managers - + /// Call the handler when the text field changes. /// /// - Note: we have to manually add an action to the textfield diff --git a/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextFieldTableViewCell.swift b/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextFieldTableViewCell.swift index b6e8e78d4..2055ab6bd 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextFieldTableViewCell.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextFieldTableViewCell.swift @@ -1,6 +1,5 @@ import UIKit - /// TextFieldTableViewCell: a textfield with a custom border line in a UITableViewCell. /// final class TextFieldTableViewCell: UITableViewCell { @@ -60,7 +59,6 @@ final class TextFieldTableViewCell: UITableViewCell { } } - // MARK: - Private methods private extension TextFieldTableViewCell { @@ -145,7 +143,6 @@ private extension TextFieldTableViewCell { } } - // MARK: - Secure Text Entry /// Methods ported from WPWalkthroughTextField.h/.m /// @@ -209,7 +206,6 @@ private extension TextFieldTableViewCell { } } - // MARK: - Constants extension TextFieldTableViewCell { @@ -231,7 +227,7 @@ extension TextFieldTableViewCell { static let passwordShown = NSLocalizedString("Shown", comment: "Accessibility value if login page's password field is displaying the password.") static let showPassword = NSLocalizedString("Show password", - comment:"Accessibility label for the 'Show password' button in the login page's password field.") + comment: "Accessibility label for the 'Show password' button in the login page's password field.") static let siteAddress = NSLocalizedString("Site address", comment: "Accessibility label of the site address field shown when adding a self-hosted site.") static let username = NSLocalizedString("Username", diff --git a/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextFieldTableViewCell.xib b/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextFieldTableViewCell.xib index fda3c096d..c0ada44fb 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextFieldTableViewCell.xib +++ b/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextFieldTableViewCell.xib @@ -1,10 +1,11 @@ - + - + + @@ -17,7 +18,7 @@ - + @@ -33,7 +34,7 @@ - + @@ -58,4 +59,9 @@ + + + + + diff --git a/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextLabelTableViewCell.swift b/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextLabelTableViewCell.swift index 69f4127c9..01732b91a 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextLabelTableViewCell.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextLabelTableViewCell.swift @@ -1,6 +1,5 @@ import UIKit - /// TextLabelTableViewCell: a text label in a UITableViewCell. /// public final class TextLabelTableViewCell: UITableViewCell { diff --git a/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextLinkButtonTableViewCell.swift b/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextLinkButtonTableViewCell.swift index 407076091..5cafac527 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextLinkButtonTableViewCell.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextLinkButtonTableViewCell.swift @@ -1,10 +1,9 @@ import UIKit - /// TextLinkButtonTableViewCell: a plain button made to look like a text link. /// class TextLinkButtonTableViewCell: UITableViewCell { - + /// Private properties /// @IBOutlet private weak var button: UIButton! @@ -13,32 +12,32 @@ class TextLinkButtonTableViewCell: UITableViewCell { @IBAction private func textLinkButtonTapped(_ sender: UIButton) { actionHandler?() } - + /// Public properties /// public static let reuseIdentifier = "TextLinkButtonTableViewCell" - + public var actionHandler: (() -> Void)? - + override func awakeFromNib() { super.awakeFromNib() button.titleLabel?.adjustsFontForContentSizeCategory = true styleBorder() } - + public func configureButton(text: String?, accessibilityTrait: UIAccessibilityTraits = .button, showBorder: Bool = false) { button.setTitle(text, for: .normal) - + let buttonTitleColor = WordPressAuthenticator.shared.unifiedStyle?.textButtonColor ?? WordPressAuthenticator.shared.style.textButtonColor let buttonHighlightColor = WordPressAuthenticator.shared.unifiedStyle?.textButtonHighlightColor ?? WordPressAuthenticator.shared.style.textButtonHighlightColor button.setTitleColor(buttonTitleColor, for: .normal) button.setTitleColor(buttonHighlightColor, for: .highlighted) button.accessibilityTraits = accessibilityTrait - + borderView.isHidden = !showBorder } - + /// Toggle button enabled / disabled /// public func enableButton(_ isEnabled: Bool) { @@ -47,7 +46,6 @@ class TextLinkButtonTableViewCell: UITableViewCell { } - // MARK: - Private methods private extension TextLinkButtonTableViewCell { diff --git a/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextWithLinkTableViewCell.swift b/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextWithLinkTableViewCell.swift index 5c27c15c5..9028f54fa 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextWithLinkTableViewCell.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/Reusable Views/TextWithLinkTableViewCell.swift @@ -1,6 +1,5 @@ import UIKit - /// TextWithLinkTableViewCell: a button with the title regular text and an underlined link. /// class TextWithLinkTableViewCell: UITableViewCell { @@ -21,7 +20,7 @@ class TextWithLinkTableViewCell: UITableViewCell { super.awakeFromNib() button.titleLabel?.adjustsFontForContentSizeCategory = true } - + /// Creates an attributed string from the provided marked text and assigns it to the button title. /// /// - Parameters: @@ -36,7 +35,7 @@ class TextWithLinkTableViewCell: UITableViewCell { let attributedString = text.underlined(color: textColor, underlineColor: linkColor) let highlightAttributedString = text.underlined(color: textColor, underlineColor: linkHighlightColor) - + button.setAttributedTitle(attributedString, for: .normal) button.setAttributedTitle(highlightAttributedString, for: .highlighted) button.accessibilityTraits = accessibilityTrait diff --git a/WordPressAuthenticator/Unified Auth/View Related/Sign up/SignupMagicLinkViewController.swift b/WordPressAuthenticator/Unified Auth/View Related/Sign up/SignupMagicLinkViewController.swift index 69428199d..e8cf9938e 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/Sign up/SignupMagicLinkViewController.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/Sign up/SignupMagicLinkViewController.swift @@ -1,6 +1,5 @@ import UIKit - /// SignupMagicLinkViewController: step two in the signup flow. /// This VC prompts the user to open their email app to look for the magic link we sent. /// @@ -23,14 +22,14 @@ final class SignupMagicLinkViewController: LoginViewController { @IBAction func handleContinueButtonTapped(_ sender: NUXButton) { tracker.track(click: .openEmailClient) tracker.track(step: .emailOpened) - + let linkMailPresenter = LinkMailPresenter(emailAddress: loginFields.username) let appSelector = AppSelector(sourceView: sender) linkMailPresenter.presentEmailClients(on: self, appSelector: appSelector) } // MARK: - View lifecycle - + override func viewDidLoad() { super.viewDidLoad() @@ -47,10 +46,10 @@ final class SignupMagicLinkViewController: LoginViewController { registerTableViewCells() loadRows() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - + if isMovingToParent { tracker.track(step: .magicLinkRequested) } else { @@ -93,7 +92,6 @@ final class SignupMagicLinkViewController: LoginViewController { } } - // MARK: - UITableViewDataSource extension SignupMagicLinkViewController: UITableViewDataSource { /// Returns the number of rows in a section. @@ -113,7 +111,6 @@ extension SignupMagicLinkViewController: UITableViewDataSource { } } - // MARK: - Private Methods private extension SignupMagicLinkViewController { /// Registers all of the available TableViewCells. @@ -169,7 +166,7 @@ private extension SignupMagicLinkViewController { func configureCheckSpamLabel(_ cell: TextLabelTableViewCell) { cell.configureLabel(text: WordPressAuthenticator.shared.displayStrings.checkSpamInstructions, style: .body) } - + /// Configure the "Check spam" cell. /// func configureoopsLabel(_ cell: TextLabelTableViewCell) { diff --git a/WordPressAuthenticator/Unified Auth/View Related/Sign up/UnifiedSignupViewController.swift b/WordPressAuthenticator/Unified Auth/View Related/Sign up/UnifiedSignupViewController.swift index 1e3ec0b94..4df9f156d 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/Sign up/UnifiedSignupViewController.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/Sign up/UnifiedSignupViewController.swift @@ -33,12 +33,12 @@ class UnifiedSignupViewController: LoginViewController { registerTableViewCells() loadRows() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - + tracker.set(flow: .signup) - + if isMovingToParent { tracker.track(step: .start) } else { @@ -83,7 +83,6 @@ class UnifiedSignupViewController: LoginViewController { } } - // MARK: - UITableViewDataSource extension UnifiedSignupViewController: UITableViewDataSource { @@ -104,11 +103,9 @@ extension UnifiedSignupViewController: UITableViewDataSource { } } - // MARK: - UITableViewDelegate conformance extension UnifiedSignupViewController: UITableViewDelegate { } - // MARK: - Private methods private extension UnifiedSignupViewController { @@ -208,8 +205,7 @@ private extension UnifiedSignupViewController { } - -// Mark: - Instance Methods +// MARK: - Instance Methods /// Implementation methods imported from SignupEmailViewController. /// extension UnifiedSignupViewController { @@ -230,11 +226,11 @@ extension UnifiedSignupViewController { }, failure: { [weak self] (error: Error) in DDLogError("Request for signup link email failed.") - + guard let self = self else { return } - + self.tracker.track(failure: error.localizedDescription) self.displayError(message: ErrorMessage.magicLinkRequestFail.description()) self.configureSubmitButton(animating: false) diff --git a/WordPressAuthenticator/Unified Auth/View Related/Site Address/SiteAddressViewController.swift b/WordPressAuthenticator/Unified Auth/View Related/Site Address/SiteAddressViewController.swift index da3be0974..821a5d241 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/Site Address/SiteAddressViewController.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/Site Address/SiteAddressViewController.swift @@ -2,7 +2,6 @@ import UIKit import WordPressUI import WordPressKit - /// SiteAddressViewController: log in by Site Address. /// final class SiteAddressViewController: LoginViewController { @@ -23,15 +22,14 @@ final class SiteAddressViewController: LoginViewController { // MARK: - Actions @IBAction func handleContinueButtonTapped(_ sender: NUXButton) { tracker.track(click: .submit) - + validateForm() } - // MARK: - View lifecycle override func viewDidLoad() { super.viewDidLoad() - + removeGoogleWaitingView() configureNavBar() setupTable() @@ -41,7 +39,7 @@ final class SiteAddressViewController: LoginViewController { configureSubmitButton(animating: false) configureForAccessibility() } - + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) @@ -51,21 +49,20 @@ final class SiteAddressViewController: LoginViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - + tracker.set(flow: .loginWithSiteAddress) - + if isMovingToParent { tracker.track(step: .start) } else { tracker.set(step: .start) } - + registerForKeyboardEvents(keyboardWillShowAction: #selector(handleKeyboardWillShow(_:)), keyboardWillHideAction: #selector(handleKeyboardWillHide(_:))) configureViewForEditingIfNeeded() } - // MARK: - Overrides /// Style individual ViewController backgrounds, for now. @@ -90,7 +87,7 @@ final class SiteAddressViewController: LoginViewController { override func configureSubmitButton(animating: Bool) { // This matches the string in WPiOS UI tests. submitButton?.accessibilityIdentifier = "Site Address Next Button" - + submitButton?.showActivityIndicator(animating) submitButton?.isEnabled = ( @@ -154,11 +151,11 @@ final class SiteAddressViewController: LoginViewController { /// Reload the tableview and show errors, if any. /// override func displayError(message: String, moveVoiceOverFocus: Bool = false) { - if errorMessage != message { + if errorMessage != message { if !message.isEmpty { tracker.track(failure: message) } - + errorMessage = message shouldChangeVoiceOverFocus = moveVoiceOverFocus loadRows() @@ -167,7 +164,6 @@ final class SiteAddressViewController: LoginViewController { } } - // MARK: - UITableViewDataSource extension SiteAddressViewController: UITableViewDataSource { /// Returns the number of rows in a section. @@ -187,7 +183,6 @@ extension SiteAddressViewController: UITableViewDataSource { } } - // MARK: - UITableViewDelegate conformance extension SiteAddressViewController: UITableViewDelegate { /// After the site address textfield cell is done displaying, remove the textfield reference. @@ -203,7 +198,6 @@ extension SiteAddressViewController: UITableViewDelegate { } } - // MARK: - Keyboard Notifications extension SiteAddressViewController: NUXKeyboardResponder { @objc func handleKeyboardWillShow(_ notification: Foundation.Notification) { @@ -215,7 +209,6 @@ extension SiteAddressViewController: NUXKeyboardResponder { } } - // MARK: - TextField Delegate conformance extension SiteAddressViewController: UITextFieldDelegate { @@ -231,27 +224,26 @@ extension SiteAddressViewController: UITextFieldDelegate { } } - // MARK: - Private methods private extension SiteAddressViewController { // MARK: - Configuration - + func configureNavBar() { navigationItem.title = WordPressAuthenticator.shared.displayStrings.logInTitle styleNavigationBar(forUnified: true) - + // Nav bar could be hidden from the host app, so reshow it. navigationController?.setNavigationBarHidden(false, animated: false) } - + func setupTable() { defaultTableViewMargin = tableViewLeadingConstraint?.constant ?? 0 setTableViewMargins(forWidth: view.frame.width) } - + // MARK: - Table Management - + /// Registers all of the available TableViewCells. /// func registerTableViewCells() { @@ -308,7 +300,7 @@ private extension SiteAddressViewController { func configureTextField(_ cell: TextFieldTableViewCell) { cell.configure(withStyle: .url, placeholder: WordPressAuthenticator.shared.displayStrings.siteAddressPlaceholder) - + // Save a reference to the first textField so it can becomeFirstResponder. siteURLField = cell.textField cell.textField.delegate = self @@ -328,7 +320,7 @@ private extension SiteAddressViewController { guard let self = self else { return } - + self.tracker.track(click: .showHelp) let alert = FancyAlertViewController.siteAddressHelpController( @@ -339,7 +331,7 @@ private extension SiteAddressViewController { }, onDismiss: { self.tracker.track(click: .dismiss) - + // Since we're showing an alert on top of this VC, `viewDidAppear` will not be called // once the alert is dismissed (which is where the step would be reset automagically), // so we need to manually reset the step here. @@ -400,7 +392,6 @@ private extension SiteAddressViewController { } } - // MARK: - Instance Methods private extension SiteAddressViewController { @@ -471,6 +462,7 @@ private extension SiteAddressViewController { } func fetchSiteInfo() { + print("🔴 SAVC > fetchSiteInfo") let baseSiteUrl = WordPressAuthenticator.baseSiteURL(string: loginFields.siteAddress) let service = WordPressComBlogService() @@ -486,8 +478,8 @@ private extension SiteAddressViewController { } self.presentNextControllerIfPossible(siteInfo: siteInfo) } - - service.fetchUnauthenticatedSiteInfoForAddress(for: baseSiteUrl, success: successBlock, failure: { [weak self] error in + + service.fetchUnauthenticatedSiteInfoForAddress(for: baseSiteUrl, success: successBlock, failure: { [weak self] _ in self?.configureViewLoading(false) guard let self = self else { return @@ -501,7 +493,7 @@ private extension SiteAddressViewController { showGetStarted() return } - + WordPressAuthenticator.shared.delegate?.shouldPresentUsernamePasswordController(for: siteInfo, onCompletion: { (result) in switch result { case let .error(error): @@ -511,7 +503,7 @@ private extension SiteAddressViewController { self.showSelfHostedUsernamePassword() return } - + self.showWPUsernamePassword() case .presentEmailController: self.showGetStarted() @@ -562,7 +554,7 @@ private extension SiteAddressViewController { navigationController?.pushViewController(vc, animated: true) } - + /// If the site is WordPressDotCom, redirect to WP login. /// func showGetStarted() { @@ -570,14 +562,14 @@ private extension SiteAddressViewController { DDLogError("Failed to navigate from SiteAddressViewController to GetStartedViewController") return } - + vc.loginFields = loginFields vc.dismissBlock = dismissBlock vc.errorToPresent = errorToPresent navigationController?.pushViewController(vc, animated: true) } - + /// Whether the form can be submitted. /// func canSubmit() -> Bool { diff --git a/WordPressAuthenticator/Unified Auth/View Related/Site Address/SiteCredentialsViewController.swift b/WordPressAuthenticator/Unified Auth/View Related/Site Address/SiteCredentialsViewController.swift index 2e08a533f..5810a6fe7 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/Site Address/SiteCredentialsViewController.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/Site Address/SiteCredentialsViewController.swift @@ -1,6 +1,5 @@ import UIKit - /// Part two of the self-hosted sign in flow: username + password. Used by WPiOS and NiOS. /// A valid site address should be acquired before presenting this view controller. /// @@ -36,7 +35,7 @@ final class SiteCredentialsViewController: LoginViewController { // MARK: - Actions @IBAction func handleContinueButtonTapped(_ sender: NUXButton) { tracker.track(click: .submit) - + validateForm() } @@ -67,7 +66,7 @@ final class SiteCredentialsViewController: LoginViewController { } else { tracker.set(step: .usernamePassword) } - + configureSubmitButton(animating: false) registerForKeyboardEvents(keyboardWillShowAction: #selector(handleKeyboardWillShow(_:)), @@ -80,7 +79,6 @@ final class SiteCredentialsViewController: LoginViewController { unregisterForKeyboardEvents() } - // MARK: - Overrides /// Style individual ViewController backgrounds, for now. @@ -93,7 +91,7 @@ final class SiteCredentialsViewController: LoginViewController { view.backgroundColor = unifiedBackgroundColor } - + override var preferredStatusBarStyle: UIStatusBarStyle { return WordPressAuthenticator.shared.unifiedStyle?.statusBarStyle ?? WordPressAuthenticator.shared.style.statusBarStyle } @@ -142,7 +140,7 @@ final class SiteCredentialsViewController: LoginViewController { if !message.isEmpty { tracker.track(failure: message) } - + errorMessage = message shouldChangeVoiceOverFocus = moveVoiceOverFocus loadRows() @@ -154,7 +152,6 @@ final class SiteCredentialsViewController: LoginViewController { func displayLoginMessage(_ message: String) {} } - // MARK: - UITableViewDataSource extension SiteCredentialsViewController: UITableViewDataSource { /// Returns the number of rows in a section. @@ -174,7 +171,6 @@ extension SiteCredentialsViewController: UITableViewDataSource { } } - // MARK: - UITableViewDelegate conformance extension SiteCredentialsViewController: UITableViewDelegate { /// After a textfield cell is done displaying, remove the textfield reference. @@ -192,7 +188,6 @@ extension SiteCredentialsViewController: UITableViewDelegate { } } - // MARK: - Keyboard Notifications extension SiteCredentialsViewController: NUXKeyboardResponder { @objc func handleKeyboardWillShow(_ notification: Foundation.Notification) { @@ -204,7 +199,6 @@ extension SiteCredentialsViewController: NUXKeyboardResponder { } } - // MARK: - TextField Delegate conformance extension SiteCredentialsViewController: UITextFieldDelegate { @@ -223,7 +217,6 @@ extension SiteCredentialsViewController: UITextFieldDelegate { } } - // MARK: - Private Methods private extension SiteCredentialsViewController { @@ -347,7 +340,7 @@ private extension SiteCredentialsViewController { guard let self = self else { return } - + self.tracker.track(click: .forgottenPassword) // If information is currently processing, ignore button tap. @@ -377,7 +370,7 @@ private extension SiteCredentialsViewController { usernameField?.becomeFirstResponder() } } - + // MARK: - Private Constants /// Rows listed in the order they were created. @@ -406,7 +399,6 @@ private extension SiteCredentialsViewController { } } - // MARK: - Instance Methods /// Implementation methods copied from LoginSelfHostedViewController. /// diff --git a/WordPressAuthenticatorTests/Analytics/AnalyticsTrackerTests.swift b/WordPressAuthenticatorTests/Analytics/AnalyticsTrackerTests.swift index b84142ac2..cf1e19fe9 100644 --- a/WordPressAuthenticatorTests/Analytics/AnalyticsTrackerTests.swift +++ b/WordPressAuthenticatorTests/Analytics/AnalyticsTrackerTests.swift @@ -2,34 +2,34 @@ import XCTest @testable import WordPressAuthenticator class AnalyticsTrackerTests: XCTestCase { - + // MARK: - Expectations: Building the properties dictionary - + private func expectedProperties(source: AuthenticatorAnalyticsTracker.Source, flow: AuthenticatorAnalyticsTracker.Flow, step: AuthenticatorAnalyticsTracker.Step) -> [String: String] { - + return [ AuthenticatorAnalyticsTracker.Property.source.rawValue: source.rawValue, AuthenticatorAnalyticsTracker.Property.flow.rawValue: flow.rawValue, AuthenticatorAnalyticsTracker.Property.step.rawValue: step.rawValue ] } - + private func expectedProperties(source: AuthenticatorAnalyticsTracker.Source, flow: AuthenticatorAnalyticsTracker.Flow, step: AuthenticatorAnalyticsTracker.Step, failure: String) -> [String: String] { - + var properties = expectedProperties(source: source, flow: flow, step: step) properties[AuthenticatorAnalyticsTracker.Property.failure.rawValue] = failure - + return properties } - + private func expectedProperties(source: AuthenticatorAnalyticsTracker.Source, flow: AuthenticatorAnalyticsTracker.Flow, step: AuthenticatorAnalyticsTracker.Step, click: AuthenticatorAnalyticsTracker.ClickTarget) -> [String: String] { - + var properties = expectedProperties(source: source, flow: flow, step: step) properties[AuthenticatorAnalyticsTracker.Property.click.rawValue] = click.rawValue - + return properties } - + /// Test that when tracking an event through the AnalyticsTracker, the backing analytics tracker /// receives a matching event. /// @@ -37,28 +37,28 @@ class AnalyticsTrackerTests: XCTestCase { let source = AuthenticatorAnalyticsTracker.Source.reauthentication let flow = AuthenticatorAnalyticsTracker.Flow.loginWithGoogle let step = AuthenticatorAnalyticsTracker.Step.start - + let expectedEventName = AuthenticatorAnalyticsTracker.EventType.step.rawValue let expectedEventProperties = self.expectedProperties(source: source, flow: flow, step: step) let trackingIsOk = expectation(description: "The parameters of the tracking call are as expected") - + let track = { (event: AnalyticsEvent) in if event.name == expectedEventName && event.properties == expectedEventProperties { - + trackingIsOk.fulfill() } } - + let tracker = AuthenticatorAnalyticsTracker(enabled: true, track: track) - + tracker.set(source: source) tracker.set(flow: flow) tracker.track(step: step) - + waitForExpectations(timeout: 0.1) } - + /// Test that tracking a failure maintains the source, flow and step from the previously recorded step. /// /// Ref: pbArwn-I6-p2 @@ -68,30 +68,30 @@ class AnalyticsTrackerTests: XCTestCase { let flow = AuthenticatorAnalyticsTracker.Flow.loginWithGoogle let step = AuthenticatorAnalyticsTracker.Step.start let failure = "some error" - + let expectedEventName = AuthenticatorAnalyticsTracker.EventType.failure.rawValue let expectedEventProperties = self.expectedProperties(source: source, flow: flow, step: step, failure: failure) let trackingIsOk = expectation(description: "The parameters of the tracking call are as expected") - + let track = { (event: AnalyticsEvent) in // We'll ignore the first event and only check the properties from the failure. if event.name == expectedEventName && event.properties == expectedEventProperties { - + trackingIsOk.fulfill() } } let tracker = AuthenticatorAnalyticsTracker(enabled: true, track: track) - + tracker.set(source: source) tracker.set(flow: flow) tracker.track(step: step) tracker.track(failure: failure) - + waitForExpectations(timeout: 0.1) } - + /// Test that tracking a click maintains the source, flow and step from the previously recorded step. /// /// Ref: pbArwn-I6-p2 @@ -101,195 +101,195 @@ class AnalyticsTrackerTests: XCTestCase { let flow = AuthenticatorAnalyticsTracker.Flow.loginWithGoogle let step = AuthenticatorAnalyticsTracker.Step.start let click = AuthenticatorAnalyticsTracker.ClickTarget.dismiss - + let expectedEventName = AuthenticatorAnalyticsTracker.EventType.interaction.rawValue let expectedEventProperties = self.expectedProperties(source: source, flow: flow, step: step, click: click) let trackingIsOk = expectation(description: "The parameters of the tracking call are as expected") - + let track = { (event: AnalyticsEvent) in // We'll ignore the first event and only check the properties from the failure. if event.name == expectedEventName && event.properties == expectedEventProperties { - + trackingIsOk.fulfill() } } - + let tracker = AuthenticatorAnalyticsTracker(enabled: true, track: track) - + tracker.set(source: source) tracker.set(flow: flow) tracker.track(step: step) tracker.track(click: click) - + waitForExpectations(timeout: 0.1) } - + // MARK: - Legacy Tracking Support Tests - + /// Tests legacy tracking for a step /// func testStepLegacyTracking() { let source = AuthenticatorAnalyticsTracker.Source.default let flows: [AuthenticatorAnalyticsTracker.Flow] = [.loginWithApple, .signupWithApple, .loginWithGoogle, .signupWithGoogle, .loginWithSiteAddress] let step = AuthenticatorAnalyticsTracker.Step.start - + let legacyTrackingExecuted = expectation(description: "The legacy tracking block was executed.") legacyTrackingExecuted.expectedFulfillmentCount = flows.count - - let track = { (event: AnalyticsEvent) in + + let track = { (_: AnalyticsEvent) in XCTFail() } - + let tracker = AuthenticatorAnalyticsTracker(enabled: false, track: track) - + tracker.set(source: source) - + for flow in flows { tracker.set(flow: flow) tracker.track(step: step, ifTrackingNotEnabled: { legacyTrackingExecuted.fulfill() }) } - + waitForExpectations(timeout: 0.1) } - + /// Tests the new tracking for a step /// func testStepNewTracking() { let source = AuthenticatorAnalyticsTracker.Source.default let flows: [AuthenticatorAnalyticsTracker.Flow] = [.loginWithApple, .signupWithApple, .loginWithGoogle, .signupWithGoogle, .loginWithSiteAddress] let step = AuthenticatorAnalyticsTracker.Step.start - + let legacyTrackingExecuted = expectation(description: "The legacy tracking block was executed.") legacyTrackingExecuted.expectedFulfillmentCount = flows.count - - let track = { (event: AnalyticsEvent) in + + let track = { (_: AnalyticsEvent) in legacyTrackingExecuted.fulfill() } - + let tracker = AuthenticatorAnalyticsTracker(enabled: true, track: track) - + tracker.set(source: source) - + for flow in flows { tracker.set(flow: flow) tracker.track(step: step, ifTrackingNotEnabled: { XCTFail() }) } - + waitForExpectations(timeout: 0.1) } - + /// Tests legacy tracking for a click interaction /// func testClickLegacyTracking() { let source = AuthenticatorAnalyticsTracker.Source.default let flows: [AuthenticatorAnalyticsTracker.Flow] = [.loginWithApple, .signupWithApple, .loginWithGoogle, .signupWithGoogle, .loginWithSiteAddress] let click = AuthenticatorAnalyticsTracker.ClickTarget.connectSite - + let legacyTrackingExecuted = expectation(description: "The legacy tracking block was executed.") legacyTrackingExecuted.expectedFulfillmentCount = flows.count - - let track = { (event: AnalyticsEvent) in + + let track = { (_: AnalyticsEvent) in XCTFail() } - + let tracker = AuthenticatorAnalyticsTracker(enabled: false, track: track) - + tracker.set(source: source) - + for flow in flows { tracker.set(flow: flow) tracker.track(click: click, ifTrackingNotEnabled: { legacyTrackingExecuted.fulfill() }) } - + waitForExpectations(timeout: 0.1) } - + /// Tests the new tracking for a click interaction /// func testClickNewTracking() { let source = AuthenticatorAnalyticsTracker.Source.default let flows: [AuthenticatorAnalyticsTracker.Flow] = [.loginWithApple, .signupWithApple, .loginWithGoogle, .signupWithGoogle, .loginWithSiteAddress] let click = AuthenticatorAnalyticsTracker.ClickTarget.connectSite - + let legacyTrackingExecuted = expectation(description: "The legacy tracking block was executed.") legacyTrackingExecuted.expectedFulfillmentCount = flows.count - - let track = { (event: AnalyticsEvent) in + + let track = { (_: AnalyticsEvent) in legacyTrackingExecuted.fulfill() } - + let tracker = AuthenticatorAnalyticsTracker(enabled: true, track: track) - + tracker.set(source: source) - + for flow in flows { tracker.set(flow: flow) tracker.track(click: click, ifTrackingNotEnabled: { XCTFail() }) } - + waitForExpectations(timeout: 0.1) } - + /// Tests legacy tracking for a failure /// func testFailureLegacyTracking() { let source = AuthenticatorAnalyticsTracker.Source.default let flows: [AuthenticatorAnalyticsTracker.Flow] = [.loginWithApple, .signupWithApple, .loginWithGoogle, .signupWithGoogle, .loginWithSiteAddress] - + let legacyTrackingExecuted = expectation(description: "The legacy tracking block was executed.") legacyTrackingExecuted.expectedFulfillmentCount = flows.count - - let track = { (event: AnalyticsEvent) in + + let track = { (_: AnalyticsEvent) in XCTFail() } - + let tracker = AuthenticatorAnalyticsTracker(enabled: false, track: track) - + tracker.set(source: source) - + for flow in flows { tracker.set(flow: flow) tracker.track(failure: "error", ifTrackingNotEnabled: { legacyTrackingExecuted.fulfill() }) } - + waitForExpectations(timeout: 0.1) } - + /// Tests the new tracking for a failure /// func testFailureNewTracking() { let source = AuthenticatorAnalyticsTracker.Source.default let flows: [AuthenticatorAnalyticsTracker.Flow] = [.loginWithApple, .signupWithApple, .loginWithGoogle, .signupWithGoogle, .loginWithSiteAddress] - + let legacyTrackingExecuted = expectation(description: "The legacy tracking block was executed.") legacyTrackingExecuted.expectedFulfillmentCount = flows.count - - let track = { (event: AnalyticsEvent) in + + let track = { (_: AnalyticsEvent) in legacyTrackingExecuted.fulfill() } - + let tracker = AuthenticatorAnalyticsTracker(enabled: true, track: track) - + tracker.set(source: source) - + for flow in flows { tracker.set(flow: flow) tracker.track(failure: "error", ifTrackingNotEnabled: { XCTFail() }) } - + waitForExpectations(timeout: 0.1) } } diff --git a/WordPressAuthenticatorTests/Authenticator/PasteboardTests.swift b/WordPressAuthenticatorTests/Authenticator/PasteboardTests.swift index 9fbe98560..25c41b829 100644 --- a/WordPressAuthenticatorTests/Authenticator/PasteboardTests.swift +++ b/WordPressAuthenticatorTests/Authenticator/PasteboardTests.swift @@ -18,11 +18,11 @@ class PasteboardTests: XCTestCase { let pasteboard = UIPasteboard.general pasteboard.string = "123456" - UIPasteboard.general.detectAuthenticatorCode() { result in + UIPasteboard.general.detectAuthenticatorCode { result in switch result { case .success(let authenticationCode): XCTAssertEqual(authenticationCode, "123456") - case .failure(_): + case .failure: XCTAssert(false) } expect.fulfill() @@ -40,11 +40,11 @@ class PasteboardTests: XCTestCase { let pasteboard = UIPasteboard.general pasteboard.string = "012345" - UIPasteboard.general.detectAuthenticatorCode() { result in + UIPasteboard.general.detectAuthenticatorCode { result in switch result { case .success(let authenticationCode): XCTAssertEqual(authenticationCode, "012345") - case .failure(_): + case .failure: XCTAssert(false) } expect.fulfill() diff --git a/WordPressAuthenticatorTests/Authenticator/WordPressAuthenticatorDisplayTextTests.swift b/WordPressAuthenticatorTests/Authenticator/WordPressAuthenticatorDisplayTextTests.swift index 4a311bc3a..5773a045a 100644 --- a/WordPressAuthenticatorTests/Authenticator/WordPressAuthenticatorDisplayTextTests.swift +++ b/WordPressAuthenticatorTests/Authenticator/WordPressAuthenticatorDisplayTextTests.swift @@ -7,7 +7,7 @@ class WordPressAuthenticatorDisplayTextTests: XCTestCase { /// Default display text instance /// let displayTextDefaults = WordPressAuthenticatorDisplayStrings.defaultStrings - + /// Verifies that values in defaultText are not nil /// func testThatDefaultTextValuesAreNotNil() { diff --git a/WordPressAuthenticatorTests/Authenticator/WordPressAuthenticatorTests.swift b/WordPressAuthenticatorTests/Authenticator/WordPressAuthenticatorTests.swift index d925bd0c3..25b09b04d 100644 --- a/WordPressAuthenticatorTests/Authenticator/WordPressAuthenticatorTests.swift +++ b/WordPressAuthenticatorTests/Authenticator/WordPressAuthenticatorTests.swift @@ -52,7 +52,7 @@ class WordPressAuthenticatorTests: XCTestCase { // MARK: WordPressAuthenticator Notification Tests func testDispatchesSupportPushNotificationReceived() { let authenticator = WordpressAuthenticatorProvider.getWordpressAuthenticator() - let _ = expectation(forNotification: .wordpressSupportNotificationReceived, object: nil, handler: nil) + _ = expectation(forNotification: .wordpressSupportNotificationReceived, object: nil, handler: nil) authenticator.supportPushNotificationReceived() @@ -61,7 +61,7 @@ class WordPressAuthenticatorTests: XCTestCase { func testDispatchesSupportPushNotificationCleared() { let authenticator = WordpressAuthenticatorProvider.getWordpressAuthenticator() - let _ = expectation(forNotification: .wordpressSupportNotificationCleared, object: nil, handler: nil) + _ = expectation(forNotification: .wordpressSupportNotificationCleared, object: nil, handler: nil) authenticator.supportPushNotificationCleared() @@ -75,7 +75,6 @@ class WordPressAuthenticatorTests: XCTestCase { let nuxTableViewController = NUXTableViewController() let basicViewController = UIViewController() - XCTAssertTrue(WordPressAuthenticator.isAuthenticationViewController(loginViewcontroller)) XCTAssertTrue(WordPressAuthenticator.isAuthenticationViewController(nuxViewController)) XCTAssertTrue(WordPressAuthenticator.isAuthenticationViewController(nuxTableViewController)) diff --git a/WordPressAuthenticatorTests/Authenticator/WordPressSourceTagTests.swift b/WordPressAuthenticatorTests/Authenticator/WordPressSourceTagTests.swift index 3b90334a4..438e629c3 100644 --- a/WordPressAuthenticatorTests/Authenticator/WordPressSourceTagTests.swift +++ b/WordPressAuthenticatorTests/Authenticator/WordPressSourceTagTests.swift @@ -2,122 +2,122 @@ import XCTest import WordPressAuthenticator class WordPressSourceTagTests: XCTestCase { - + func testGeneralLoginSourceTag() { let tag = WordPressSupportSourceTag.generalLogin - + XCTAssertEqual(tag.name, "generalLogin") XCTAssertEqual(tag.origin, "origin:login-screen") } - + func testJetpackLoginSourceTag() { let tag = WordPressSupportSourceTag.jetpackLogin - + XCTAssertEqual(tag.name, "jetpackLogin") XCTAssertEqual(tag.origin, "origin:jetpack-login-screen") } - + func testLoginEmailSourceTag() { let tag = WordPressSupportSourceTag.loginEmail - + XCTAssertEqual(tag.name, "loginEmail") XCTAssertEqual(tag.origin, "origin:login-email") } - + func testLoginAppleSourceTag() { let tag = WordPressSupportSourceTag.loginApple XCTAssertEqual(tag.name, "loginApple") XCTAssertEqual(tag.origin, "origin:login-apple") } - + func testlogin2FASourceTag() { let tag = WordPressSupportSourceTag.login2FA XCTAssertEqual(tag.name, "login2FA") XCTAssertEqual(tag.origin, "origin:login-2fa") } - + func testLoginMagicLinkSourceTag() { let tag = WordPressSupportSourceTag.loginMagicLink - + XCTAssertEqual(tag.name, "loginMagicLink") XCTAssertEqual(tag.origin, "origin:login-magic-link") } - + func testSiteAddressSourceTag() { let tag = WordPressSupportSourceTag.loginSiteAddress XCTAssertEqual(tag.name, "loginSiteAddress") XCTAssertEqual(tag.origin, "origin:login-site-address") } - + func testLoginUsernameSourceTag() { let tag = WordPressSupportSourceTag.loginUsernamePassword XCTAssertEqual(tag.name, "loginUsernamePassword") XCTAssertEqual(tag.origin, "origin:login-username-password") } - + func testLoginUsernamePasswordSourceTag() { let tag = WordPressSupportSourceTag.loginWPComUsernamePassword XCTAssertEqual(tag.name, "loginWPComUsernamePassword") XCTAssertEqual(tag.origin, "origin:wpcom-login-username-password") } - + func testLoginWPComPasswordSourceTag() { let tag = WordPressSupportSourceTag.loginWPComPassword XCTAssertEqual(tag.name, "loginWPComPassword") XCTAssertEqual(tag.origin, "origin:login-wpcom-password") } - + func testWPComSignupEmailSourceTag() { let tag = WordPressSupportSourceTag.wpComSignupEmail XCTAssertEqual(tag.name, "wpComSignupEmail") XCTAssertEqual(tag.origin, "origin:wpcom-signup-email-entry") } - + func testWPComSignupSourceTag() { let tag = WordPressSupportSourceTag.wpComSignup XCTAssertEqual(tag.name, "wpComSignup") XCTAssertEqual(tag.origin, "origin:signup-screen") } - + func testWPComSignupWaitingForGoogleSourceTag() { let tag = WordPressSupportSourceTag.wpComSignupWaitingForGoogle XCTAssertEqual(tag.name, "wpComSignupWaitingForGoogle") XCTAssertEqual(tag.origin, "origin:signup-waiting-for-google") } - + func testWPComAuthGoogleSignupWaitingForGoogleSourceTag() { let tag = WordPressSupportSourceTag.wpComAuthWaitingForGoogle XCTAssertEqual(tag.name, "wpComAuthWaitingForGoogle") XCTAssertEqual(tag.origin, "origin:auth-waiting-for-google") } - + func testWPComAuthGoogleSignupConfirmationSourceTag() { let tag = WordPressSupportSourceTag.wpComAuthGoogleSignupConfirmation XCTAssertEqual(tag.name, "wpComAuthGoogleSignupConfirmation") XCTAssertEqual(tag.origin, "origin:auth-google-signup-confirmation") } - + func testWPComSignupMagicLinkSourceTag() { let tag = WordPressSupportSourceTag.wpComSignupMagicLink XCTAssertEqual(tag.name, "wpComSignupMagicLink") XCTAssertEqual(tag.origin, "origin:signup-magic-link") } - + func testWPComSignupAppleSourceTag() { let tag = WordPressSupportSourceTag.wpComSignupApple - + XCTAssertEqual(tag.name, "wpComSignupApple") XCTAssertEqual(tag.origin, "origin:signup-apple") } diff --git a/WordPressAuthenticatorTests/Credentials/CredentialsTests.swift b/WordPressAuthenticatorTests/Credentials/CredentialsTests.swift index 69e555bd8..a15824123 100644 --- a/WordPressAuthenticatorTests/Credentials/CredentialsTests.swift +++ b/WordPressAuthenticatorTests/Credentials/CredentialsTests.swift @@ -2,37 +2,36 @@ import XCTest @testable import WordPressAuthenticator class CredentialsTests: XCTestCase { - + let token = "arstdhneio123456789qwfpgjluy" let siteURL = "https://example.com" let username = "user123" let password = "arstdhneio" let xmlrpc = "https://example.com/xmlrpc.php" - - + func testWordpressComCredentialsInit() { let wpcomCredentials = WordPressComCredentials(authToken: token, isJetpackLogin: false, multifactor: false, siteURL: siteURL) - + XCTAssertEqual(wpcomCredentials.authToken, token) XCTAssertEqual(wpcomCredentials.isJetpackLogin, false) XCTAssertEqual(wpcomCredentials.multifactor, false) XCTAssertEqual(wpcomCredentials.siteURL, siteURL) } - + func testWordPressComCredentialsSiteURLReturnsDefaultValue() { let wpcomCredentials = WordPressComCredentials(authToken: token, isJetpackLogin: false, multifactor: false, siteURL: "") - + let expected = "https://wordpress.com" - + XCTAssertEqual(wpcomCredentials.siteURL, expected) } - + func testWordPressComCredentialsEquatableReturnsCorrectValue() { let credential = WordPressComCredentials(authToken: token, isJetpackLogin: false, @@ -65,46 +64,46 @@ class CredentialsTests: XCTestCase { XCTAssertNotEqual(credential, differentSiteURL) XCTAssertNotEqual(credential, differentAuthToken) } - + func testWordpressOrgCredentialsInit() { let wporgcredentials = WordPressOrgCredentials(username: username, password: password, xmlrpc: xmlrpc, options: [:]) - + XCTAssertEqual(wporgcredentials.username, username) XCTAssertEqual(wporgcredentials.password, password) XCTAssertEqual(wporgcredentials.xmlrpc, xmlrpc) } - + func testWordPressOrgCredentialsEquatable() { let lhs = WordPressOrgCredentials(username: username, password: password, xmlrpc: xmlrpc, options: [:]) - + let rhs = WordPressOrgCredentials(username: username, password: password, xmlrpc: xmlrpc, options: [:]) - + XCTAssertTrue(lhs == rhs) } - + func testWordPressOrgCredentialsNotEquatable() { let lhs = WordPressOrgCredentials(username: username, password: password, xmlrpc: xmlrpc, options: [:]) - + let rhs = WordPressOrgCredentials(username: "username5678", password: password, xmlrpc: xmlrpc, options: [:]) - + XCTAssertFalse(lhs == rhs) } - + func testAuthenticatorCredentialsInit() { let wporgCredentials = WordPressOrgCredentials(username: username, password: password, @@ -116,8 +115,7 @@ class CredentialsTests: XCTestCase { siteURL: siteURL) let authenticatorCredentials = AuthenticatorCredentials(wpcom: wpcomCredentials, wporg: wporgCredentials) - - + XCTAssertEqual(authenticatorCredentials.wpcom?.authToken, token) XCTAssertEqual(authenticatorCredentials.wpcom?.isJetpackLogin, false) XCTAssertEqual(authenticatorCredentials.wpcom?.multifactor, false) @@ -127,6 +125,4 @@ class CredentialsTests: XCTestCase { XCTAssertEqual(authenticatorCredentials.wporg?.xmlrpc, xmlrpc) } - } - diff --git a/WordPressAuthenticatorTests/Email Client Picker/AppSelectorTests.swift b/WordPressAuthenticatorTests/Email Client Picker/AppSelectorTests.swift index 5bc445af5..f16418db4 100644 --- a/WordPressAuthenticatorTests/Email Client Picker/AppSelectorTests.swift +++ b/WordPressAuthenticatorTests/Email Client Picker/AppSelectorTests.swift @@ -1,7 +1,6 @@ import XCTest @testable import WordPressAuthenticator - struct URLMocks { static let mockAppList = ["gmail": "googlemail://", "airmail": "airmail://"] @@ -20,7 +19,7 @@ class MockUrlHandler: URLHandler { return shouldOpenUrls } - func open(_ url: URL, options: [UIApplication.OpenExternalURLOptionsKey : Any], completionHandler completion: ((Bool) -> Void)?) { + func open(_ url: URL, options: [UIApplication.OpenExternalURLOptionsKey: Any], completionHandler completion: ((Bool) -> Void)?) { openUrlExpectation?.fulfill() } } diff --git a/WordPressAuthenticatorTests/Mocks/WordpressAuthenticatorProvider.swift b/WordPressAuthenticatorTests/Mocks/WordpressAuthenticatorProvider.swift index 2ffb69177..a92ea5f6e 100644 --- a/WordPressAuthenticatorTests/Mocks/WordpressAuthenticatorProvider.swift +++ b/WordPressAuthenticatorTests/Mocks/WordpressAuthenticatorProvider.swift @@ -12,13 +12,13 @@ public class WordpressAuthenticatorProvider: NSObject { googleLoginScheme: "com.googleuserconsent.apps", userAgent: "") } - + static func wordPressAuthenticatorStyle(_ style: AuthenticatorStyeType) -> WordPressAuthenticatorStyle { var wpAuthStyle: WordPressAuthenticatorStyle! - + switch style { case .random: - wpAuthStyle = WordPressAuthenticatorStyle ( + wpAuthStyle = WordPressAuthenticatorStyle( primaryNormalBackgroundColor: UIColor.random(), primaryNormalBorderColor: UIColor.random(), primaryHighlightBackgroundColor: UIColor.random(), @@ -47,13 +47,13 @@ public class WordpressAuthenticatorProvider: NSObject { return wpAuthStyle } } - + static func wordPressAuthenticatorUnifiedStyle(_ style: AuthenticatorStyeType) -> WordPressAuthenticatorUnifiedStyle { var wpUnifiedAuthStyle: WordPressAuthenticatorUnifiedStyle! - + switch style { case .random: - wpUnifiedAuthStyle = WordPressAuthenticatorUnifiedStyle ( + wpUnifiedAuthStyle = WordPressAuthenticatorUnifiedStyle( borderColor: UIColor.random(), errorColor: UIColor.random(), textColor: UIColor.random(), @@ -71,17 +71,17 @@ public class WordpressAuthenticatorProvider: NSObject { static func getWordpressAuthenticator() -> WordPressAuthenticator { return WordPressAuthenticator( - configuration:wordPressAuthenticatorConfiguration(), + configuration: wordPressAuthenticatorConfiguration(), style: wordPressAuthenticatorStyle(.random), unifiedStyle: wordPressAuthenticatorUnifiedStyle(.random), displayImages: WordPressAuthenticatorDisplayImages.defaultImages, displayStrings: WordPressAuthenticatorDisplayStrings.defaultStrings) } - + @objc static func initializeWordPressAuthenticator() { WordPressAuthenticator.initialize( - configuration:wordPressAuthenticatorConfiguration(), + configuration: wordPressAuthenticatorConfiguration(), style: wordPressAuthenticatorStyle(.random), unifiedStyle: wordPressAuthenticatorUnifiedStyle(.random), displayImages: WordPressAuthenticatorDisplayImages.defaultImages, @@ -89,12 +89,10 @@ public class WordpressAuthenticatorProvider: NSObject { } } - enum AuthenticatorStyeType { case random } - extension CGFloat { static func random() -> CGFloat { return CGFloat(arc4random()) / CGFloat(UInt32.max) @@ -104,9 +102,9 @@ extension CGFloat { extension UIColor { static func random() -> UIColor { return UIColor( - red: .random(), + red: .random(), green: .random(), - blue: .random(), + blue: .random(), alpha: 1.0 ) } diff --git a/WordPressAuthenticatorTests/Model/LoginFieldsValidationTests.swift b/WordPressAuthenticatorTests/Model/LoginFieldsValidationTests.swift index 0f334003f..e92ecf765 100644 --- a/WordPressAuthenticatorTests/Model/LoginFieldsValidationTests.swift +++ b/WordPressAuthenticatorTests/Model/LoginFieldsValidationTests.swift @@ -1,7 +1,6 @@ import XCTest @testable import WordPressAuthenticator - // MARK: - LoginFields Validation Tests // class LoginFieldsValidationTests: XCTestCase { @@ -33,10 +32,10 @@ class LoginFieldsValidationTests: XCTestCase { loginFields.siteAddress = "hostname" XCTAssertTrue(loginFields.validateSiteForSignin(), "Hostnames should validate.") - + loginFields.siteAddress = "http://hostname" XCTAssert(loginFields.validateSiteForSignin(), "Since we want to validate simple mistakes, to use a hostname you'll need an http:// or https:// prefix.") - + loginFields.siteAddress = "https://hostname" XCTAssert(loginFields.validateSiteForSignin(), "Since we want to validate simple mistakes, to use a hostname you'll need an http:// or https:// prefix.") From 0f969fca7436794c8219d5b9d9a45a7937d0e531 Mon Sep 17 00:00:00 2001 From: Stephenie Harris Date: Mon, 29 Mar 2021 15:04:59 -0600 Subject: [PATCH 20/23] Fix build error caused by non-optional var. --- .../Unified Auth/GoogleAuthenticator.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPressAuthenticator/Unified Auth/GoogleAuthenticator.swift b/WordPressAuthenticator/Unified Auth/GoogleAuthenticator.swift index 80ee30605..aad82da8a 100644 --- a/WordPressAuthenticator/Unified Auth/GoogleAuthenticator.swift +++ b/WordPressAuthenticator/Unified Auth/GoogleAuthenticator.swift @@ -103,7 +103,7 @@ class GoogleAuthenticator: NSObject { return facade }() - private lazy weak var authenticationDelegate: WordPressAuthenticatorDelegate = { + private weak var authenticationDelegate: WordPressAuthenticatorDelegate? = { guard let delegate = WordPressAuthenticator.shared.delegate else { fatalError() } @@ -359,7 +359,7 @@ private extension GoogleAuthenticator { if accountCreated { SVProgressHUD.dismiss() // Notify the host app - self?.authenticationDelegate.createdWordPressComAccount(username: wpcomUsername, authToken: wpcomToken) + self?.authenticationDelegate?.createdWordPressComAccount(username: wpcomUsername, authToken: wpcomToken) // Notify the delegate self?.accountCreated(credentials: credentials) @@ -368,7 +368,7 @@ private extension GoogleAuthenticator { // Existing Account // Sync host app - self?.authenticationDelegate.sync(credentials: credentials) { + self?.authenticationDelegate?.sync(credentials: credentials) { SVProgressHUD.dismiss() // Notify delegate self?.logInInstead(credentials: credentials) From 26832ddb444a182addf5464f3125141ef5fef2aa Mon Sep 17 00:00:00 2001 From: James Frost Date: Fri, 2 Apr 2021 14:55:27 +0100 Subject: [PATCH 21/23] Allow NUXButtonView leading and trailing constraints to be overridden * This fixes an issue on the login prologue screen where the top shadow didn't reach all the way to the edges of the superview, as it was constrained to the edges of the button view. --- .../NUX/NUXButtonView.storyboard | 15 ++++++---- .../NUX/NUXButtonViewController.swift | 29 ++++++++++++++++++- .../Signin/LoginPrologueViewController.swift | 2 ++ 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/WordPressAuthenticator/NUX/NUXButtonView.storyboard b/WordPressAuthenticator/NUX/NUXButtonView.storyboard index efab307ca..c36107515 100644 --- a/WordPressAuthenticator/NUX/NUXButtonView.storyboard +++ b/WordPressAuthenticator/NUX/NUXButtonView.storyboard @@ -1,9 +1,9 @@ - + - + @@ -47,7 +47,7 @@ - + @@ -64,7 +64,7 @@ - + @@ -76,6 +76,7 @@ + @@ -86,7 +87,6 @@ - @@ -96,6 +96,8 @@ + + @@ -105,5 +107,8 @@ + + + diff --git a/WordPressAuthenticator/NUX/NUXButtonViewController.swift b/WordPressAuthenticator/NUX/NUXButtonViewController.swift index 262b246f0..86e8b090c 100644 --- a/WordPressAuthenticator/NUX/NUXButtonViewController.swift +++ b/WordPressAuthenticator/NUX/NUXButtonViewController.swift @@ -34,13 +34,23 @@ open class NUXButtonViewController: UIViewController { // MARK: - Properties - @IBOutlet private var shadowView: UIImageView? @IBOutlet var stackView: UIStackView? @IBOutlet var bottomButton: NUXButton? @IBOutlet var topButton: NUXButton? @IBOutlet var tertiaryButton: NUXButton? @IBOutlet var buttonHolder: UIView? + @IBOutlet private var shadowView: UIImageView? + @IBOutlet private var shadowViewEdgeConstraints: [NSLayoutConstraint]! + + /// Used to constrain the shadow view outside of the + /// bounds of this view controller. + weak var shadowLayoutGuide: UILayoutGuide? { + didSet { + updateShadowViewEdgeConstraints() + } + } + open weak var delegate: NUXButtonViewControllerDelegate? open var backgroundColor: UIColor? @@ -91,6 +101,23 @@ open class NUXButtonViewController: UIViewController { } } + private func updateShadowViewEdgeConstraints() { + guard let layoutGuide = shadowLayoutGuide, + let shadowView = shadowView else { + return + } + + NSLayoutConstraint.deactivate(shadowViewEdgeConstraints) + shadowView.translatesAutoresizingMaskIntoConstraints = false + + shadowViewEdgeConstraints = [ + layoutGuide.leadingAnchor.constraint(equalTo: shadowView.leadingAnchor), + layoutGuide.trailingAnchor.constraint(equalTo: shadowView.trailingAnchor), + ] + + NSLayoutConstraint.activate(shadowViewEdgeConstraints) + } + // MARK: public API /// Public method to set the button titles. diff --git a/WordPressAuthenticator/Signin/LoginPrologueViewController.swift b/WordPressAuthenticator/Signin/LoginPrologueViewController.swift index 58dd366b4..729c6f9fb 100644 --- a/WordPressAuthenticator/Signin/LoginPrologueViewController.swift +++ b/WordPressAuthenticator/Signin/LoginPrologueViewController.swift @@ -163,6 +163,8 @@ class LoginPrologueViewController: LoginViewController { } buildUnifiedPrologueButtons(buttonViewController) + + buttonViewController.shadowLayoutGuide = view.safeAreaLayoutGuide } /// Displays the old UI prologue buttons. From 3f64695eaf173af3b2fa8b3c2c89c2813a16e462 Mon Sep 17 00:00:00 2001 From: James Frost Date: Fri, 2 Apr 2021 14:55:56 +0100 Subject: [PATCH 22/23] Bump podspec to 1.36.0-beta.4 --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index a17173fb2..34b42f073 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WordPressAuthenticator" - s.version = "1.36.0-beta.3" + s.version = "1.36.0-beta.4" s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps." s.description = <<-DESC From 7a75f51095018bf4732c67779b27dbce5249c689 Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Tue, 6 Apr 2021 13:09:47 +0200 Subject: [PATCH 23/23] Bump version to 1.36.0 --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index 34b42f073..174cdead7 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WordPressAuthenticator" - s.version = "1.36.0-beta.4" + s.version = "1.36.0" s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps." s.description = <<-DESC