Skip to content
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

Plans in Site Creation: Integrate Plan selection into Site Creation flow #21688

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
16 changes: 15 additions & 1 deletion WordPress/Classes/Utility/WebKitViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ extension WebKitAuthenticatable {

class WebKitViewController: UIViewController, WebKitAuthenticatable {
@objc let webView: WKWebView
@objc let progressView = WebProgressView()
@objc let progressView: WebProgressView = {
let progressView = WebProgressView()
progressView.isHidden = true
return progressView
}()
@objc let titleView = NavigationTitleView()
let analyticsSource: String?

Expand Down Expand Up @@ -86,6 +90,7 @@ class WebKitViewController: UIViewController, WebKitAuthenticatable {
@objc var secureInteraction = false
@objc var addsWPComReferrer = false
@objc var customTitle: String?
@objc var displayStatusInNavigationBar = true
private let opensNewInSafari: Bool
let linkBehavior: LinkBehavior

Expand Down Expand Up @@ -128,6 +133,7 @@ class WebKitViewController: UIViewController, WebKitAuthenticatable {
opensNewInSafari = configuration.opensNewInSafari
onClose = configuration.onClose
analyticsSource = configuration.analyticsSource
displayStatusInNavigationBar = configuration.displayStatusInNavigationBar

super.init(nibName: nil, bundle: nil)
hidesBottomBarWhenPushed = true
Expand Down Expand Up @@ -253,6 +259,10 @@ class WebKitViewController: UIViewController, WebKitAuthenticatable {
// MARK: Navigation bar setup

@objc func configureNavigation() {
guard displayStatusInNavigationBar else {
return
}

setupNavBarTitleView()
setupRefreshButton()

Expand Down Expand Up @@ -470,6 +480,10 @@ class WebKitViewController: UIViewController, WebKitAuthenticatable {
}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
guard displayStatusInNavigationBar else {
return
}

guard let object = object as? WKWebView,
object == webView,
let keyPath = keyPath else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class WebViewControllerConfiguration: NSObject {
@objc var optionsButton: UIBarButtonItem?
@objc var secureInteraction = false
@objc var addsWPComReferrer = false
@objc var displayStatusInNavigationBar = true
@objc var analyticsSource: String?

/// Opens any new pages in Safari. Otherwise, a new web view will be opened
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ class SiteDesignContentCollectionViewController: CollapsableHeaderViewController
}

private func configureHeaderStyling() {
headerView.backgroundColor = .systemBackground
headerView.backgroundColor = .basicBackground
hideHeaderVisualEffects()
}

Expand Down
17 changes: 17 additions & 0 deletions WordPress/Classes/ViewRelated/Site Creation/Plan/PlanStep.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
final class PlanStep: WizardStep {
weak var delegate: WizardDelegate?

private let creator: SiteCreator

internal var content: UIViewController {
let viewModel = PlanWizardContentViewModel(siteCreator: creator)
return PlanWizardContent(viewModel: viewModel) { [weak self] planId in
self?.creator.planId = planId
self?.delegate?.nextStep()
}
}

init(creator: SiteCreator) {
self.creator = creator
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import UIKit

final class PlanWizardContent: WebKitViewController {
typealias PlanSelectionCallback = (Int?) -> Void

private let viewModel: PlanWizardContentViewModel
private let completion: PlanSelectionCallback

init(viewModel: PlanWizardContentViewModel, completion: @escaping PlanSelectionCallback) {
self.viewModel = viewModel
self.completion = completion
let configuration = WebViewControllerConfiguration(url: viewModel.url)
configuration.authenticateWithDefaultAccount()
configuration.secureInteraction = true
configuration.displayStatusInNavigationBar = false
super.init(configuration: configuration)
}

override func viewDidLoad() {
super.viewDidLoad()

view.backgroundColor = .basicBackground
}

override func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
guard let url = navigationAction.request.url else {
decisionHandler(.allow)
return
}

if viewModel.isPlanSelected(url) {
completion(viewModel.selectedPlanId(from: url))
decisionHandler(.cancel)
return
}

decisionHandler(.allow)
}

// MARK: - Required Init

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import Foundation

struct PlanWizardContentViewModel {
private let siteCreator: SiteCreator

var url: URL {
var components = URLComponents(string: Constants.plansWebAddress)!
var queryItems: [URLQueryItem] = []

if let domainSuggestion = siteCreator.address, !domainSuggestion.isFree {
queryItems.append(.init(name: Constants.paidDomainNameParameter, value: domainSuggestion.domainName))
}

components.queryItems = queryItems
return components.url!
}


init(siteCreator: SiteCreator) {
self.siteCreator = siteCreator
}

func isPlanSelected(_ redirectionURL: URL) -> Bool {
return selectedPlanSlug(from: redirectionURL) != nil
}

func selectedPlanId(from url: URL) -> Int? {
guard let planId = parameterValue(from: url, key: Constants.planIdParameter) else {
return nil
}

return Int(planId)
}

func selectedPlanSlug(from url: URL) -> String? {
return parameterValue(from: url, key: Constants.planSlugParameter)
}

enum Constants {
static let plansWebAddress = "https://wordpress.com/jetpack-app/plans"
static let planIdParameter = "plan_id"
static let planSlugParameter = "plan_slug"
static let paidDomainNameParameter = "paid_domain_name"
}
}

private extension PlanWizardContentViewModel {
func parameterValue(from url: URL, key: String) -> String? {
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true),
let planSlug = components.queryItems?.first(where: { $0.name == key })?.value else {
return nil
}

return planSlug
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ final class WebAddressWizardContent: CollapsableHeaderViewController {
super.init(scrollableView: table,
mainTitle: Strings.mainTitle,
prompt: Strings.prompt,
primaryActionTitle: Strings.createSite,
primaryActionTitle: creator.domainPurchasingEnabled ? Strings.selectDomain : Strings.createSite,
accessoryView: searchHeader)
}

Expand All @@ -145,6 +145,7 @@ final class WebAddressWizardContent: CollapsableHeaderViewController {
loadHeaderView()
addAddressHintView()
configureUIIfNeeded()
navigationItem.backButtonTitle = Strings.backButtonTitle
}

private func configureUIIfNeeded() {
Expand All @@ -155,8 +156,8 @@ final class WebAddressWizardContent: CollapsableHeaderViewController {
NSLayoutConstraint.activate([
largeTitleView.widthAnchor.constraint(equalTo: headerStackView.widthAnchor)
])
largeTitleView.textAlignment = .natural
promptView.textAlignment = .natural
largeTitleView.textAlignment = .center
promptView.textAlignment = .center
promptView.font = .systemFont(ofSize: 17)
}

Expand All @@ -169,6 +170,7 @@ final class WebAddressWizardContent: CollapsableHeaderViewController {
searchBar.layer.borderWidth = 0
searchHeader.addSubview(searchBar)
searchBar.delegate = self
headerView.backgroundColor = .basicBackground

NSLayoutConstraint.activate([
searchBar.leadingAnchor.constraint(equalTo: searchHeader.leadingAnchor, constant: 8),
Expand Down Expand Up @@ -506,6 +508,9 @@ final class WebAddressWizardContent: CollapsableHeaderViewController {
comment: "Select domain name. Subtitle")
static let createSite: String = NSLocalizedString("Create Site",
comment: "Button to progress to the next step")
static let selectDomain: String = NSLocalizedString("siteCreation.domains.buttons.selectDomain",
value: "Select domain",
comment: "Button to progress to the next step after selecting domain in Site Creation")
static let searchPlaceholder: String = NSLocalizedString("Type a name for your site",
comment: "Site creation. Seelect a domain, search field placeholder")
static let searchAccessibility: String = NSLocalizedString("Searches for available domains to use for your site.",
Expand All @@ -514,6 +519,10 @@ final class WebAddressWizardContent: CollapsableHeaderViewController {
comment: "Suggested domains")
static let noMatch: String = NSLocalizedString("This domain is unavailable",
comment: "Notifies the user that the a domain matching the search term wasn't returned in the results")
static let backButtonTitle = NSLocalizedString("siteCreation.domain.backButton.title",
value: "Domains",
comment: "Back button title shown in Site Creation flow to come back from Plan selection to Domain selection"
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ enum SiteCreationStep {
case intent
case segments
case siteAssembly
case plan
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,24 @@ final class SiteCreationWizardLauncher {
return SiteCreator()
}()

let steps: [SiteCreationStep] = [
.intent,
.design,
.address,
.siteAssembly
]
let steps: [SiteCreationStep] = {
if RemoteFeatureFlag.plansInSiteCreation.enabled() {
return [
.intent,
.design,
.address,
.plan,
.siteAssembly
]
} else {
return [
.intent,
.design,
.address,
.siteAssembly
]
}
}()

private lazy var wizard: SiteCreationWizard = {
return SiteCreationWizard(steps: steps.map { initStep($0) })
Expand Down Expand Up @@ -43,6 +55,8 @@ final class SiteCreationWizardLauncher {
case .address:
let addressService = DomainsServiceAdapter(coreDataStack: ContextManager.shared)
return WebAddressStep(creator: self.creator, service: addressService)
case .plan:
return PlanStep(creator: self.creator)
case .design:
// we call dropLast to remove .siteAssembly
let isLastStep = steps.dropLast().last == .design
Expand Down
Loading