Skip to content

Commit d402747

Browse files
committed
Pass catalog eligibility value when presenting POS
1 parent 8d9a123 commit d402747

File tree

12 files changed

+48
-95
lines changed

12 files changed

+48
-95
lines changed

Modules/Sources/PointOfSale/Controllers/POSEntryPointController.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ public protocol POSEntryPointEligibilityCheckerProtocol {
55
func checkEligibility() async -> POSEligibilityState
66
/// Refreshes the eligibility state based on the provided ineligible reason.
77
func refreshEligibility(ineligibleReason: POSIneligibleReason) async throws -> POSEligibilityState
8-
9-
var localCatalogEligibilityService: POSLocalCatalogEligibilityServiceProtocol? { get }
108
}
119

1210
@Observable final class POSEntryPointController {

Modules/Sources/PointOfSale/Models/PointOfSaleSettingsController.swift

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,7 @@ protocol PointOfSaleSettingsControllerProtocol {
2424

2525
let storeViewModel: POSSettingsStoreViewModel
2626
let localCatalogViewModel: POSSettingsLocalCatalogViewModel?
27-
private let localCatalogEligibilityService: POSLocalCatalogEligibilityServiceProtocol?
28-
29-
var isLocalCatalogEligible: Bool {
30-
localCatalogEligibilityService?.eligibilityState == .eligible
31-
}
27+
let isLocalCatalogEligible: Bool
3228

3329
init(siteID: Int64,
3430
settingsService: PointOfSaleSettingsServiceProtocol,
@@ -38,13 +34,13 @@ protocol PointOfSaleSettingsControllerProtocol {
3834
siteSettings: [SiteSetting],
3935
grdbManager: GRDBManagerProtocol?,
4036
catalogSyncCoordinator: POSCatalogSyncCoordinatorProtocol?,
41-
localCatalogEligibilityService: POSLocalCatalogEligibilityServiceProtocol?) {
37+
isLocalCatalogEligible: Bool) {
4238
self.storeViewModel = POSSettingsStoreViewModel(siteID: siteID,
4339
settingsService: settingsService,
4440
pluginsService: pluginsService,
4541
defaultSiteName: defaultSiteName,
4642
siteSettings: siteSettings)
47-
self.localCatalogEligibilityService = localCatalogEligibilityService
43+
self.isLocalCatalogEligible = isLocalCatalogEligible
4844

4945
if let catalogSyncCoordinator, let grdbManager {
5046
self.localCatalogViewModel = POSSettingsLocalCatalogViewModel(

Modules/Sources/PointOfSale/Presentation/PointOfSaleEntryPointView.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ public struct PointOfSaleEntryPointView: View {
6363
siteSettings: [SiteSetting],
6464
grdbManager: GRDBManagerProtocol?,
6565
catalogSyncCoordinator: POSCatalogSyncCoordinatorProtocol?,
66+
isLocalCatalogEligible: Bool,
6667
services: POSDependencyProviding) {
6768
self.onPointOfSaleModeActiveStateChange = onPointOfSaleModeActiveStateChange
6869

6970
// Use observable controller with GRDB if local catalog is eligible,
7071
// otherwise fall back to standard controller.
71-
let isLocalCatalogEligible = services.localCatalogEligibility.localCatalogEligibilityService?.eligibilityState == .eligible
7272
if isLocalCatalogEligible, let grdbManager = grdbManager {
7373
self.itemsController = PointOfSaleObservableItemsController(
7474
siteID: siteID,
@@ -113,7 +113,7 @@ public struct PointOfSaleEntryPointView: View {
113113
siteSettings: siteSettings,
114114
grdbManager: grdbManager,
115115
catalogSyncCoordinator: catalogSyncCoordinator,
116-
localCatalogEligibilityService: services.localCatalogEligibility.localCatalogEligibilityService)
116+
isLocalCatalogEligible: isLocalCatalogEligible)
117117
self.collectOrderPaymentAnalyticsTracker = collectOrderPaymentAnalyticsTracker
118118
self.searchHistoryService = searchHistoryService
119119
self.popularPurchasableItemsController = PointOfSaleItemsController(
@@ -203,6 +203,7 @@ public struct PointOfSaleEntryPointView: View {
203203
siteSettings: [],
204204
grdbManager: nil,
205205
catalogSyncCoordinator: nil,
206+
isLocalCatalogEligible: false,
206207
services: POSPreviewServices()
207208
)
208209
}

Modules/Sources/PointOfSale/Protocols/POSDependencyProviding.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,6 @@ public protocol POSExternalViewProviding {
6464
func createWCWebView(adminUrl: URL, completion: @escaping () -> Void) -> AnyView
6565
}
6666

67-
/// Protocol that provides local catalog eligibility service for POS
68-
public protocol POSLocalCatalogEligibilityProviding {
69-
var localCatalogEligibilityService: POSLocalCatalogEligibilityServiceProtocol? { get }
70-
}
71-
7267
/// Main protocol that combines all POS dependency providers
7368
/// This enables dependency injection for POS code while maintaining clean separation from ServiceLocator
7469
public protocol POSDependencyProviding {
@@ -78,5 +73,4 @@ public protocol POSDependencyProviding {
7873
var connectivity: POSConnectivityProviding { get }
7974
var externalNavigation: POSExternalNavigationProviding { get }
8075
var externalViews: POSExternalViewProviding { get }
81-
var localCatalogEligibility: POSLocalCatalogEligibilityProviding { get }
8276
}

Modules/Sources/PointOfSale/Utils/POSEnvironmentKeys.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,3 @@ struct EmptyPOSExternalView: POSExternalViewProviding {
160160
}
161161
init() {}
162162
}
163-
164-
struct EmptyPOSLocalCatalogEligibility: POSLocalCatalogEligibilityProviding {
165-
var localCatalogEligibilityService: POSLocalCatalogEligibilityServiceProtocol? = nil
166-
init() {}
167-
}

Modules/Sources/PointOfSale/Utils/PreviewHelpers.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,6 @@ final class PointOfSalePreviewBarcodeScanService: PointOfSaleBarcodeScanServiceP
471471
}
472472

473473
final class PointOfSalePreviewTabEligibilityChecker: POSEntryPointEligibilityCheckerProtocol {
474-
var localCatalogEligibilityService: (any POSLocalCatalogEligibilityServiceProtocol)? = nil
475474
func checkEligibility() async -> POSEligibilityState { .eligible }
476475
func refreshEligibility(ineligibleReason: POSIneligibleReason) async throws -> POSEligibilityState { .eligible }
477476
}
@@ -591,7 +590,6 @@ final class POSPreviewServices: POSDependencyProviding {
591590
var connectivity: POSConnectivityProviding = EmptyPOSConnectivityProvider()
592591
var externalNavigation: POSExternalNavigationProviding = EmptyPOSExternalNavigation()
593592
var externalViews: POSExternalViewProviding = EmptyPOSExternalView()
594-
var localCatalogEligibility: POSLocalCatalogEligibilityProviding = EmptyPOSLocalCatalogEligibility()
595593
}
596594

597595
// MARK: - Preview Catalog Services

Modules/Tests/PointOfSaleTests/Controllers/PointOfSaleSettingsControllerTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ struct PointOfSaleSettingsControllerTests {
2121
siteSettings: [],
2222
grdbManager: nil,
2323
catalogSyncCoordinator: nil,
24-
localCatalogEligibilityService: MockPOSLocalCatalogEligibilityService())
24+
isLocalCatalogEligible: true)
2525

2626
// When
2727
let cardReader = sut.connectedCardReader
@@ -41,7 +41,7 @@ struct PointOfSaleSettingsControllerTests {
4141
siteSettings: [],
4242
grdbManager: nil,
4343
catalogSyncCoordinator: nil,
44-
localCatalogEligibilityService: MockPOSLocalCatalogEligibilityService())
44+
isLocalCatalogEligible: true)
4545

4646
// Initially nil
4747
#expect(sut.connectedCardReader == nil)

Modules/Tests/PointOfSaleTests/Mocks/MockPOSEligibilityChecker.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import Foundation
22
@testable import PointOfSale
33

44
final class MockPOSEligibilityChecker: POSEntryPointEligibilityCheckerProtocol {
5-
var localCatalogEligibilityService: (any POSLocalCatalogEligibilityServiceProtocol)? = nil
65
var initialVisibility: Bool = false
76
var visibility: Bool = false
87
var eligibility: POSEligibilityState = .eligible

WooCommerce/Classes/POS/Adaptors/POSServiceLocatorAdaptor.swift

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,9 @@ import protocol PointOfSale.POSFeatureFlagProviding
1212
import protocol PointOfSale.POSConnectivityProviding
1313
import protocol PointOfSale.POSExternalNavigationProviding
1414
import protocol PointOfSale.POSExternalViewProviding
15-
import protocol PointOfSale.POSLocalCatalogEligibilityProviding
16-
import protocol PointOfSale.POSLocalCatalogEligibilityServiceProtocol
1715

1816
final class POSServiceLocatorAdaptor: POSDependencyProviding {
19-
private let _localCatalogEligibilityService: POSLocalCatalogEligibilityServiceProtocol?
20-
21-
init(localCatalogEligibilityService: POSLocalCatalogEligibilityServiceProtocol?) {
22-
self._localCatalogEligibilityService = localCatalogEligibilityService
17+
init() {
2318
}
2419

2520
var analytics: POSAnalyticsProviding {
@@ -45,10 +40,6 @@ final class POSServiceLocatorAdaptor: POSDependencyProviding {
4540
var externalViews: POSExternalViewProviding {
4641
POSExternalViewAdaptor()
4742
}
48-
49-
var localCatalogEligibility: POSLocalCatalogEligibilityProviding {
50-
POSLocalCatalogEligibilityAdaptor(service: _localCatalogEligibilityService)
51-
}
5243
}
5344

5445
// MARK: - Individual Service Adaptors
@@ -141,11 +132,3 @@ private struct POSExternalViewAdaptor: POSExternalViewProviding {
141132
AnyView(WCSettingsWebView(adminUrl: adminUrl, completion: completion))
142133
}
143134
}
144-
145-
private struct POSLocalCatalogEligibilityAdaptor: POSLocalCatalogEligibilityProviding {
146-
let localCatalogEligibilityService: POSLocalCatalogEligibilityServiceProtocol?
147-
148-
init(service: POSLocalCatalogEligibilityServiceProtocol?) {
149-
self.localCatalogEligibilityService = service
150-
}
151-
}

WooCommerce/Classes/POS/TabBar/POSTabCoordinator.swift

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ final class POSTabCoordinator {
4242
private let pushNotesManager: PushNotesManager
4343
private let eligibilityChecker: POSEntryPointEligibilityCheckerProtocol
4444

45+
/// Local catalog eligibility service - created asynchronously during init
46+
private(set) var localCatalogEligibilityService: POSLocalCatalogEligibilityServiceProtocol?
47+
4548
private lazy var posItemFetchStrategyFactory: PointOfSaleItemFetchStrategyFactory = {
4649
PointOfSaleItemFetchStrategyFactory(siteID: siteID,
4750
credentials: credentials,
@@ -123,6 +126,26 @@ final class POSTabCoordinator {
123126
self.eligibilityChecker = eligibilityChecker
124127

125128
tabContainerController.wrappedController = POSTabViewController()
129+
130+
// Create local catalog eligibility service asynchronously
131+
// Check POS tab eligibility first, then create service with that state
132+
Task { @MainActor [weak self] in
133+
guard let self else { return }
134+
135+
let posEligibility = await eligibilityChecker.checkEligibility()
136+
137+
let service = await POSLocalCatalogEligibilityService(
138+
siteID: siteID,
139+
catalogSizeChecker: POSCatalogSizeChecker(
140+
credentials: credentials,
141+
selectedSite: defaultSitePublisher,
142+
appPasswordSupportState: isAppPasswordSupported
143+
),
144+
posTabEligibilityState: posEligibility
145+
)
146+
147+
self.localCatalogEligibilityService = service
148+
}
126149
}
127150

128151
func onTabSelected() {
@@ -143,35 +166,24 @@ private extension POSTabCoordinator {
143166
Task { @MainActor [weak self] in
144167
guard let self else { return }
145168

146-
// Check local catalog eligibility before initializing infrastructure
147-
// Try to use pre-created service from eligibility checker, otherwise create it now
148-
let localCatalogEligibilityService: POSLocalCatalogEligibilityServiceProtocol
149-
if let preCreatedService = eligibilityChecker.localCatalogEligibilityService {
150-
localCatalogEligibilityService = preCreatedService
169+
// Get local catalog eligibility as bool from service
170+
// Service is created asynchronously in init, might not be ready yet
171+
let isLocalCatalogEligible: Bool
172+
if let service = localCatalogEligibilityService {
173+
// Retry transient failures before using the value
174+
switch service.eligibilityState {
175+
case .ineligible(reason: .catalogSizeCheckFailed), .ineligible(reason: .posTabNotEligible):
176+
await service.refreshEligibilityState()
177+
default:
178+
break
179+
}
180+
isLocalCatalogEligible = service.eligibilityState == .eligible
151181
} else {
152-
// Fallback: assume we're POS eligible and create service
153-
localCatalogEligibilityService = await POSLocalCatalogEligibilityService(
154-
siteID: siteID,
155-
catalogSizeChecker: POSCatalogSizeChecker(credentials: credentials,
156-
selectedSite: defaultSitePublisher,
157-
appPasswordSupportState: isAppPasswordSupported
158-
),
159-
posTabEligibilityState: .eligible
160-
)
182+
// Service not ready yet (rare race condition), assume ineligible
183+
isLocalCatalogEligible = false
161184
}
162185

163-
switch localCatalogEligibilityService.eligibilityState {
164-
case .ineligible(reason: .catalogSizeCheckFailed):
165-
// If we cached a failed check, we can recover by refreshing the value before we next open POS
166-
await localCatalogEligibilityService.refreshEligibilityState()
167-
case .eligible, .ineligible:
168-
break
169-
}
170-
171-
let isLocalCatalogEligible = localCatalogEligibilityService.eligibilityState == .eligible
172-
173-
// Create service adaptor with eligibility service
174-
let serviceAdaptor = POSServiceLocatorAdaptor(localCatalogEligibilityService: localCatalogEligibilityService)
186+
let serviceAdaptor = POSServiceLocatorAdaptor()
175187
let collectPaymentAnalyticsAdaptor = POSCollectOrderPaymentAnalyticsAdaptor(analytics: serviceAdaptor.analytics)
176188
let cardPresentPaymentService = await CardPresentPaymentService(siteID: siteID,
177189
stores: storesManager,
@@ -233,6 +245,7 @@ private extension POSTabCoordinator {
233245
siteSettings: ServiceLocator.selectedSiteSettings.siteSettings,
234246
grdbManager: grdbManager,
235247
catalogSyncCoordinator: catalogSyncCoordinator,
248+
isLocalCatalogEligible: isLocalCatalogEligible,
236249
services: serviceAdaptor
237250
)
238251

0 commit comments

Comments
 (0)