Skip to content

Commit 20dd6ee

Browse files
committed
Refactor ViewModel to expose the showPlaceholderls properties when a sync request is happening
1 parent b057ad7 commit 20dd6ee

File tree

1 file changed

+52
-9
lines changed

1 file changed

+52
-9
lines changed

WooCommerce/Classes/ViewRelated/Orders/Order Details/Address Edit/CountrySelectorViewModel.swift

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ final class CountrySelectorViewModel: FilterListSelectorViewModelable, Observabl
1515
}
1616
}
1717

18+
/// Define if the view should show placeholders instead of the real elements.
19+
///
20+
@Published private(set) var showPlaceholders: Bool = false
21+
1822
/// Command that powers the `ListSelector` view.
1923
///
2024
let command = CountrySelectorCommand(countries: [])
@@ -34,6 +38,10 @@ final class CountrySelectorViewModel: FilterListSelectorViewModelable, Observabl
3438
return ResultsController<StorageCountry>(storageManager: storageManager, sortedBy: [countriesDescriptor])
3539
}()
3640

41+
/// Trigger to sync countries.
42+
///
43+
private let syncCountriesTrigger = PassthroughSubject<Void, Never>()
44+
3745
/// Storage to fetch countries
3846
///
3947
private let storageManager: StorageManagerType
@@ -50,15 +58,17 @@ final class CountrySelectorViewModel: FilterListSelectorViewModelable, Observabl
5058
self.siteID = siteID
5159
self.storageManager = storageManager
5260
self.stores = stores
53-
fetchAndBindCountries()
61+
bindSyncTrigger()
62+
bindStoredCountries()
5463
}
5564
}
5665

5766
// MARK: Helpers
5867
private extension CountrySelectorViewModel {
59-
/// Fetches & Binds countries from storage, If there are no stored countries, sync them from a remote source.
68+
/// Fetches & Binds countries from storage, If there are no stored countries, trigger a sync request.
6069
///
61-
func fetchAndBindCountries() {
70+
func bindStoredCountries() {
71+
6272
// Bind stored countries & command
6373
countriesResultsController.onDidChangeContent = { [weak self] in
6474
guard let self = self else { return }
@@ -68,13 +78,46 @@ private extension CountrySelectorViewModel {
6878
// Initial fetch
6979
try? countriesResultsController.performFetch()
7080

71-
// Reset countries with fetched data or sync countries if needed.
72-
if !countriesResultsController.isEmpty {
73-
command.resetCountries(countriesResultsController.fetchedObjects)
74-
} else {
75-
let action = DataAction.synchronizeCountries(siteID: siteID, onCompletion: { _ in })
76-
stores.dispatch(action)
81+
// Trigger a sync request if there are no countries.
82+
guard !countriesResultsController.isEmpty else {
83+
return syncCountriesTrigger.send()
84+
}
85+
86+
// Reset countries with fetched
87+
command.resetCountries(countriesResultsController.fetchedObjects)
88+
}
89+
90+
/// Sync countries when requested. Defines the `showPlaceholderState` value depending if countries are being synced or not.
91+
///
92+
func bindSyncTrigger() {
93+
syncCountriesTrigger
94+
.handleEvents(receiveOutput: { // Set `showPlaceholders` to `true` before initiating sync.
95+
self.showPlaceholders = true // I could not find a way to assign this using combine operators. :-(
96+
})
97+
.map { // Sync countries
98+
self.makeSyncCountriesFuture()
99+
.replaceError(with: ()) // TODO: Handle errors
100+
}
101+
.switchToLatest()
102+
.map { _ in // Set `showPlaceholders` to `false` after sync is done.
103+
false
104+
}
105+
.assign(to: &$showPlaceholders)
106+
}
107+
108+
/// Creates a publisher that syncs countries into our storage layer.
109+
///
110+
func makeSyncCountriesFuture() -> AnyPublisher<Void, Error> {
111+
Future<Void, Error> { [weak self] promise in
112+
guard let self = self else { return }
113+
114+
let action = DataAction.synchronizeCountries(siteID: self.siteID) { result in
115+
let newResult = result.map { _ in } // Hides the result success type because we don't need it.
116+
promise(newResult)
117+
}
118+
self.stores.dispatch(action)
77119
}
120+
.eraseToAnyPublisher()
78121
}
79122
}
80123

0 commit comments

Comments
 (0)