Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import UIKit
import Yosemite
import WooFoundation
import protocol Storage.StorageManagerType
import class Networking.ProductsRemote

/// Controls navigation for the flow to add a product given a navigation controller.
/// This class is not meant to be retained so that its life cycle is throughout the navigation. Example usage:
Expand Down Expand Up @@ -81,6 +82,8 @@ private extension AddProductCoordinator {
isProductCreationTypeEnabled && productsResultsController.numberOfObjects < 3
}

/// Presents a bottom sheet for users to choose if they want a create a product manually or via a template.
///
func presentProductCreationTypeBottomSheet() {
let title = NSLocalizedString("How do you want to start?",
comment: "Message title of bottom sheet for selecting a template or manual product")
Expand All @@ -93,14 +96,21 @@ private extension AddProductCoordinator {
productTypesListPresenter.show(from: navigationController, sourceView: sourceView, sourceBarButtonItem: sourceBarButtonItem, arrowDirections: .any)
}

/// Presents a bottom sheet for users to choose if what kind of product they want to create.
///
func presentProductTypeBottomSheet(creationType: ProductCreationType) {
let title = NSLocalizedString("Select a product type",
comment: "Message title of bottom sheet for selecting a product type to create a product")
let viewProperties = BottomSheetListSelectorViewProperties(title: title)
let command = ProductTypeBottomSheetListSelectorCommand(selected: nil) { selectedBottomSheetProductType in
ServiceLocator.analytics.track(.addProductTypeSelected, withProperties: ["product_type": selectedBottomSheetProductType.productType.rawValue])
self.navigationController.dismiss(animated: true) {
self.presentProductForm(bottomSheetProductType: selectedBottomSheetProductType)
switch creationType {
case .manual:
self.presentProductForm(bottomSheetProductType: selectedBottomSheetProductType)
case .template:
self.createAndPresentTemplate(productType: selectedBottomSheetProductType)
}
}
}

Expand All @@ -120,15 +130,60 @@ private extension AddProductCoordinator {
arrowDirections: .any)
}

/// Creates & Fetches a template product.
/// If success: Navigates to the product.
/// If failure: Shows an error notice
///
func createAndPresentTemplate(productType: BottomSheetProductType) {
guard let template = Self.templateType(from: productType) else {
DDLogError("⛔️ Product Type: \(productType) not supported as a template.")
return presentErrorNotice()
}

// Loading ViewController while the product is being created
let loadingTitle = NSLocalizedString("Creating Template Product...", comment: "Loading text while creating a product from a template")
let viewProperties = InProgressViewProperties(title: loadingTitle, message: "")
let inProgressViewController = InProgressViewController(viewProperties: viewProperties)

let action = ProductAction.createTemplateProduct(siteID: siteID, template: template) { result in

// Dismiss the loader
inProgressViewController.dismiss(animated: true)

switch result {
case .success(let product):
self.presentProduct(product, formType: .edit) // We need to strongly capture `self` because no one is retaining `AddProductCoordinator`.

case .failure(let error):
// Log error and inform the user
DDLogError("⛔️ There was an error creating the template product: \(error)")
self.presentErrorNotice()
}
}

ServiceLocator.stores.dispatch(action)

// Present loader right after the creation action is dispatched.
inProgressViewController.modalPresentationStyle = .overCurrentContext
self.navigationController.tabBarController?.present(inProgressViewController, animated: true, completion: nil)
}

/// Presents a new product based on the provided bottom sheet type.
///
func presentProductForm(bottomSheetProductType: BottomSheetProductType) {
guard let product = ProductFactory().createNewProduct(type: bottomSheetProductType.productType,
isVirtual: bottomSheetProductType.isVirtual,
siteID: siteID) else {
assertionFailure("Unable to create product of type: \(bottomSheetProductType)")
return
}
let model = EditableProductModel(product: product)
presentProduct(product, formType: .add)
}

/// Presents a product onto the current navigation stack.
///
func presentProduct(_ product: Product, formType: ProductFormType) {
let model = EditableProductModel(product: product)
let currencyCode = ServiceLocator.currencySettings.currencyCode
let currency = ServiceLocator.currencySettings.symbol(from: currencyCode)
let productImageActionHandler = productImageUploader
Expand All @@ -137,7 +192,7 @@ private extension AddProductCoordinator {
isLocalID: true),
originalStatuses: model.imageStatuses)
let viewModel = ProductFormViewModel(product: model,
formType: .add,
formType: formType,
productImageActionHandler: productImageActionHandler)
let viewController = ProductFormViewController(viewModel: viewModel,
eventLogger: ProductFormEventLogger(),
Expand All @@ -148,4 +203,30 @@ private extension AddProductCoordinator {
viewController.hidesBottomBarWhenPushed = true
navigationController.pushViewController(viewController, animated: true)
}

/// Converts a `BottomSheetProductType` type to a `ProductsRemote.TemplateType` template type.
/// Returns `nil` if the `BottomSheetProductType` is not suported or does not exists.
///
static func templateType(from productType: BottomSheetProductType) -> ProductsRemote.TemplateType? {
switch productType {
case .simple(let isVirtual):
if isVirtual {
return .digital
} else {
return .physical
}
case .variable:
return .variable
default:
return nil
}
}

/// Presents an general error notice using the system notice presenter.
///
private func presentErrorNotice() {
let notice = Notice(title: NSLocalizedString("There was a problem creating the template product.",
comment: "Title for the error notice when creating a template product"))
ServiceLocator.noticePresenter.enqueue(notice: notice)
}
}
2 changes: 2 additions & 0 deletions WooCommerce/WooCommerce.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11644,6 +11644,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer";
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = PZYM8XX95Q;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = PZYM8XX95Q;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist";
INFOPLIST_PREFIX_HEADER = DerivedSources/InfoPlist.h;
Expand All @@ -11658,6 +11659,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
PROVISIONING_PROFILE_SPECIFIER = "WooCommerce Development";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "WooCommerce Development";
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "WooCommerce Catalyst Development";
SUPPORTS_MACCATALYST = NO;
SWIFT_VERSION = 5.0;
Expand Down