@@ -17,12 +17,15 @@ import class Yosemite.PluginsService
1717
1818/// Represents the reasons why a site may be ineligible for POS.
1919enum POSIneligibleReason : Equatable {
20+ case notTablet
2021 case unsupportedIOSVersion
2122 case unsupportedWooCommerceVersion( minimumVersion: String )
2223 case siteSettingsNotAvailable
2324 case wooCommercePluginNotFound
25+ case featureFlagDisabled
2426 case featureSwitchDisabled
2527 case featureSwitchSyncFailure
28+ case unsupportedCountry( supportedCountries: [ CountryCode ] )
2629 case unsupportedCurrency( supportedCurrencies: [ CurrencyCode ] )
2730 case selfDeallocated
2831}
@@ -42,29 +45,10 @@ protocol POSEntryPointEligibilityCheckerProtocol {
4245 func checkEligibility( ) async -> POSEligibilityState
4346}
4447
45- /// Legacy enum containing POS invisible reasons + POSIneligibleReason cases for i1.
46- private enum LegacyPOSIneligibleReason : Equatable {
47- case notTablet
48- case unsupportedIOSVersion
49- case unsupportedWooCommerceVersion( minimumVersion: String )
50- case siteSettingsNotAvailable
51- case wooCommercePluginNotFound
52- case featureFlagDisabled
53- case featureSwitchDisabled
54- case featureSwitchSyncFailure
55- case unsupportedCountry( supportedCountries: [ CountryCode ] )
56- case unsupportedCurrency( supportedCurrencies: [ CurrencyCode ] )
57- case selfDeallocated
58- }
59-
60- /// Legacy POS eligibility state for i1.
61- private enum LegacyPOSEligibilityState : Equatable {
62- case eligible
63- case ineligible( reason: LegacyPOSIneligibleReason )
64- }
65-
66- /// POS tab eligibility checker for i1. Will be replaced by `POSTabEligibilityCheckerI2` when removing `pointOfSaleAsATabi2` feature flag.
6748final class POSTabEligibilityChecker : POSEntryPointEligibilityCheckerProtocol {
49+ private var siteSettingsEligibility : POSEligibilityState ?
50+ private var featureFlagEligibility : POSEligibilityState ?
51+
6852 private let siteID : Int64
6953 private let userInterfaceIdiom : UIUserInterfaceIdiom
7054 private let siteSettings : SelectedSiteSettingsProtocol
@@ -96,10 +80,6 @@ final class POSTabEligibilityChecker: POSEntryPointEligibilityCheckerProtocol {
9680
9781 /// Determines whether the POS entry point can be shown based on the selected store and feature gates.
9882 func checkEligibility( ) async -> POSEligibilityState {
99- . eligible
100- }
101-
102- private func checkI1Eligibility( ) async -> LegacyPOSEligibilityState {
10383 switch checkDeviceEligibility ( ) {
10484 case . eligible:
10585 break
@@ -138,13 +118,17 @@ final class POSTabEligibilityChecker: POSEntryPointEligibilityCheckerProtocol {
138118
139119 /// Checks the final visibility of the POS tab.
140120 func checkVisibility( ) async -> Bool {
141- let eligibility = await checkI1Eligibility ( )
142- return eligibility == . eligible
121+ if featureFlagService. isFeatureFlagEnabled ( . pointOfSaleAsATabi2) {
122+ return await checkVisibilityBasedOnCountryAndRemoteFeatureFlag ( )
123+ } else {
124+ let eligibility = await checkEligibility ( )
125+ return eligibility == . eligible
126+ }
143127 }
144128}
145129
146130private extension POSTabEligibilityChecker {
147- func checkDeviceEligibility( ) -> LegacyPOSEligibilityState {
131+ func checkDeviceEligibility( ) -> POSEligibilityState {
148132 guard #available( iOS 17 . 0 , * ) else {
149133 return . ineligible( reason: . unsupportedIOSVersion)
150134 }
@@ -155,12 +139,41 @@ private extension POSTabEligibilityChecker {
155139
156140 return . eligible
157141 }
142+
143+ func checkVisibilityBasedOnCountryAndRemoteFeatureFlag( ) async -> Bool {
144+ guard checkDeviceEligibility ( ) == . eligible else {
145+ return false
146+ }
147+
148+ async let siteSettingsEligibility = checkSiteSettingsEligibility ( )
149+ async let featureFlagEligibility = checkRemoteFeatureEligibility ( )
150+
151+ self . siteSettingsEligibility = await siteSettingsEligibility
152+ switch await siteSettingsEligibility {
153+ case . eligible:
154+ break
155+ case let . ineligible( reason) :
156+ if case . unsupportedCurrency = reason {
157+ break
158+ } else {
159+ return false
160+ }
161+ }
162+
163+ self. featureFlagEligibility = await featureFlagEligibility
164+ switch await featureFlagEligibility {
165+ case . eligible:
166+ return true
167+ case . ineligible:
168+ return false
169+ }
170+ }
158171}
159172
160173// MARK: - WC Plugin Related Eligibility Check
161174
162175private extension POSTabEligibilityChecker {
163- func checkPluginEligibility( ) async -> LegacyPOSEligibilityState {
176+ func checkPluginEligibility( ) async -> POSEligibilityState {
164177 let wcPlugin = await fetchWooCommercePlugin ( siteID: siteID)
165178
166179 guard VersionHelpers . isVersionSupported ( version: wcPlugin. version,
@@ -186,7 +199,7 @@ private extension POSTabEligibilityChecker {
186199 }
187200
188201 @MainActor
189- func checkFeatureSwitchEnabled( siteID: Int64 ) async -> LegacyPOSEligibilityState {
202+ func checkFeatureSwitchEnabled( siteID: Int64 ) async -> POSEligibilityState {
190203 await withCheckedContinuation { [ weak self] continuation in
191204 guard let self else {
192205 return continuation. resume ( returning: . ineligible( reason: . selfDeallocated) )
@@ -207,7 +220,11 @@ private extension POSTabEligibilityChecker {
207220// MARK: - Site Settings Related Eligibility Check
208221
209222private extension POSTabEligibilityChecker {
210- func checkSiteSettingsEligibility( ) async -> LegacyPOSEligibilityState {
223+ func checkSiteSettingsEligibility( ) async -> POSEligibilityState {
224+ if let siteSettingsEligibility {
225+ return siteSettingsEligibility
226+ }
227+
211228 // Waits for the first site settings that matches the given site ID.
212229 let siteSettings = await waitForSiteSettingsRefresh ( )
213230 guard siteSettings. isNotEmpty else {
@@ -232,7 +249,7 @@ private extension POSTabEligibilityChecker {
232249 return [ ]
233250 }
234251
235- func isEligibleFromCountryAndCurrencyCode( countryCode: CountryCode , currencyCode: CurrencyCode ) -> LegacyPOSEligibilityState {
252+ func isEligibleFromCountryAndCurrencyCode( countryCode: CountryCode , currencyCode: CurrencyCode ) -> POSEligibilityState {
236253 let supportedCountries : [ CountryCode ] = [ . US, . GB]
237254 let supportedCurrencies : [ CountryCode : [ CurrencyCode ] ] = [ . US: [ . USD] ,
238255 . GB: [ . GBP] ]
@@ -254,10 +271,14 @@ private extension POSTabEligibilityChecker {
254271
255272private extension POSTabEligibilityChecker {
256273 @MainActor
257- func checkRemoteFeatureEligibility( ) async -> LegacyPOSEligibilityState {
274+ func checkRemoteFeatureEligibility( ) async -> POSEligibilityState {
275+ if let featureFlagEligibility {
276+ return featureFlagEligibility
277+ }
278+
258279 // Only whitelisted accounts in WPCOM have the Point of Sale remote feature flag enabled. These can be found at D159901-code
259280 // If the account is whitelisted, then the remote value takes preference over the local feature flag configuration
260- await withCheckedContinuation { [ weak self] continuation in
281+ return await withCheckedContinuation { [ weak self] continuation in
261282 guard let self else {
262283 return continuation. resume ( returning: . ineligible( reason: . selfDeallocated) )
263284 }
0 commit comments