Skip to content
This repository was archived by the owner on Feb 5, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
061dcd5
Update extension for storyboard and UIViewController to instantiate w…
itsmeichigo Aug 15, 2022
1120d94
Add new delegate method for troubleshooting a site
itsmeichigo Aug 15, 2022
1be9c7c
Make navigation controller optional in `troubleshootSite`
itsmeichigo Aug 15, 2022
a094ce6
Add new initializer for `SiteAddressViewController` to support troubl…
itsmeichigo Aug 15, 2022
d9667c4
Add new method to support displaying the site address UI for troubles…
itsmeichigo Aug 15, 2022
1f1b5a6
Bump version in podspec
itsmeichigo Aug 15, 2022
e1d5159
Make the default extension public
itsmeichigo Aug 15, 2022
2c8b170
Refactor: rename needsTroubleShooting to isSiteDiscovery and update t…
itsmeichigo Aug 17, 2022
811c11c
Check site validity before checking for WordPress
itsmeichigo Aug 17, 2022
3a31819
Move error handling to the main thread
itsmeichigo Aug 17, 2022
23a5324
Stop loading state when encountering non-existent URL error
itsmeichigo Aug 17, 2022
72a7652
Increase timeout for site check
itsmeichigo Aug 17, 2022
17c962e
Update error message for non-existent site address
itsmeichigo Aug 17, 2022
eb58755
Merge branch 'trunk' into wcios/site-address-discovery
itsmeichigo Aug 17, 2022
7cdd0c6
Trigger delegate method when check WP fails
itsmeichigo Aug 17, 2022
032faba
Add comment to clarify parameters for troubleshootSite
itsmeichigo Aug 18, 2022
90de21d
Bump podspec version
itsmeichigo Aug 18, 2022
9ac61bf
Merge branch 'trunk' into wcios/site-address-discovery
itsmeichigo Aug 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion WordPressAuthenticator.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Pod::Spec.new do |s|
s.name = 'WordPressAuthenticator'
s.version = '2.2.1-beta.2'
s.version = '2.2.1-beta.3'

s.summary = 'WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps.'
s.description = <<-DESC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ public class AuthenticatorAnalyticsTracker {
///
case loginWithSiteAddress = "login_site_address"

/// This flow starts when the user wants to troubleshoot their site by inputting its address
///
case siteDiscovery = "site_discovery"

/// This flow represents the signup (when the user inputs an email that’s not registered with a .com account)
///
case signup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,14 @@ import WordPressKit
return SiteAddressViewController.instantiate(from: .siteAddress)
}

/// Returns a Site Address view controller and triggers the protocol method `troubleshootSite` after fetching the site info.
///
@objc public class func siteDiscoveryUI() -> UIViewController? {
return SiteAddressViewController.instantiate(from: .siteAddress) { coder in
SiteAddressViewController(isSiteDiscovery: true, coder: coder)
}
}

// Helper used by WPAuthTokenIssueSolver
@objc
public class func signinForWPCom(dotcomEmailAddress: String?, dotcomUsername: String?, onDismissed: ((_ cancelled: Bool) -> Void)? = nil) -> UIViewController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,15 @@ public protocol WordPressAuthenticatorDelegate: AnyObject {
///
func sync(credentials: AuthenticatorCredentials, onCompletion: @escaping () -> Void)

/// Signals to the Host App that a WordPress site is available and needs validated.
/// This method is only triggered in the site discovery flow.
///
/// - Parameters:
/// - siteInfo: The fetched site information - can be nil the site doesn't exist or have WordPress
/// - navigationController: the current navigation stack of the site discovery flow.
///
func troubleshootSite(_ siteInfo: WordPressComSiteInfo?, in navigationController: UINavigationController?)

/// Signals the Host App that a given Analytics Event has occurred.
///
func track(event: WPAnalyticsStat)
Expand All @@ -102,3 +111,11 @@ public protocol WordPressAuthenticatorDelegate: AnyObject {
///
func track(event: WPAnalyticsStat, error: Error)
}

/// Extension with default implementation for optional delegate methods.
///
public extension WordPressAuthenticatorDelegate {
func troubleshootSite(_ siteInfo: WordPressComSiteInfo?, in navigationController: UINavigationController?) {
// No-op
}
}
4 changes: 2 additions & 2 deletions WordPressAuthenticator/Extensions/UIStoryboard+Helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ enum Storyboard: String {
/// Returns a view controller from a Storyboard
/// assuming the identifier is the same as the class name.
///
func instantiateViewController<T: NSObject>(ofClass classType: T.Type) -> T? {
func instantiateViewController<T: NSObject>(ofClass classType: T.Type, creator: ((NSCoder) -> UIViewController?)? = nil) -> T? {
let identifier = classType.classNameWithoutNamespaces
return instance.instantiateViewController(withIdentifier: identifier) as? T
return instance.instantiateViewController(identifier: identifier, creator: creator) as? T
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL this 🙇

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ extension UIViewController {

/// Convenience method to instantiate a view controller from a storyboard.
///
static func instantiate(from storyboard: Storyboard) -> Self? {
return storyboard.instantiateViewController(ofClass: self)
static func instantiate(from storyboard: Storyboard, creator: ((NSCoder) -> UIViewController?)? = nil) -> Self? {
return storyboard.instantiateViewController(ofClass: self, creator: creator)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,20 @@ final class SiteAddressViewController: LoginViewController {
/// should show an activity indicator.
private var viewIsLoading: Bool = false

/// Whether the protocol method `troubleshootSite` should be triggered after site info is fetched.
///
private let isSiteDiscovery: Bool

init?(isSiteDiscovery: Bool, coder: NSCoder) {
self.isSiteDiscovery = isSiteDiscovery
super.init(coder: coder)
}

required init?(coder: NSCoder) {
self.isSiteDiscovery = false
super.init(coder: coder)
}

// MARK: - Actions
@IBAction func handleContinueButtonTapped(_ sender: NUXButton) {
tracker.track(click: .submit)
Expand Down Expand Up @@ -59,7 +73,11 @@ final class SiteAddressViewController: LoginViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

tracker.set(flow: .loginWithSiteAddress)
if isSiteDiscovery {
tracker.set(flow: .siteDiscovery)
} else {
tracker.set(flow: .loginWithSiteAddress)
}

if isMovingToParent {
tracker.track(step: .start)
Expand Down Expand Up @@ -416,8 +434,42 @@ private extension SiteAddressViewController {

configureViewLoading(true)

guard let url = URL(string: loginFields.siteAddress) else {
configureViewLoading(false)
return displayError(message: Localization.invalidURL, moveVoiceOverFocus: true)
}

// Checks that the site exists
var request = URLRequest(url: url)
request.httpMethod = "HEAD"
request.timeoutInterval = 10.0 // waits for 10 seconds
let task = URLSession.shared.dataTask(with: request) { [weak self] _, _, error in
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }

if let error = error {
self.configureViewLoading(false)

if self.authenticationDelegate.shouldHandleError(error) {
self.authenticationDelegate.handleError(error) { customUI in
self.pushCustomUI(customUI)
}
return
}

return self.displayError(message: Localization.nonExistentSiteError, moveVoiceOverFocus: true)
}

// Proceeds to check for the site's WordPress
self.guessXMLRPCURL(for: self.loginFields.siteAddress)
}
}
task.resume()
}
Comment on lines +442 to +468
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


Should we raise a PR in the WP iOS repository and test this change as this code will execute even if isSiteDiscovery is false? 🤔
Internal reference - p91TBi-49U-p2

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense! Added a PR here: wordpress-mobile/WordPress-iOS#19209.


func guessXMLRPCURL(for siteAddress: String) {
let facade = WordPressXMLRPCAPIFacade()
facade.guessXMLRPCURL(forSite: loginFields.siteAddress, success: { [weak self] (url) in
facade.guessXMLRPCURL(forSite: siteAddress, success: { [weak self] (url) in
// Success! We now know that we have a valid XML-RPC endpoint.
// At this point, we do NOT know if this is a WP.com site or a self-hosted site.
if let url = url {
Expand All @@ -439,6 +491,11 @@ private extension SiteAddressViewController {
// WordPressAuthenticator.track(.loginFailed, error: error)
self.configureViewLoading(false)

guard self.isSiteDiscovery == false else {
WordPressAuthenticator.shared.delegate?.troubleshootSite(nil, in: self.navigationController)
return
}

let err = self.originalErrorOrError(error: error as NSError)

/// Check if the host app wants to provide custom UI to handle the error.
Expand Down Expand Up @@ -515,6 +572,11 @@ private extension SiteAddressViewController {
loginFields.siteAddress = verifiedSiteAddress
}

guard isSiteDiscovery == false else {
WordPressAuthenticator.shared.delegate?.troubleshootSite(siteInfo, in: navigationController)
return
}

guard siteInfo?.isWPCom == false else {
showGetStarted()
return
Expand Down Expand Up @@ -611,3 +673,14 @@ private extension SiteAddressViewController {
present(alertController, animated: true)
}
}

private extension SiteAddressViewController {
enum Localization {
static let invalidURL = NSLocalizedString(
"Invalid URL. Please double-check and try again.",
comment: "Error message shown when the input URL is invalid.")
static let nonExistentSiteError = NSLocalizedString(
"Cannot access the site at this address. Please double-check and try again.",
comment: "Error message shown when the input URL does not point to an existing site.")
}
}