From 81cf50c40f5bdace566f7bb39adcc9d5fa196336 Mon Sep 17 00:00:00 2001 From: Stephen B <158498287+StephenDev0@users.noreply.github.com> Date: Tue, 16 Dec 2025 13:36:04 -0500 Subject: [PATCH] Fix the ddi bugs --- StikJIT/StikJITApp.swift | 27 +++++++++++++++++++++++++-- StikJIT/Views/HomeView.swift | 18 ++++++++++++++++-- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/StikJIT/StikJITApp.swift b/StikJIT/StikJITApp.swift index 0936cdd..20a7bcc 100644 --- a/StikJIT/StikJITApp.swift +++ b/StikJIT/StikJITApp.swift @@ -233,7 +233,7 @@ class TunnelManager: ObservableObject { } VPNLogger.shared.log("VPN status updated: \(self.tunnelStatus.rawValue)") if connectionStatus == .connected && heartbeatStartPending { - startHeartbeatInBackground() + startHeartbeatInBackground(showErrorUI: heartbeatPendingShowUI) } } } @@ -502,6 +502,7 @@ class DNSChecker: ObservableObject { var pubHeartBeat = false private var heartbeatStartPending = false private var heartbeatStartInProgress = false +private var heartbeatPendingShowUI = true @main struct HeartbeatApp: App { @@ -516,6 +517,7 @@ struct HeartbeatApp: App { @StateObject private var mount = MountingProgress.shared @StateObject private var themeExpansionManager = ThemeExpansionManager() @Environment(\.scenePhase) private var scenePhase // Observe scene lifecycle + @State private var shouldAttemptHeartbeatRestart = false init() { registerAdvancedOptionsDefault() @@ -565,6 +567,20 @@ struct HeartbeatApp: App { } } + private func handleScenePhaseChange(_ newPhase: ScenePhase) { + switch newPhase { + case .background: + shouldAttemptHeartbeatRestart = true + case .active: + if shouldAttemptHeartbeatRestart { + shouldAttemptHeartbeatRestart = false + startHeartbeatInBackground(showErrorUI: false) + } + default: + break + } + } + private var globalAccent: Color { themeExpansionManager.resolvedAccentColor(from: customAccentColorHex) } @@ -629,6 +645,9 @@ struct HeartbeatApp: App { HeartbeatApp.updateUIKitTint(customHex: newHex, hasAccess: themeExpansionManager.hasThemeExpansion) } + .onChange(of: scenePhase) { newPhase in + handleScenePhaseChange(newPhase) + } .sheet(isPresented: $showWelcomeSheet) { WelcomeSheetView { // When the user taps "Continue", mark the app as launched and start the VPN if allowed. @@ -753,12 +772,13 @@ func isPairing() -> Bool { return true } -func startHeartbeatInBackground(requireVPNConnection: Bool? = nil) { +func startHeartbeatInBackground(requireVPNConnection: Bool? = nil, showErrorUI: Bool = true) { assert(Thread.isMainThread, "startHeartbeatInBackground must be called on the main thread") let pairingFileURL = URL.documentsDirectory.appendingPathComponent("pairingFile.plist") guard FileManager.default.fileExists(atPath: pairingFileURL.path) else { heartbeatStartPending = false + heartbeatPendingShowUI = true return } @@ -768,6 +788,7 @@ func startHeartbeatInBackground(requireVPNConnection: Bool? = nil) { if !heartbeatStartPending { print("Heartbeat start deferred until VPN connects") } + heartbeatPendingShowUI = showErrorUI heartbeatStartPending = true return } @@ -777,6 +798,7 @@ func startHeartbeatInBackground(requireVPNConnection: Bool? = nil) { } heartbeatStartPending = false + heartbeatPendingShowUI = true heartbeatStartInProgress = true DispatchQueue.global(qos: .userInteractive).async { @@ -798,6 +820,7 @@ func startHeartbeatInBackground(requireVPNConnection: Bool? = nil) { let err2 = error as NSError let code = err2.code print("Error: \(error.localizedDescription) (Code: \(code))") + guard showErrorUI else { return } DispatchQueue.main.async { if code == -9 { do { diff --git a/StikJIT/Views/HomeView.swift b/StikJIT/Views/HomeView.swift index fc9a425..ec339e7 100644 --- a/StikJIT/Views/HomeView.swift +++ b/StikJIT/Views/HomeView.swift @@ -76,6 +76,7 @@ struct HomeView: View { @State private var isSchedulingInitialSetup = false @AppStorage("cachedAppNamesData") private var cachedAppNamesData: Data? @AppStorage("autoStartVPN") private var autoStartVPN = true + @State private var lastDDIIndicatorStatus: StartupIndicatorStatus = .idle @AppStorage("appTheme") private var appThemeRaw: String = AppTheme.system.rawValue @Environment(\.themeExpansionManager) private var themeExpansion @@ -195,6 +196,7 @@ struct HomeView: View { hasAutoStartedConnectionCheck = true runConnectionDiagnostics(autoStart: true) } + lastDDIIndicatorStatus = ddiIndicatorStatus NotificationCenter.default.addObserver( forName: NSNotification.Name("ShowPairingFilePicker"), object: nil, @@ -212,6 +214,9 @@ struct HomeView: View { refreshBackground() checkPairingFileExists() heartbeatOK = pubHeartBeat + if !mounting.coolisMounted { + MountingProgress.shared.checkforMounted() + } } .onChange(of: pairingFileExists) { _, newValue in if newValue { @@ -233,6 +238,9 @@ struct HomeView: View { loadAppListIfNeeded() syncFavoriteAppNamesWithCache() } + .onChange(of: ddiIndicatorStatus) { _, newStatus in + handleDDIIndicatorChange(newStatus) + } .onChange(of: recentApps) { _, _ in loadAppListIfNeeded() } @@ -269,6 +277,7 @@ struct HomeView: View { isImportingFile = false pairingFileIsValid = true withAnimation { showPairingFileMessage = true } + MountingProgress.shared.checkforMounted() DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { withAnimation { showPairingFileMessage = false } } @@ -651,6 +660,12 @@ struct HomeView: View { isCellularActive = false } + private func handleDDIIndicatorChange(_ newStatus: StartupIndicatorStatus) { + defer { lastDDIIndicatorStatus = newStatus } + guard lastDDIIndicatorStatus == .success, newStatus == .warning else { return } + startHeartbeatInBackground(showErrorUI: false) + } + private var pairingStatusDescription: String { if isValidatingPairingFile { return "Validating pairing file…" } if pairingFileExists { @@ -1178,8 +1193,7 @@ struct HomeView: View { refreshBackground() checkPairingFileExists() loadAppListIfNeeded() - - if tunnel.tunnelStatus == .connected { + if tunnel.tunnelStatus == .connected || !requiresLoopbackVPN { MountingProgress.shared.checkforMounted() } }