🐛 Fixed stupid app state updated twice

This commit is contained in:
2025-10-30 23:58:05 +08:00
parent 402bb3fe04
commit 3edcdd72af
4 changed files with 42 additions and 23 deletions

View File

@@ -455,17 +455,19 @@ class NetworkService {
} }
func connectWebSocket(token: String, serverUrl: String) { func connectWebSocket(token: String, serverUrl: String) {
connectLock.lock()
defer { connectLock.unlock() }
webSocketQueue.async { [weak self] in webSocketQueue.async { [weak self] in
guard let self = self else { return } guard let self = self else { return }
self.connectLock.lock()
defer { self.connectLock.unlock() }
// Prevent redundant connection attempts // Prevent redundant connection attempts
if self.currentConnectionState == .connecting || self.currentConnectionState == .connected { if self.currentConnectionState == .connecting || self.currentConnectionState == .connected {
print("[WebSocket] Already connecting or connected, ignoring new connect request.") print("[WebSocket] Already connecting or connected, ignoring new connect request.")
return return
} }
self.currentConnectionState = .connecting
// Ensure any existing task is cancelled before starting a new one // Ensure any existing task is cancelled before starting a new one
self.webSocketTask?.cancel(with: .goingAway, reason: nil) self.webSocketTask?.cancel(with: .goingAway, reason: nil)
@@ -490,13 +492,12 @@ class NetworkService {
return return
} }
print("[WebSocket] Trying connecting to \(url)")
self.currentConnectionState = .connecting
var request = URLRequest(url: url) var request = URLRequest(url: url)
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization") request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.addValue("application/json", forHTTPHeaderField: "Content-Type")
print("[WebSocket] Trying connecting to \(url)")
self.webSocketTask = self.session.webSocketTask(with: request) self.webSocketTask = self.session.webSocketTask(with: request)
self.webSocketTask?.resume() self.webSocketTask?.resume()

View File

@@ -19,22 +19,34 @@ class AppState: ObservableObject {
let networkService = NetworkService() let networkService = NetworkService()
private var wcService = WatchConnectivityService() private var wcService = WatchConnectivityService()
private var cancellables = Set<AnyCancellable>() private var cancellables = Set<AnyCancellable>()
private var hasAttemptedConnection = false
init() { init() {
wcService.$token.combineLatest(wcService.$serverUrl) wcService.$token.combineLatest(wcService.$serverUrl, wcService.$isFetched)
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sink { [weak self] token, serverUrl in .sink { [weak self] (token: String?, serverUrl: String?, isFetched: Bool?) in
self?.token = token guard let self = self else { return }
self?.serverUrl = serverUrl
if let token = token, let serverUrl = serverUrl { self.token = token
self?.isReady = true self.serverUrl = serverUrl
// Auto-connect WebSocket here
self?.networkService.connectWebSocket(token: token, serverUrl: serverUrl) if let token = token, let serverUrl = serverUrl, !token.isEmpty, !serverUrl.isEmpty {
} else { self.isReady = true
self?.isReady = false // Only connect once when we have valid credentials and tried fetch from phone
// Disconnect WebSocket if token or serverUrl become nil if !self.hasAttemptedConnection && isFetched == true {
self?.networkService.disconnectWebSocket() self.hasAttemptedConnection = true
} } print("[AppState] Connecting WebSocket to server: \(serverUrl)")
self.networkService.connectWebSocket(token: token, serverUrl: serverUrl)
}
} else {
self.isReady = false
if self.hasAttemptedConnection {
self.hasAttemptedConnection = false
// Disconnect WebSocket if token or serverUrl become invalid
self.networkService.disconnectWebSocket()
}
}
}
.store(in: &cancellables) .store(in: &cancellables)
} }

View File

@@ -14,6 +14,7 @@ import Combine
class WatchConnectivityService: NSObject, WCSessionDelegate, ObservableObject { class WatchConnectivityService: NSObject, WCSessionDelegate, ObservableObject {
@Published var token: String? @Published var token: String?
@Published var serverUrl: String? @Published var serverUrl: String?
@Published var isFetched: Bool?
private let session: WCSession private let session: WCSession
private let userDefaults = UserDefaults.standard private let userDefaults = UserDefaults.standard
@@ -30,6 +31,7 @@ class WatchConnectivityService: NSObject, WCSessionDelegate, ObservableObject {
// Load cached data // Load cached data
self.token = userDefaults.string(forKey: tokenKey) self.token = userDefaults.string(forKey: tokenKey)
self.serverUrl = userDefaults.string(forKey: serverUrlKey) self.serverUrl = userDefaults.string(forKey: serverUrlKey)
self.isFetched = false
} }
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
@@ -58,7 +60,13 @@ class WatchConnectivityService: NSObject, WCSessionDelegate, ObservableObject {
} }
func requestDataFromPhone() { func requestDataFromPhone() {
if self.isFetched == true {
print("[watchOS] Skipped fetch from phone due to tried.")
return
}
guard session.isReachable else { guard session.isReachable else {
self.isFetched = true
print("[watchOS] Phone is not reachable") print("[watchOS] Phone is not reachable")
return return
} }
@@ -68,6 +76,7 @@ class WatchConnectivityService: NSObject, WCSessionDelegate, ObservableObject {
guard let self = self else { return } guard let self = self else { return }
print("[watchOS] Received reply: \(response)") print("[watchOS] Received reply: \(response)")
DispatchQueue.main.async { DispatchQueue.main.async {
self.isFetched = true
if let token = response["token"] as? String { if let token = response["token"] as? String {
self.token = token self.token = token
self.userDefaults.set(token, forKey: self.tokenKey) self.userDefaults.set(token, forKey: self.tokenKey)

View File

@@ -49,9 +49,6 @@ struct ExploreView: View {
.environmentObject(appState) .environmentObject(appState)
} else { } else {
ProgressView { Text("Connecting to phone...") } ProgressView { Text("Connecting to phone...") }
.onAppear {
appState.requestData()
}
} }
} }
.sheet(isPresented: $isComposing) { .sheet(isPresented: $isComposing) {