Skip to content

Commit fa75864

Browse files
committed
Improve state observation for refresh control
1 parent bc5c1bf commit fa75864

File tree

4 files changed

+34
-43
lines changed

4 files changed

+34
-43
lines changed

Modules/Sources/PointOfSale/Presentation/Settings/POSSettingsLocalCatalogViewModel.swift

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -96,37 +96,44 @@ final class POSSettingsLocalCatalogViewModel {
9696
var previousState = currentSyncState
9797

9898
while !Task.isCancelled {
99-
// Use withObservationTracking to detect changes
100-
await withCheckedContinuation { (continuation: CheckedContinuation<Void, Never>) in
101-
withObservationTracking {
102-
// Access the observed property to register observation
103-
_ = currentSyncState
104-
} onChange: {
105-
// When state changes, resume the continuation
106-
continuation.resume()
107-
}
108-
}
99+
// Wait for the next state change
100+
await observeNextStateChange()
109101

110-
// Check if state actually changed
102+
// Read the new state after change is detected
111103
let newState = currentSyncState
112-
if newState != previousState {
113-
switch newState {
114-
case .syncCompleted, .syncFailed, .initialSyncFailed:
115-
// Sync finished - clear the refreshing state if it was set
116-
if isRefreshingCatalog {
117-
isRefreshingCatalog = false
118-
// Reload catalog data to show updated info
119-
await loadCatalogData()
120-
}
121-
case .syncStarted, .initialSyncStarted:
122-
// Sync is running - keep spinner active
123-
break
124-
case .syncNeverDone:
125-
// No sync has been done
126-
break
104+
guard newState != previousState else { continue }
105+
106+
// Handle terminal states when user initiated refresh
107+
switch newState {
108+
case .syncCompleted, .syncFailed, .initialSyncFailed:
109+
// Sync finished - clear the refreshing state if it was set
110+
if isRefreshingCatalog {
111+
isRefreshingCatalog = false
112+
// Reload catalog data to show updated info
113+
await loadCatalogData()
127114
}
128-
previousState = newState
115+
case .syncStarted, .initialSyncStarted:
116+
// Sync is running - keep spinner active
117+
break
118+
case .syncNeverDone:
119+
// No sync has been done
120+
break
129121
}
122+
previousState = newState
123+
}
124+
}
125+
}
126+
127+
/// Waits for the next change to the observed sync state.
128+
/// Re-registers observation each time it's called.
129+
private func observeNextStateChange() async {
130+
await withCheckedContinuation { (continuation: CheckedContinuation<Void, Never>) in
131+
withObservationTracking {
132+
// Access the observed property to register observation
133+
_ = currentSyncState
134+
} onChange: {
135+
// When state changes, resume the continuation
136+
continuation.resume()
130137
}
131138
}
132139
}

Modules/Tests/NetworkingTests/Network/BackgroundCatalogDownloadCoordinatorTests.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ struct BackgroundCatalogDownloadCoordinatorTests {
4545

4646
@Test func handleBackgroundSessionEvent_calls_completion_handler_when_no_state() async {
4747
// Given
48-
BackgroundDownloadState.clear() // Ensure no saved state
4948
let sessionIdentifier = "com.woocommerce.pos.catalog.download.999"
5049
let mockDownloader = MockBackgroundDownloader()
5150
let coordinator = BackgroundCatalogDownloadCoordinator(backgroundDownloader: mockDownloader)

Modules/Tests/NetworkingTests/Network/BackgroundDownloadStateTests.swift

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,9 @@ struct BackgroundDownloadStateTests {
2525
let loaded = BackgroundDownloadState.load(for: "test.session.123")
2626
#expect(loaded?.sessionIdentifier == "test.session.123")
2727
#expect(loaded?.siteID == 456)
28-
29-
// Cleanup
30-
BackgroundDownloadState.clear()
3128
}
3229

3330
@Test func load_returns_nil_for_nonexistent_session() {
34-
// Given
35-
BackgroundDownloadState.clear()
36-
3731
// When
3832
let loaded = BackgroundDownloadState.load(for: "nonexistent.session")
3933

@@ -54,9 +48,6 @@ struct BackgroundDownloadStateTests {
5448

5549
// Then
5650
#expect(loaded == nil)
57-
58-
// Cleanup
59-
BackgroundDownloadState.clear()
6051
}
6152

6253
@Test func clear_removes_saved_state() {
@@ -98,8 +89,5 @@ struct BackgroundDownloadStateTests {
9889
#expect(loadedFirst == nil) // First session is overwritten
9990
#expect(loadedSecond?.sessionIdentifier == "session.2")
10091
#expect(loadedSecond?.siteID == 200)
101-
102-
// Cleanup
103-
BackgroundDownloadState.clear()
10492
}
10593
}

Modules/Tests/NetworkingTests/Remote/POSCatalogSyncRemoteTests.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,6 @@ extension POSCatalogSyncRemoteTests {
993993
// Given
994994
let remote = createRemote()
995995
let downloadURL = "https://example.com/catalog.json"
996-
BackgroundDownloadState.clear() // Start clean
997996

998997
let mockFileURL = mockBackgroundDownloader.createMockDownloadFile(withContent: "[]")
999998
mockBackgroundDownloader.mockSuccessfulDownload(fileURL: mockFileURL)
@@ -1023,14 +1022,12 @@ extension POSCatalogSyncRemoteTests {
10231022

10241023
// Cleanup
10251024
try? FileManager.default.removeItem(at: mockFileURL)
1026-
BackgroundDownloadState.clear()
10271025
}
10281026

10291027
@Test func downloadCatalog_clears_state_on_success() async throws {
10301028
// Given
10311029
let remote = createRemote()
10321030
let downloadURL = "https://example.com/catalog.json"
1033-
BackgroundDownloadState.clear() // Start clean
10341031

10351032
// When
10361033
let mockFileURL = mockBackgroundDownloader.createMockDownloadFile(withContent: "[]")

0 commit comments

Comments
 (0)