@@ -4,6 +4,10 @@ import enum Networking.DotcomError
44import enum Storage. StatsVersion
55import protocol Experiments. FeatureFlagService
66
7+ private enum ProductsOnboardingSyncingError : Error {
8+ case noContentToShow // there is no content to show, because the site is not eligible, it was already shown, or other reason
9+ }
10+
711/// Syncs data for dashboard stats UI and determines the state of the dashboard UI based on stats version.
812final class DashboardViewModel {
913 /// Stats v4 is shown by default, then falls back to v3 if store stats are unavailable.
@@ -20,13 +24,15 @@ final class DashboardViewModel {
2024 private let stores : StoresManager
2125 private let featureFlagService : FeatureFlagService
2226 private let analytics : Analytics
27+ private let justInTimeMessagesManager : JustInTimeMessagesProvider
2328
2429 init ( stores: StoresManager = ServiceLocator . stores,
2530 featureFlags: FeatureFlagService = ServiceLocator . featureFlagService,
2631 analytics: Analytics = ServiceLocator . analytics) {
2732 self . stores = stores
2833 self . featureFlagService = featureFlags
2934 self . analytics = analytics
35+ self . justInTimeMessagesManager = JustInTimeMessagesProvider ( stores: stores, analytics: analytics)
3036 }
3137
3238 /// Syncs store stats for dashboard UI.
@@ -116,37 +122,46 @@ final class DashboardViewModel {
116122
117123 /// Checks for announcements to show on the dashboard
118124 ///
119- func syncAnnouncements( for siteID: Int64 ) {
120- syncProductsOnboarding ( for: siteID) { [ weak self] in
121- self ? . syncJustInTimeMessages ( for: siteID)
125+ func syncAnnouncements( for siteID: Int64 ) async {
126+ // For now, products onboarding takes precedence over Just In Time Messages,
127+ // so we can stop if there is an onboarding announcement to display.
128+ // This should be revisited when either onboarding or JITMs are expanded. See: pe5pgL-11B-p2
129+ do {
130+ try await syncProductsOnboarding ( for: siteID)
131+ } catch {
132+ await syncJustInTimeMessages ( for: siteID)
122133 }
123134 }
124135
125- /// Checks if a store is eligible for products onboarding and prepares the onboarding announcement if needed.
136+ /// Checks if a store is eligible for products onboarding -returning error otherwise- and prepares the onboarding announcement if needed.
126137 ///
127- private func syncProductsOnboarding( for siteID: Int64 , onCompletion: @escaping ( ) -> Void ) {
128- let action = ProductAction . checkProductsOnboardingEligibility ( siteID: siteID) { [ weak self] result in
129- switch result {
130- case . success( let isEligible) :
131- if isEligible {
132- ServiceLocator . analytics. track ( event: . ProductsOnboarding. storeIsEligible ( ) )
138+ private func syncProductsOnboarding( for siteID: Int64 ) async throws {
139+ try await withCheckedThrowingContinuation { [ weak self] continuation in
140+ let action = ProductAction . checkProductsOnboardingEligibility ( siteID: siteID) { [ weak self] result in
141+ switch result {
142+ case . success( let isEligible) :
143+ if isEligible {
144+ ServiceLocator . analytics. track ( event: . ProductsOnboarding. storeIsEligible ( ) )
133145
134- self ? . setProductsOnboardingBannerIfNeeded ( )
135- }
146+ self ? . setProductsOnboardingBannerIfNeeded ( )
147+ }
148+
149+ if self ? . announcementViewModel is ProductsOnboardingAnnouncementCardViewModel {
150+ continuation. resume ( returning: ( ( ) ) )
151+ } else {
152+ continuation. resume ( throwing: ProductsOnboardingSyncingError . noContentToShow)
153+ }
136154
137- // For now, products onboarding takes precedence over Just In Time Messages,
138- // so we can stop if there is an onboarding announcement to display.
139- // This should be revisited when either onboarding or JITMs are expanded. See: pe5pgL-11B-p2
140- if self ? . announcementViewModel is ProductsOnboardingAnnouncementCardViewModel {
141- return
155+ case . failure( let error) :
156+ DDLogError ( " ⛔️ Dashboard — Error checking products onboarding eligibility: \( error) " )
157+ continuation. resume ( throwing: error)
142158 }
143- onCompletion ( )
144- case . failure ( let error ) :
145- DDLogError ( " ⛔️ Dashboard — Error checking products onboarding eligibility: \( error ) " )
146- onCompletion ( )
159+ }
160+
161+ Task { @ MainActor in
162+ stores . dispatch ( action )
147163 }
148164 }
149- stores. dispatch ( action)
150165 }
151166
152167 /// Sets the view model for the products onboarding banner if the user hasn't dismissed it before.
@@ -166,39 +181,14 @@ final class DashboardViewModel {
166181
167182 /// Checks for Just In Time Messages and prepares the announcement if needed.
168183 ///
169- private func syncJustInTimeMessages( for siteID: Int64 ) {
184+ private func syncJustInTimeMessages( for siteID: Int64 ) async {
170185 guard featureFlagService. isFeatureFlagEnabled ( . justInTimeMessagesOnDashboard) else {
171186 return
172187 }
173188
174- let action = JustInTimeMessageAction . loadMessage (
175- siteID: siteID,
176- screen: Constants . dashboardScreenName,
177- hook: . adminNotices) { [ weak self] result in
178- guard let self = self else { return }
179- switch result {
180- case let . success( messages) :
181- guard let message = messages. first else {
182- self . announcementViewModel = nil
183- return
184- }
185- self . analytics. track ( event:
186- . JustInTimeMessage. fetchSuccess ( source: Constants . dashboardScreenName,
187- messageID: message. messageID,
188- count: Int64 ( messages. count) ) )
189- let viewModel = JustInTimeMessageAnnouncementCardViewModel (
190- justInTimeMessage: message,
191- screenName: Constants . dashboardScreenName,
192- siteID: siteID)
193- self . announcementViewModel = viewModel
194- viewModel. $showWebViewSheet. assign ( to: & self . $showWebViewSheet)
195- case let . failure( error) :
196- self . analytics. track ( event:
197- . JustInTimeMessage. fetchFailure ( source: Constants . dashboardScreenName,
198- error: error) )
199- }
200- }
201- stores. dispatch ( action)
189+ let viewModel = try ? await justInTimeMessagesManager. loadMessage ( for: . dashboard, siteID: siteID)
190+ viewModel? . $showWebViewSheet. assign ( to: & self . $showWebViewSheet)
191+ announcementViewModel = viewModel
202192 }
203193}
204194
0 commit comments