From cf69dbb6570ec2212b51fcda9cf284a3dd5b597a Mon Sep 17 00:00:00 2001 From: Hafiz Rahman Date: Thu, 31 Oct 2024 16:23:34 +0700 Subject: [PATCH] First pass at converting error dialog into an error screen for disabled application password. --- ...cationPasswordAuthorizationViewModel.swift | 2 +- ...sswordAuthorizationWebViewController.swift | 36 ++++++++++++++++++- ...ApplicationPasswordDisabledViewModel.swift | 20 ++++++++++- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/WooCommerce/Classes/Authentication/Application Password/ApplicationPasswordAuthorizationViewModel.swift b/WooCommerce/Classes/Authentication/Application Password/ApplicationPasswordAuthorizationViewModel.swift index f4af2404173..17dcd02737c 100644 --- a/WooCommerce/Classes/Authentication/Application Password/ApplicationPasswordAuthorizationViewModel.swift +++ b/WooCommerce/Classes/Authentication/Application Password/ApplicationPasswordAuthorizationViewModel.swift @@ -4,7 +4,7 @@ import Yosemite /// View model for `ApplicationPasswordAuthorizationWebViewController`. /// final class ApplicationPasswordAuthorizationViewModel { - private let siteURL: String + let siteURL: String private let stores: StoresManager init(siteURL: String, diff --git a/WooCommerce/Classes/Authentication/Application Password/ApplicationPasswordAuthorizationWebViewController.swift b/WooCommerce/Classes/Authentication/Application Password/ApplicationPasswordAuthorizationWebViewController.swift index 836f54d9f74..376e5463e54 100644 --- a/WooCommerce/Classes/Authentication/Application Password/ApplicationPasswordAuthorizationWebViewController.swift +++ b/WooCommerce/Classes/Authentication/Application Password/ApplicationPasswordAuthorizationWebViewController.swift @@ -157,7 +157,20 @@ private extension ApplicationPasswordAuthorizationWebViewController { guard let url = try await viewModel.fetchAuthURL() else { DDLogError("⛔️ No authorization URL found for application passwords") analytics.track(.applicationPasswordAuthorizationURLNotAvailable) - return showErrorAlert(message: Localization.applicationPasswordDisabled) + + let errorUI = applicationPasswordDisabledUI(for: viewModel.siteURL) + // When the error view controller is popped, also pop the web view + errorUI.navigationItem.leftBarButtonItem = UIBarButtonItem( + image: UIImage(systemName: "chevron.backward"), + style: .plain, + target: self, + action: #selector(popBothControllers) + ) + + // Push instead of present + navigationController?.pushViewController(errorUI, animated: true) + + return } loadAuthorizationPage(url: url) } catch { @@ -171,6 +184,12 @@ private extension ApplicationPasswordAuthorizationWebViewController { } } + @objc private func popBothControllers() { + // Pop back two view controllers to remove both error and web view + navigationController?.popViewController(animated: false) + navigationController?.popViewController(animated: true) + } + func loadAuthorizationPage(url: URL) { let parameters: [URLQueryItem] = [ URLQueryItem(name: Constants.Query.appName, value: appName), @@ -220,6 +239,14 @@ private extension ApplicationPasswordAuthorizationWebViewController { } present(alertController, animated: true) } + + /// The error screen to be displayed when the user tries to log in with site credentials + /// with application password disabled. + /// + func applicationPasswordDisabledUI(for siteURL: String) -> UIViewController { + let viewModel = ApplicationPasswordDisabledViewModel(siteURL: siteURL) + return ULErrorViewController(viewModel: viewModel) + } } extension ApplicationPasswordAuthorizationWebViewController: WKNavigationDelegate { @@ -254,6 +281,13 @@ extension ApplicationPasswordAuthorizationWebViewController: WKNavigationDelegat } } +extension ApplicationPasswordAuthorizationWebViewController: UIAdaptivePresentationControllerDelegate { + func presentationControllerDidDismiss(_ presentationController: UIPresentationController) { + // This will be called when the error UI is dismissed + navigationController?.dismiss(animated: true) + } +} + private extension ApplicationPasswordAuthorizationWebViewController { enum Constants { static let successURL = "woocommerce://application-password" diff --git a/WooCommerce/Classes/Authentication/Navigation Exceptions/ApplicationPasswordDisabledViewModel.swift b/WooCommerce/Classes/Authentication/Navigation Exceptions/ApplicationPasswordDisabledViewModel.swift index 7a9a747a7c2..1267e74c283 100644 --- a/WooCommerce/Classes/Authentication/Navigation Exceptions/ApplicationPasswordDisabledViewModel.swift +++ b/WooCommerce/Classes/Authentication/Navigation Exceptions/ApplicationPasswordDisabledViewModel.swift @@ -5,11 +5,14 @@ import WordPressAuthenticator /// modeling an error when application password is disabled. /// struct ApplicationPasswordDisabledViewModel: ULErrorViewModel { - init(siteURL: String) { + init(siteURL: String, + authentication: Authentication = ServiceLocator.authenticationManager) { self.siteURL = siteURL + self.authentication = authentication } let siteURL: String + let authentication: Authentication let image: UIImage = .errorImage // TODO: update this if needed var text: NSAttributedString { @@ -55,6 +58,17 @@ struct ApplicationPasswordDisabledViewModel: ULErrorViewModel { } WebviewHelper.launch(Constants.applicationPasswordLink, with: viewController) } + + var rightBarButtonItemTitle: String? { + return Localization.helpButtonTitle + } + + func didTapRightBarButtonItem(in viewController: UIViewController?) { + guard let viewController else { + return + } + authentication.presentSupport(from: viewController, screen: .noWooError) + } } private extension ApplicationPasswordDisabledViewModel { @@ -78,6 +92,10 @@ private extension ApplicationPasswordDisabledViewModel { "Log in with WordPress.com", comment: "Button that will navigate to the authentication flow with WP.com" ) + static let helpButtonTitle = NSLocalizedString( + "Help", + comment: "Button that will navigate to the support area" + ) } enum Constants { static let applicationPasswordLink = "https://make.wordpress.org/core/2020/11/05/application-passwords-integration-guide/"