Skip to content

Commit 525e5f5

Browse files
committed
Fix the black screen
1 parent bbae4ac commit 525e5f5

3 files changed

Lines changed: 85 additions & 13 deletions

File tree

StikJIT/StikJITApp.swift

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,9 @@ class TunnelManager: ObservableObject {
227227
self.tunnelStatus = .error
228228
}
229229
VPNLogger.shared.log("VPN status updated: \(self.tunnelStatus.rawValue)")
230+
if connectionStatus == .connected && heartbeatStartPending {
231+
startHeartbeatInBackground()
232+
}
230233
}
231234
}
232235

@@ -295,8 +298,8 @@ class TunnelManager: ObservableObject {
295298
}
296299

297300
private func startExistingVPN(manager: NETunnelProviderManager) {
298-
guard tunnelStatus != .connected else {
299-
VPNLogger.shared.log("Network tunnel is already connected")
301+
guard tunnelStatus == .disconnected || tunnelStatus == .error else {
302+
VPNLogger.shared.log("Ignoring VPN start; current status: \(tunnelStatus.rawValue)")
300303
return
301304
}
302305
tunnelStatus = .connecting
@@ -483,12 +486,15 @@ class DNSChecker: ObservableObject {
483486

484487
// Global state variable for the heartbeat response.
485488
var pubHeartBeat = false
489+
private var heartbeatStartPending = false
490+
private var heartbeatStartInProgress = false
486491

487492
@main
488493
struct HeartbeatApp: App {
489494
@AppStorage("hasLaunchedBefore") var hasLaunchedBefore: Bool = false
490495
@AppStorage("customAccentColor") private var customAccentColorHex: String = ""
491496
@AppStorage("appTheme") private var appThemeRaw: String = AppTheme.system.rawValue
497+
@AppStorage("autoStartVPN") private var autoStartVPN = true
492498
@State private var showWelcomeSheet: Bool = false
493499
@State private var show_alert = false
494500
@State private var alert_string = ""
@@ -551,6 +557,14 @@ struct HeartbeatApp: App {
551557
}
552558
}
553559

560+
private func triggerAutoVPNStartIfNeeded() {
561+
guard autoStartVPN else { return }
562+
let manager = TunnelManager.shared
563+
if manager.tunnelStatus == .disconnected || manager.tunnelStatus == .error {
564+
manager.startVPN()
565+
}
566+
}
567+
554568
private var globalAccent: Color {
555569
themeExpansionManager.resolvedAccentColor(from: customAccentColorHex)
556570
}
@@ -599,7 +613,7 @@ struct HeartbeatApp: App {
599613
if !hasLaunchedBefore {
600614
showWelcomeSheet = true
601615
} else {
602-
TunnelManager.shared.startVPN()
616+
triggerAutoVPNStartIfNeeded()
603617
}
604618
HeartbeatApp.updateUIKitTint(customHex: customAccentColorHex,
605619
hasAccess: themeExpansionManager.hasThemeExpansion)
@@ -613,10 +627,10 @@ struct HeartbeatApp: App {
613627
}
614628
.sheet(isPresented: $showWelcomeSheet) {
615629
WelcomeSheetView {
616-
// When the user taps "Continue", mark the app as launched and start the VPN.
630+
// When the user taps "Continue", mark the app as launched and start the VPN if allowed.
617631
hasLaunchedBefore = true
618632
showWelcomeSheet = false
619-
TunnelManager.shared.startVPN()
633+
triggerAutoVPNStartIfNeeded()
620634
}
621635
}
622636
}
@@ -653,8 +667,11 @@ class MountingProgress: ObservableObject {
653667
@Published var coolisMounted: Bool = false
654668

655669
func checkforMounted() {
656-
DispatchQueue.main.async {
657-
self.coolisMounted = isMounted()
670+
DispatchQueue.global(qos: .utility).async {
671+
let mounted = isMounted()
672+
DispatchQueue.main.async {
673+
self.coolisMounted = mounted
674+
}
658675
}
659676
}
660677

@@ -671,10 +688,21 @@ class MountingProgress: ObservableObject {
671688
}
672689

673690
private func mount() {
674-
self.coolisMounted = isMounted()
691+
guard TunnelManager.shared.tunnelStatus == .connected else {
692+
DispatchQueue.main.async {
693+
self.coolisMounted = false
694+
self.mountingThread = nil
695+
}
696+
return
697+
}
698+
699+
let currentlyMounted = isMounted()
700+
DispatchQueue.main.async {
701+
self.coolisMounted = currentlyMounted
702+
}
675703
let pairingpath = URL.documentsDirectory.appendingPathComponent("pairingFile.plist").path
676704

677-
if isPairing(), !isMounted() {
705+
if isPairing(), !currentlyMounted {
678706
if let mountingThread = mountingThread {
679707
mountingThread.cancel()
680708
self.mountingThread = nil
@@ -697,7 +725,8 @@ class MountingProgress: ObservableObject {
697725
}
698726
}
699727
} else {
700-
self.coolisMounted = isMounted()
728+
self.coolisMounted = true
729+
self.checkforMounted()
701730
}
702731
self.mountingThread = nil
703732
}
@@ -724,8 +753,37 @@ func isPairing() -> Bool {
724753
return true
725754
}
726755

727-
func startHeartbeatInBackground() {
756+
func startHeartbeatInBackground(requireVPNConnection: Bool = true) {
757+
assert(Thread.isMainThread, "startHeartbeatInBackground must be called on the main thread")
758+
let pairingFileURL = URL.documentsDirectory.appendingPathComponent("pairingFile.plist")
759+
760+
guard FileManager.default.fileExists(atPath: pairingFileURL.path) else {
761+
heartbeatStartPending = false
762+
return
763+
}
764+
765+
let vpnConnected = TunnelManager.shared.tunnelStatus == .connected
766+
if requireVPNConnection && !vpnConnected {
767+
if !heartbeatStartPending {
768+
print("Heartbeat start deferred until VPN connects")
769+
}
770+
heartbeatStartPending = true
771+
return
772+
}
773+
774+
guard !heartbeatStartInProgress else {
775+
return
776+
}
777+
778+
heartbeatStartPending = false
779+
heartbeatStartInProgress = true
780+
728781
let heartBeatThread = Thread {
782+
defer {
783+
DispatchQueue.main.async {
784+
heartbeatStartInProgress = false
785+
}
786+
}
729787
let completionHandler: @convention(block) (Int32, String?) -> Void = { result, message in
730788
if result == 0 {
731789
print("Heartbeat started successfully: \(message ?? "")")
@@ -762,7 +820,9 @@ func startHeartbeatInBackground() {
762820
showTryAgain: true
763821
) { shouldTryAgain in
764822
if shouldTryAgain {
765-
startHeartbeatInBackground()
823+
DispatchQueue.main.async {
824+
startHeartbeatInBackground()
825+
}
766826
}
767827
}
768828
}

StikJIT/Utilities/mountDDI.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ func htons(_ value: UInt16) -> UInt16 {
4747
}
4848

4949
func isMounted() -> Bool {
50+
guard TunnelManager.shared.tunnelStatus == .connected else {
51+
return false
52+
}
53+
5054
var addr = sockaddr_in()
5155
memset(&addr, 0, MemoryLayout<sockaddr_in>.size)
5256
addr.sin_family = sa_family_t(AF_INET)

StikJIT/Views/HomeView.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ struct HomeView: View {
8686
themeExpansion?.resolvedAccentColor(from: customAccentColorHex) ?? .blue
8787
}
8888

89-
private var ddiMounted: Bool { isMounted() }
89+
private var ddiMounted: Bool { mounting.coolisMounted }
9090
private var canConnectByApp: Bool { pairingFileExists && ddiMounted }
9191
private var pairingFileLikelyInvalid: Bool {
9292
(pairingFileExists || pairingFilePresentOnDisk) &&
@@ -119,6 +119,7 @@ struct HomeView: View {
119119
.padding(.horizontal, 20)
120120
.padding(.vertical, 30)
121121
}
122+
.scrollIndicators(.hidden)
122123

123124
if isImportingFile {
124125
Color.black.opacity(0.35).ignoresSafeArea()
@@ -154,6 +155,9 @@ struct HomeView: View {
154155
refreshBackground()
155156
loadAppListIfNeeded()
156157
startWiFiMonitoring()
158+
if tunnel.tunnelStatus == .connected {
159+
MountingProgress.shared.checkforMounted()
160+
}
157161
if autoStartVPN && tunnel.tunnelStatus == .disconnected {
158162
TunnelManager.shared.startVPN()
159163
}
@@ -191,7 +195,9 @@ struct HomeView: View {
191195
}
192196
.onChange(of: tunnel.tunnelStatus) { _, newStatus in
193197
if newStatus == .connected {
198+
loadAppListIfNeeded(force: cachedAppNames.isEmpty)
194199
runConnectionDiagnostics()
200+
MountingProgress.shared.checkforMounted()
195201
}
196202
}
197203
.onChange(of: favoriteApps) { _, _ in
@@ -1111,6 +1117,8 @@ struct HomeView: View {
11111117
return
11121118
}
11131119

1120+
guard tunnel.tunnelStatus == .connected else { return }
1121+
11141122
if !force && !cachedAppNames.isEmpty { return }
11151123

11161124
DispatchQueue.global(qos: .userInitiated).async {

0 commit comments

Comments
 (0)