From 6d290d8da68ba9db3da84cc94a3388128d6d1ef6 Mon Sep 17 00:00:00 2001 From: Jamil Date: Wed, 27 Mar 2024 07:53:32 -0700 Subject: [PATCH] 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. --- .../FirezoneKit/Features/MainView.swift | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/swift/apple/FirezoneKit/Sources/FirezoneKit/Features/MainView.swift b/swift/apple/FirezoneKit/Sources/FirezoneKit/Features/MainView.swift index 712293251..67fe4a051 100644 --- a/swift/apple/FirezoneKit/Sources/FirezoneKit/Features/MainView.swift +++ b/swift/apple/FirezoneKit/Sources/FirezoneKit/Features/MainView.swift @@ -15,6 +15,7 @@ import SwiftUI final class MainViewModel: ObservableObject { private let logger: AppLogger private var cancellables: Set = [] + 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() {