Skip to content

Commit f3c83fd

Browse files
committed
POC put to use
1 parent fc0fa07 commit f3c83fd

File tree

7 files changed

+167
-16
lines changed

7 files changed

+167
-16
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import UIKit
2+
import Yosemite
3+
4+
final class ProductDetailRouter {
5+
enum PresentationStyle {
6+
case undefined
7+
case push
8+
case modal
9+
case contained(containerViewController: () -> UIViewController?)
10+
11+
var asProductFormPresentationStyle: ProductFormPresentationStyle {
12+
switch self {
13+
case .push:
14+
.navigationStack
15+
case .modal:
16+
.navigationStack
17+
case .contained(let containerViewController):
18+
.contained(containerViewController: containerViewController)
19+
case .undefined:
20+
.navigationStack
21+
}
22+
}
23+
}
24+
25+
static var shared = ProductDetailRouter(productURLProvider: ProductURLProvider())
26+
27+
private let productURLProvider: ProductURLProvider
28+
29+
init(productURLProvider: ProductURLProvider) {
30+
self.productURLProvider = productURLProvider
31+
}
32+
33+
func open(product: Product,
34+
presenter: UIViewController,
35+
presentationStyle: PresentationStyle,
36+
onDismiss: (() -> Void)? = nil) {
37+
if product.productType == .booking {
38+
let coordinator = WebViewProductDetailCoordinator(product: product,
39+
productURLProvider: productURLProvider)
40+
coordinator.start(presenter: presenter, onDismiss: onDismiss)
41+
} else {
42+
let coordinator = NativeProductDetailCoordinator(product: product)
43+
coordinator.start(presenter: presenter,
44+
presentationStyle: presentationStyle,
45+
onDismiss: onDismiss)
46+
}
47+
}
48+
49+
func viewController(product: Product,
50+
presentationStyle: PresentationStyle = .undefined,
51+
forceReadOnly: Bool,
52+
onDeleteCompletion: (() -> Void)? = nil) -> UIViewController {
53+
if product.productType == .booking {
54+
let coordinator = WebViewProductDetailCoordinator(product: product,
55+
productURLProvider: productURLProvider)
56+
return coordinator.viewController()
57+
58+
} else {
59+
let coordinator = NativeProductDetailCoordinator(product: product)
60+
return coordinator.viewController(presentationStyle: presentationStyle,
61+
forceReadOnly: forceReadOnly)
62+
}
63+
}
64+
}
65+
66+
final class ProductURLProvider {
67+
func adminURL(for product: Product) -> URL? {
68+
return URL(string: "https://wordpress.com")
69+
}
70+
}
71+
72+
final class WebViewProductDetailCoordinator: NSObject {
73+
private let product: Product
74+
private let productURLProvider: ProductURLProvider
75+
76+
private var onDismiss: (() -> Void)?
77+
78+
init(product: Product, productURLProvider: ProductURLProvider) {
79+
self.product = product
80+
self.productURLProvider = productURLProvider
81+
}
82+
83+
func viewController(onDeleteCompletion: (() -> Void)? = nil) -> UIViewController {
84+
guard let url = productURLProvider.adminURL(for: product) else {
85+
return UIViewController() // TODO: What do we do in this case?
86+
}
87+
88+
let viewModel = WPAdminWebViewModel(title: product.name, initialURL: url)
89+
let webViewController = AuthenticatedWebViewController(viewModel: viewModel)
90+
91+
return webViewController
92+
}
93+
94+
func start(presenter: UIViewController,
95+
onDismiss: (() -> Void)? = nil) {
96+
let webViewController = viewController()
97+
webViewController.navigationItem.leftBarButtonItem = UIBarButtonItem(
98+
barButtonSystemItem: .done,
99+
target: self,
100+
action: #selector(dismissWebView)
101+
)
102+
103+
presenter.navigationController?.present(webViewController, animated: true)
104+
}
105+
106+
@objc
107+
private func dismissWebView() {
108+
let completion = onDismiss
109+
onDismiss = nil
110+
completion?()
111+
}
112+
}
113+
114+
final class NativeProductDetailCoordinator {
115+
private let product: Product
116+
117+
init(product: Product) {
118+
self.product = product
119+
}
120+
121+
func start(presenter: UIViewController,
122+
presentationStyle: ProductDetailRouter.PresentationStyle,
123+
onDismiss: (() -> Void)? = nil) {
124+
125+
}
126+
127+
func viewController(
128+
presentationStyle: ProductDetailRouter.PresentationStyle,
129+
forceReadOnly: Bool,
130+
onDeleteCompletion: (() -> Void)? = nil) -> UIViewController {
131+
return ProductDetailsFactory.productDetails(product: product,
132+
presentationStyle: presentationStyle.asProductFormPresentationStyle,
133+
forceReadOnly: false,
134+
onDeleteCompletion: onDeleteCompletion ?? {})
135+
}
136+
}

WooCommerce/Classes/ViewModels/Order Details/OrderDetailsViewModel.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,6 @@ extension OrderDetailsViewModel {
510510
viewController.present(navController, animated: true, completion: nil)
511511
case .aggregateOrderItem:
512512
let item = dataSource.aggregateOrderItems[indexPath.row]
513-
// TODO: Replace with ProductDetailRouter
514513
let loaderViewController = ProductLoaderViewController(model: .init(aggregateOrderItem: item),
515514
siteID: order.siteID,
516515
forceReadOnly: false)

WooCommerce/Classes/ViewRelated/Products/Product Loader/ProductLoaderViewController.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,10 @@ private extension ProductLoaderViewController {
227227
/// Presents the ProductFormViewController, as a childViewController, for a given Product.
228228
///
229229
func presentProductDetails(for product: Product) {
230-
// TODO: Replace with ProductDetailRouter
231-
ProductDetailsFactory.productDetails(product: product,
232-
presentationStyle: .contained(containerViewController: { [weak self] in self }),
233-
forceReadOnly: forceReadOnly) { [weak self] viewController in
234-
self?.attachProductDetailsChildViewController(viewController)
235-
}
230+
let viewController = ProductDetailRouter.shared.viewController(product: product,
231+
presentationStyle: .contained(containerViewController: { [weak self] in self }),
232+
forceReadOnly: forceReadOnly)
233+
attachProductDetailsChildViewController(viewController)
236234
}
237235

238236
/// Presents the product variation details for a given ProductVariation and its parent Product.

WooCommerce/Classes/ViewRelated/Products/ProductDetailsFactory.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,21 @@ struct ProductDetailsFactory {
2626
onDeleteCompletion: onDeleteCompletion)
2727
onCompletion(vc)
2828
}
29+
30+
static func productDetails(product: Product,
31+
presentationStyle: ProductFormPresentationStyle,
32+
currencySettings: CurrencySettings = ServiceLocator.currencySettings,
33+
forceReadOnly: Bool,
34+
productImageUploader: ProductImageUploaderProtocol = ServiceLocator.productImageUploader,
35+
onDeleteCompletion: @escaping () -> Void = {}) -> UIViewController {
36+
let vc = productDetails(product: product,
37+
presentationStyle: presentationStyle,
38+
currencySettings: currencySettings,
39+
isEditProductsEnabled: forceReadOnly ? false: true,
40+
productImageUploader: productImageUploader,
41+
onDeleteCompletion: onDeleteCompletion)
42+
return vc
43+
}
2944
}
3045

3146
private extension ProductDetailsFactory {

WooCommerce/Classes/ViewRelated/Products/ProductsSplitViewCoordinator.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,15 @@ private extension ProductsSplitViewCoordinator {
122122
}
123123

124124
func showProductForm(product: Product) {
125-
// TODO: Replace with ProductDetailRouter
126-
ProductDetailsFactory.productDetails(product: product,
127-
presentationStyle: .navigationStack,
128-
forceReadOnly: false,
129-
onDeleteCompletion: { [weak self] in
125+
let viewController = ProductDetailRouter.shared.viewController(product: product,
126+
forceReadOnly: false,
127+
onDeleteCompletion: { [weak self] in
130128
self?.onSecondaryProductFormDeletion()
131-
}) { [weak self] viewController in
132-
self?.showSecondaryView(contentType: .productForm(product: product), viewController: viewController, replacesNavigationStack: true)
133-
}
129+
})
130+
131+
showSecondaryView(contentType: .productForm(product: product),
132+
viewController: viewController,
133+
replacesNavigationStack: true)
134134
}
135135

136136
func startProductCreationIfNoUnsavedChanges(sourceView: AddProductCoordinator.SourceView, isFirstProduct: Bool) {

WooCommerce/Classes/ViewRelated/Products/ProductsViewController.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1222,7 +1222,6 @@ private extension ProductsViewController {
12221222
}
12231223
return
12241224
}
1225-
// TODO: Replace with ProductDetailRouter
12261225
navigateToContent(.productForm(product: product))
12271226
}
12281227
}

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,7 @@
13401340
640DA3482E97DE4F00317FB2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 640DA3472E97DE4F00317FB2 /* SceneDelegate.swift */; };
13411341
64D355A52E99048E005F53F7 /* TestingSceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D355A42E99048E005F53F7 /* TestingSceneDelegate.swift */; };
13421342
68051E1E2E9DFE5500228196 /* POSNotificationSchedulerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68051E1D2E9DFE5100228196 /* POSNotificationSchedulerTests.swift */; };
1343+
680BA59A2A4C377900F5559D /* UpgradeViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 680BA5992A4C377900F5559D /* UpgradeViewState.swift */; };
13431344
680E36B52BD8B9B900E8BCEA /* OrderSubscriptionTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 680E36B42BD8B9B900E8BCEA /* OrderSubscriptionTableViewCell.xib */; };
13441345
680E36B72BD8C49F00E8BCEA /* OrderSubscriptionTableViewCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 680E36B62BD8C49F00E8BCEA /* OrderSubscriptionTableViewCellViewModel.swift */; };
13451346
682140AF2E125437005E86AB /* UILabel+SalesChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 682140AE2E125430005E86AB /* UILabel+SalesChannel.swift */; };
@@ -5777,6 +5778,7 @@
57775778
3F0904022D26A40800D8ACCE /* WordPressAuthenticator */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (3F09041C2D26A40800D8ACCE /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = WordPressAuthenticator; sourceTree = "<group>"; };
57785779
3F09040E2D26A40800D8ACCE /* WordPressAuthenticatorTests */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (3FD28D5E2D271391002EBB3D /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = WordPressAuthenticatorTests; sourceTree = "<group>"; };
57795780
3FD9BFBE2E0A2533004A8DC8 /* WooCommerceScreenshots */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (3FD9BFC42E0A2534004A8DC8 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = WooCommerceScreenshots; sourceTree = "<group>"; };
5781+
646A2C682E9FCD7E003A32A1 /* Routing */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Routing; sourceTree = "<group>"; };
57805782
DEDB5D342E7A68950022E5A1 /* Bookings */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Bookings; sourceTree = "<group>"; };
57815783
/* End PBXFileSystemSynchronizedRootGroup section */
57825784

@@ -9727,6 +9729,7 @@
97279729
B56DB3F12049C0B800D4AA8E /* Classes */ = {
97289730
isa = PBXGroup;
97299731
children = (
9732+
646A2C682E9FCD7E003A32A1 /* Routing */,
97309733
640DA3472E97DE4F00317FB2 /* SceneDelegate.swift */,
97319734
DEDB5D342E7A68950022E5A1 /* Bookings */,
97329735
2DCB54F82E6AE8C900621F90 /* CIAB */,
@@ -13248,6 +13251,7 @@
1324813251
);
1324913252
fileSystemSynchronizedGroups = (
1325013253
2D33E6B02DD1453E000C7198 /* WooShippingPaymentMethod */,
13254+
646A2C682E9FCD7E003A32A1 /* Routing */,
1325113255
DEDB5D342E7A68950022E5A1 /* Bookings */,
1325213256
);
1325313257
name = WooCommerce;

0 commit comments

Comments
 (0)