Skip to content

Commit e4473e0

Browse files
committed
Observe all loaded products at once
1 parent c6a75f1 commit e4473e0

File tree

1 file changed

+24
-22
lines changed

1 file changed

+24
-22
lines changed

WooCommerce/Classes/ViewRelated/Dashboard/TopPerformers/TopPerformersDashboardViewModel.swift

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ final class TopPerformersDashboardViewModel: ObservableObject {
3131

3232
private var resultsController: ResultsController<StorageTopEarnerStats>?
3333

34-
// periphery:ignore - keep a strong reference to listen to changes of a product
35-
private var entityListener: EntityListener<Product>?
34+
// Map of product IDs and their listeners
35+
private var entityListeners: [Int64: EntityListener<Product>] = [:]
36+
37+
private var hasProductChanges = PassthroughSubject<Void, Never>()
3638

3739
private var currentDate: Date {
3840
Date()
@@ -86,7 +88,6 @@ final class TopPerformersDashboardViewModel: ObservableObject {
8688
self.usageTracksEventEmitter = usageTracksEventEmitter
8789

8890
observeSyncingCompletion()
89-
observeSelectedItem()
9091

9192
Task { @MainActor in
9293
self.timeRange = await loadLastTimeRange() ?? .today
@@ -219,40 +220,40 @@ private extension TopPerformersDashboardViewModel {
219220
.store(in: &subscriptions)
220221
}
221222

222-
func observeSelectedItem() {
223-
$selectedItem
224-
.scan((nil, nil)) { (previous: (current: TopEarnerStatsItem?,
225-
previous: TopEarnerStatsItem?),
226-
newValue: TopEarnerStatsItem?) in
227-
return (current: newValue, previous: previous.current)
223+
func observeProducts(ids: [Int64]) {
224+
entityListeners = [:]
225+
for id in ids {
226+
if let listener = createProductEntityListener(id: id) {
227+
entityListeners[id] = listener
228228
}
229-
.sink { [weak self] (newItem, oldItem) in
230-
guard let newItem, oldItem == nil else {
231-
self?.entityListener = nil
232-
return
229+
}
230+
231+
hasProductChanges
232+
.debounce(for: .milliseconds(300), scheduler: DispatchQueue.main)
233+
.sink { [weak self] in
234+
Task {
235+
await self?.reloadDataIfNeeded(forceRefresh: true)
233236
}
234-
self?.observeOpenedProductIfPossible(id: newItem.productID)
235237
}
236238
.store(in: &subscriptions)
237239
}
238240

239-
func observeOpenedProductIfPossible(id: Int64) {
241+
func createProductEntityListener(id: Int64) -> EntityListener<Product>? {
240242
guard var product = storageManager.viewStorage.loadProduct(siteID: siteID, productID: id)?.toReadOnly() else {
241-
return
243+
return nil
242244
}
243245
let entityListener = EntityListener(storageManager: ServiceLocator.storageManager, readOnlyEntity: product)
244246
entityListener.onUpsert = { [weak self] updatedProduct in
245247
// reload stats if there are changes to product
246-
guard updatedProduct.name != product.name ||
247-
updatedProduct.imageURL != product.imageURL else {
248+
guard let self,
249+
updatedProduct.name != product.name ||
250+
updatedProduct.imageURL != product.imageURL else {
248251
return
249252
}
250253
product = updatedProduct
251-
Task {
252-
await self?.reloadDataIfNeeded(forceRefresh: true)
253-
}
254+
hasProductChanges.send(())
254255
}
255-
self.entityListener = entityListener
256+
return entityListener
256257
}
257258

258259
@MainActor
@@ -305,6 +306,7 @@ private extension TopPerformersDashboardViewModel {
305306
return periodViewModel.update(state: .loaded(rows: []))
306307
}
307308
periodViewModel.update(state: .loaded(rows: items))
309+
observeProducts(ids: items.map { $0.productID })
308310
}
309311

310312
func createResultsController(timeRange: StatsTimeRangeV4) -> ResultsController<StorageTopEarnerStats> {

0 commit comments

Comments
 (0)