-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Fix an issue where the All Domains flow wasn't taking into account sites with existing plan #22343
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
Changes from all commits
beda8a0
0ba85e7
1ddee63
8923eaf
d5e405b
3eb3edb
6398d0a
b8b430f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,19 +13,26 @@ class RegisterDomainCoordinator { | |
| typealias DomainPurchasedCallback = ((UIViewController, String) -> Void) | ||
| typealias DomainAddedToCartCallback = ((UIViewController, String, Blog) -> Void) | ||
|
|
||
| // MARK: Variables | ||
| // MARK: Dependencies | ||
|
|
||
| private let domainRegistrationService: RegisterDomainDetailsServiceProxyProtocol | ||
| private let crashLogger: CrashLogging | ||
|
|
||
| // MARK: Variables | ||
|
|
||
| let analyticsSource: String | ||
|
|
||
| // TODO: This can cause Core Data crashes. Pass `NSManagedObjectID` instead. | ||
| var site: Blog? | ||
| var domainPurchasedCallback: DomainPurchasedCallback? | ||
| var domainAddedToCartAndLinkedToSiteCallback: DomainAddedToCartCallback? | ||
|
|
||
| var domain: DomainSuggestion? | ||
|
|
||
| var domainPurchasedCallback: DomainPurchasedCallback? | ||
|
|
||
| private var webViewURLChangeObservation: NSKeyValueObservation? | ||
|
|
||
| // MARK: - Init | ||
|
|
||
| /// Initializes a `RegisterDomainCoordinator` with the specified parameters. | ||
| /// | ||
| /// - Parameters: | ||
|
|
@@ -36,20 +43,23 @@ class RegisterDomainCoordinator { | |
| init(site: Blog?, | ||
| domainPurchasedCallback: RegisterDomainCoordinator.DomainPurchasedCallback? = nil, | ||
| analyticsSource: String = "domains_register", | ||
| crashLogger: CrashLogging = .main) { | ||
| crashLogger: CrashLogging = .main, | ||
| domainRegistrationService: RegisterDomainDetailsServiceProxyProtocol = RegisterDomainDetailsServiceProxy()) { | ||
| self.site = site | ||
| self.domainPurchasedCallback = domainPurchasedCallback | ||
| self.crashLogger = crashLogger | ||
| self.analyticsSource = analyticsSource | ||
| self.domainRegistrationService = domainRegistrationService | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This service was instantiated within the |
||
| } | ||
|
|
||
| // MARK: Public Functions | ||
| // MARK: - Public Functions | ||
|
|
||
| /// Adds the selected domain to the cart then launches the checkout webview. | ||
| /// This flow support purchasing domains only, without plans. | ||
| func handlePurchaseDomainOnly(on viewController: UIViewController, | ||
| onSuccess: @escaping () -> (), | ||
| onFailure: @escaping () -> ()) { | ||
| // TODO: Refactor `handlePurchaseDomainOnly` to use `purchaseDomain` helper. | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will be addressed in another PR. |
||
| createCart { [weak self] result in | ||
| switch result { | ||
| case .success: | ||
|
|
@@ -66,13 +76,14 @@ class RegisterDomainCoordinator { | |
| func addDomainToCartLinkedToCurrentSite(on viewController: UIViewController, | ||
| onSuccess: @escaping () -> (), | ||
| onFailure: @escaping () -> ()) { | ||
| // TODO: Refactor `addDomainToCartLinkedToCurrentSite` to use `purchaseDomain` helper. | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will be addressed in another PR. |
||
| guard let blog = site else { | ||
| return | ||
| } | ||
| createCart { [weak self] result in | ||
| switch result { | ||
| case .success(let domain): | ||
| self?.domainAddedToCartAndLinkedToSiteCallback?(viewController, domain.domainName, blog) | ||
| self?.presentPlansWebview(for: blog, domain: domain, on: viewController) | ||
| onSuccess() | ||
| case .failure: | ||
| onFailure() | ||
|
|
@@ -83,18 +94,9 @@ class RegisterDomainCoordinator { | |
| /// Related to the `purchaseFromDomainManagement` Domain selection type. | ||
| /// Adds the selected domain to the cart then launches the checkout webview | ||
| /// The checkout webview is configured for the domain management flow | ||
| func handleNoSiteChoice(on viewController: UIViewController, | ||
| choicesViewModel: DomainPurchaseChoicesViewModel?) { | ||
| createCart { [weak self] result in | ||
| switch result { | ||
| case .success: | ||
| self?.presentCheckoutWebview(on: viewController, title: TextContent.checkoutTitle) | ||
| choicesViewModel?.isGetDomainLoading = false | ||
|
|
||
| case .failure: | ||
| viewController.displayActionableNotice(title: TextContent.errorTitle, actionTitle: TextContent.errorDismiss) | ||
| choicesViewModel?.isGetDomainLoading = false | ||
| } | ||
| func handleNoSiteChoice(on viewController: UIViewController, choicesViewModel: DomainPurchaseChoicesViewModel?) { | ||
| self.purchaseDomain(for: site, on: viewController) { _ in | ||
| choicesViewModel?.isGetDomainLoading = false | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -117,18 +119,11 @@ class RegisterDomainCoordinator { | |
| return | ||
| } | ||
| controller.showLoading() | ||
| self.createCart { [weak self] result in | ||
| guard let self else { | ||
| return | ||
| } | ||
| switch result { | ||
| case .success(let domain): | ||
| self.purchaseDomain(for: selectedBlog, on: controller) { result in | ||
| controller.hideLoading() | ||
| if case .success = result { | ||
| self.site = selectedBlog | ||
| self.domainAddedToCartAndLinkedToSiteCallback?(controller, domain.domainName, selectedBlog) | ||
| case .failure: | ||
| controller.displayActionableNotice(title: TextContent.errorTitle, actionTitle: TextContent.errorDismiss) | ||
| } | ||
| controller.hideLoading() | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -141,24 +136,66 @@ class RegisterDomainCoordinator { | |
|
|
||
| // MARK: Helpers | ||
|
|
||
| /// Initiates the process of purchasing a domain with or without a site. | ||
| /// | ||
| /// - Parameters: | ||
| /// - site: The blog site for which the domain is being purchased. Optional. | ||
| /// - viewController: The UIViewController from which the domain registration or checkout process is presented. | ||
| /// - completion: A closure that is called upon the completion of the purchase attempt. | ||
| /// It returns a `Result` indicating either success or failure. | ||
| /// | ||
| /// The method follows this logic: | ||
| /// - The "Register Domain" screen is presented when `site.canRegisterDomainWithPaidPlan` is `true`. | ||
| /// - If the site does not have any domains (`!site.hasDomains`), the Plans web view is shown. | ||
| /// - For sites with existing domains, the Checkout web view is presented, | ||
| private func purchaseDomain(for site: Blog?, on viewController: UIViewController, completion: @escaping (Result<Void, Swift.Error>) -> Void) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think a VM would be a better fit for these service calls but it doesn't have to be part of this PR. |
||
| guard let domain else { | ||
| completion(.failure(Error.noDomainWhenCreatingCart)) | ||
| return | ||
| } | ||
| if let site, site.canRegisterDomainWithPaidPlan { | ||
| self.presentDomainRegistration(for: site, domain: domain, on: viewController) | ||
| completion(.success(())) | ||
| return | ||
| } | ||
| self.createCart { [weak self] result in | ||
| guard let self else { | ||
| return | ||
| } | ||
| switch result { | ||
| case .success(let domain): | ||
| if let site, !site.hasDomains { | ||
| self.presentPlansWebview(for: site, domain: domain, on: viewController) | ||
| } else { | ||
| self.presentCheckoutWebview(on: viewController, title: TextContent.checkoutTitle) | ||
| } | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is exactly the change that fixes the issue:
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for clarifying 🙏
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @staskus Re-reading
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, sounds right! |
||
| completion(.success(())) | ||
| case .failure(let error): | ||
| viewController.displayActionableNotice(title: TextContent.errorTitle, actionTitle: TextContent.errorDismiss) | ||
|
salimbraksa marked this conversation as resolved.
|
||
| completion(.failure(error)) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private func createCart(completion: @escaping (Result<DomainSuggestion, Swift.Error>) -> Void) { | ||
| guard let domain else { | ||
| completion(.failure(Error.noDomainWhenCreatingCart)) | ||
| return | ||
| } | ||
| let siteID = site?.dotComID?.intValue | ||
| let proxy = RegisterDomainDetailsServiceProxy() | ||
| proxy.createPersistentDomainShoppingCart(siteID: siteID, | ||
| domainSuggestion: domain, | ||
| privacyProtectionEnabled: domain.supportsPrivacy ?? false, | ||
| success: { _ in | ||
| self.domainRegistrationService.createPersistentDomainShoppingCart(siteID: siteID, | ||
| domainSuggestion: domain, | ||
| privacyProtectionEnabled: domain.supportsPrivacy ?? false, | ||
| success: { _ in | ||
| completion(.success(domain)) | ||
| }, | ||
| failure: { error in | ||
| failure: { error in | ||
| completion(.failure(error)) | ||
| }) | ||
| } | ||
|
|
||
| // MARK: - Presenting Checkout Web View | ||
|
|
||
| private func presentCheckoutWebview(on viewController: UIViewController, | ||
| title: String?) { | ||
| guard let domain, | ||
|
|
@@ -252,6 +289,46 @@ class RegisterDomainCoordinator { | |
| } | ||
| } | ||
|
|
||
| // MARK: - Presenting Domain Registration View | ||
|
|
||
| private func presentDomainRegistration( | ||
| for site: Blog, | ||
| domain: DomainSuggestion, | ||
| on viewController: UIViewController | ||
| ) { | ||
| guard let siteID = site.dotComID?.intValue else { | ||
| return | ||
| } | ||
| let destination = RegisterDomainDetailsViewController() | ||
| destination.viewModel = RegisterDomainDetailsViewModel(siteID: siteID, domain: domain) { [weak self] name in | ||
| guard let self = self else { | ||
| return | ||
| } | ||
| self.domainPurchasedCallback?(viewController, name) | ||
| self.trackDomainPurchasingCompleted() | ||
| } | ||
| } | ||
|
|
||
| // MARK: - Presenting Plans | ||
|
|
||
| private func presentPlansWebview( | ||
| for site: Blog, | ||
| domain: DomainSuggestion, | ||
| on viewController: UIViewController | ||
| ) { | ||
| let presentPlansFlow = FreeToPaidPlansCoordinator.plansFlowAfterDomainAddedToCartBlock( | ||
| customTitle: nil, | ||
| analyticsSource: analyticsSource | ||
| ) { [weak self] controller, domain in | ||
| guard let self else { | ||
| return | ||
| } | ||
| self.domainPurchasedCallback?(controller, domain) | ||
| self.trackDomainPurchasingCompleted() | ||
| } | ||
| presentPlansFlow(viewController, domain.domainName, site) | ||
| } | ||
|
|
||
| // MARK: - Tracks | ||
|
|
||
| private func track(_ event: WPAnalyticsEvent, properties: [AnyHashable: Any]? = nil) { | ||
|
|
||

Uh oh!
There was an error while loading. Please reload this page.
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.
FYI @hassaanelgarem I'll address this in a separate PR.