fix(apple): Avoid getting stuck at the "load resources" view (#4336)

This was a race condition that was covered up by the long connecting
time of the old tunnel, and is now more prevalent because we connect
much more quickly.

The issue was that we respond to changes in the tunnel's status and
resource list separately, which can cause an issue where the view moved
to the `connected` state before the resource list is initialized. Since
those vars don't get updated after that, the view gets stuck in that
state.

This PR fixes that by combining those handlers into a single one that
responds to either so we'll end up at a view that's populated and
connected.
This commit is contained in:
Jamil
2024-03-27 07:53:32 -07:00
committed by GitHub
parent 6e7f2c98cd
commit 6d290d8da6

View File

@@ -15,6 +15,7 @@ import SwiftUI
final class MainViewModel: ObservableObject {
private let logger: AppLogger
private var cancellables: Set<AnyCancellable> = []
let tunnelStore: TunnelStore
@Dependency(\.mainQueue) private var mainQueue
@@ -24,33 +25,32 @@ import SwiftUI
init(tunnelStore: TunnelStore, logger: AppLogger) {
self.tunnelStore = tunnelStore
self.logger = logger
setupObservers()
}
private func setupObservers() {
tunnelStore.$status
.receive(on: mainQueue)
.sink { [weak self] status in
guard let self = self else { return }
if status == .connected {
self.tunnelStore.beginUpdatingResources()
} else {
self.tunnelStore.endUpdatingResources()
}
}
.store(in: &cancellables)
tunnelStore.$resourceListJSON
.receive(on: mainQueue)
.sink { [weak self] json in
guard let self = self,
let json = json,
let data = json.data(using: .utf8)
else { return }
Publishers.CombineLatest(
tunnelStore.$status,
tunnelStore.$resourceListJSON
)
.receive(on: mainQueue)
.sink(receiveValue: { [weak self] status, json in
guard let self = self else { return }
if let json = json,
let data = json.data(using: .utf8)
{
resources = try? JSONDecoder().decode([Resource].self, from: data)
}
.store(in: &cancellables)
if status == .connected {
self.tunnelStore.beginUpdatingResources()
} else {
self.tunnelStore.endUpdatingResources()
}
})
.store(in: &cancellables)
}
func signOutButtonTapped() {