-
Notifications
You must be signed in to change notification settings - Fork 112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Login] Improve error messaging displaying a new error screen when application password is disabled #15031
base: trunk
Are you sure you want to change the base?
[Login] Improve error messaging displaying a new error screen when application password is disabled #15031
Conversation
…ed application password.
…ledViewModel.swift - Modify navigation logic to pop to the third last view controller or root if fewer than three - Update primary button title to "Retry" for retrying application password authorization - Remove outdated primary button title "Log in with WordPress.com"
…ordDisabledViewModel` using Woo mobile guidelines
…swordViewModelTests`
📲 You can test the changes from this Pull Request in WooCommerce iOS by scanning the QR code below to install the corresponding build.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While testing navigation back and forth, I encountered a case where the application password fetch failed with the following log:
Tracked application_password_authorization_url_fetch_failed, properties: [error_domain: Networking.RequestAuthenticatorError, error_description: Alamofire.AFError.requestAdaptationFailed(error: Networking.RequestAuthenticatorError.applicationPasswordNotAvailable), error_code: 1]
In this case, the fetchAuthURL
method failed with error and the logic went through to the catch
block, which showed an alert instead of the application password not available screen:
Simulator.Screen.Recording.-.iPhone.16.Pro.-.2025-02-03.at.11.50.29.mp4
We should also check the logic in this catch block to show the new screen if we get the applicationPasswordNotAvailable
error.
// Pop back two view controllers to remove both error and web view | ||
navigationController?.popViewController(animated: false) | ||
navigationController?.popViewController(animated: true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is hacky and prone to error. How about looking for the index of ApplicationPasswordTutorialViewController
in the navigation stack, and pop to the index before that?
A better option would be to send the view controller before the application password flow to this view controller via presentApplicationPasswordWebView
in AuthenticationManager
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with you and with your second suggestion, so I applied the new changes in this commit: 9b480ba
.../Authentication/Application Password/ApplicationPasswordAuthorizationWebViewController.swift
Outdated
Show resolved
Hide resolved
if viewControllers.count >= 3 { | ||
navigationController.popToViewController(viewControllers[viewControllers.count - 3], animated: true) | ||
} else { | ||
navigationController.popToRootViewController(animated: true) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The number 3 seems to be a magic number, it's not clear why we have to do this. Please consider my suggestion above about looking for the index of a specific view controller to pop to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now I'm using the previousVC
like in the comment above, please feel free to check changes here: 9b480ba 🙏
…abled-note-take-2
- Modify `ApplicationPasswordAuthorizationWebViewController.swift` to include a reference to the previous view controller for navigation purposes. - Update `AuthenticationManager.swift` to pass the previous view controller to the web view used for application password authorization. - Enhance `ApplicationPasswordDisabledViewModel.swift` to store the previous view controller and use it for navigation. - Adjust `PostSiteCredentialLoginChecker.swift` to capture and utilize the last view controller before the application password flow. - Update tests in `ApplicationPasswordDisabledViewModelTests.swift` to include the previous view controller in the view model initialization.
…abled-note-take-2
@itsmeichigo this is ready for another check 🙌 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates, Paolo. I found a few issues with the new changes in the comments below.
Also, it seems that you missed the comment in my previous round about missing the case when fetching the authentication URL fails with Alamofire.AFError.requestAdaptationFailed(error: Networking.RequestAuthenticatorError.applicationPasswordNotAvailable)
.
@@ -34,6 +34,9 @@ final class ApplicationPasswordAuthorizationWebViewController: UIViewController | |||
return indicator | |||
}() | |||
|
|||
/// The view controller that was presenting the application password flow. | |||
private weak var previousViewController: UIViewController? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering: is there any case where previousViewController
can be deallocated when the user is still on ApplicationPasswordAuthorizationWebViewController
? I'm curious why the weak reference is necessary here.
@@ -171,6 +189,15 @@ private extension ApplicationPasswordAuthorizationWebViewController { | |||
} | |||
} | |||
|
|||
/// Pops to the previous view controller (if provided) or pops one level otherwise. | |||
@objc private func navigateToPreviousViewController() { | |||
if let previous = previousViewController, let nav = navigationController { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super nit: we can simplify the if let
checks now.
if let previous = previousViewController, let nav = navigationController { | |
if let previousViewController, let navigationController { |
let image: UIImage = .errorImage | ||
|
||
// The VC that was showing before the application password flow. This is used to navigate back without guesswork. | ||
let previousViewController: UIViewController? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Related to a question above: the previousViewController
reference is kept strongly here. Is it intentional to keep the weak reference in ApplicationPasswordAuthorizationWebViewController
but strong here?
guard let viewController else { | ||
return | ||
guard let navigationController = viewController?.navigationController else { return } | ||
if let previousViewController = previousViewController { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super nit:
if let previousViewController = previousViewController { | |
if let previousViewController { |
// show application password disabled error, and catch the last view controller that was showing before the Application Password flow. | ||
let previousViewController = navigationController.viewControllers.dropLast().last |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the exact controller that you are navigating to here? Please note that the PostSiteCredentialLoginChecker
can be triggered from two places: (1) after site credential login (if application password is not required), and (2) after application password login.
For (1), I'd suggest sending nil
as the previous view controller to the PostSiteCredentialLoginChecker
, so that the error page would simply pop itself upon navigating back.
For (2), I'd suggest sending the previous view controller from the application password entry point in AuthenticationManager
if let previousViewController = previousViewController { | ||
navigationController.popToViewController(previousViewController, animated: true) | ||
} else { | ||
navigationController.popToRootViewController(animated: true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you want to pop to the previous view controller, popToRoot
seems incorrect. Should it be popViewController
?
Closes: #14004 (and peaMlT-U4)
Description
This pull request introduces improvements to handling the scenario when application passwords are disabled in user's website. The changes involve updating the error handling UI and navigation logic to provide a better user experience. This is a continuation of the job started by @hafizrahman here.
Testing information
Screenshots
RELEASE-NOTES.txt
if necessary.Reviewer (or Author, in the case of optional code reviews):
Please make sure these conditions are met before approving the PR, or request changes if the PR needs improvement: