File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 2323 <key >CFBundlePackageType </key >
2424 <string >APPL </string >
2525 <key >CFBundleShortVersionString </key >
26- <string >0.2.5 </string >
26+ <string >0.2.6 </string >
2727 <key >CFBundleSupportedPlatforms </key >
2828 <array >
2929 <string >MacOSX </string >
3030 </array >
3131 <key >CFBundleVersion </key >
32- <string >7 </string >
32+ <string >8 </string >
3333 <key >DTCompiler </key >
3434 <string >com.apple.compilers.llvm.clang.1_0 </string >
3535 <key >DTPlatformBuild </key >
Original file line number Diff line number Diff line change @@ -102,6 +102,26 @@ final class AppCoordinator: ObservableObject {
102102 LoginItemManager . applyPreference ( )
103103 self ? . controller. startNetworkMonitoring ( )
104104 self ? . showOnboardingIfNeeded ( )
105+ self ? . scheduleAutoConnectIfNeeded ( )
106+ }
107+ }
108+
109+ /// Kicks off a delayed `controller.connect()` when the user has opted into
110+ /// auto-connect-on-launch AND setup is already complete. Success flips
111+ /// `shouldAutoReconnect` inside the controller, so later network drops
112+ /// auto-recover through the existing reachability path.
113+ private func scheduleAutoConnectIfNeeded( ) {
114+ guard AutoConnectPreference . isEnabled, configStore. isConfigured else { return }
115+ AppLogger . shared. info ( " auto-connect on launch scheduled (5s delay) " )
116+ Task { @MainActor [ weak self] in
117+ try ? await Task . sleep ( nanoseconds: 5 * 1_000_000_000 )
118+ guard let self else { return }
119+ guard case . disconnected = self . controller. state else {
120+ AppLogger . shared. info ( " auto-connect skipped — state= \( self . controller. state) " )
121+ return
122+ }
123+ AppLogger . shared. info ( " auto-connect firing " )
124+ await self . controller. connect ( )
105125 }
106126 }
107127
Original file line number Diff line number Diff line change 1717 <key >CFBundlePackageType </key >
1818 <string >APPL </string >
1919 <key >CFBundleShortVersionString </key >
20- <string >0.2.5 </string >
20+ <string >0.2.6 </string >
2121 <key >CFBundleVersion </key >
22- <string >7 </string >
22+ <string >8 </string >
2323 <key >LSMinimumSystemVersion </key >
2424 <string >13.0 </string >
2525 <key >LSUIElement </key >
Original file line number Diff line number Diff line change @@ -7,6 +7,7 @@ struct SettingsView: View {
77 @State private var config : VPNConfig = VPNConfig ( username: " " , passwordPrefix: " " , totpSecret: " " )
88 @State private var originalConfig : VPNConfig = VPNConfig ( username: " " , passwordPrefix: " " , totpSecret: " " )
99 @State private var launchAtLogin : Bool = LoginItemManager . isEnabledPreference
10+ @State private var autoConnectOnLaunch : Bool = AutoConnectPreference . isEnabled
1011 @State private var showSavedAlert : Bool = false
1112 @State private var savedAlertTitle : String = " "
1213 @State private var savedAlertMessage : String = " "
@@ -39,6 +40,10 @@ struct SettingsView: View {
3940 . onChange ( of: launchAtLogin) { newValue in
4041 LoginItemManager . isEnabledPreference = newValue
4142 }
43+ Toggle ( " Auto-connect on launch " , isOn: $autoConnectOnLaunch)
44+ . onChange ( of: autoConnectOnLaunch) { newValue in
45+ AutoConnectPreference . isEnabled = newValue
46+ }
4247 HStack {
4348 Text ( " Log file " )
4449 Spacer ( )
Original file line number Diff line number Diff line change 1+ import Foundation
2+
3+ /// Stores the "auto-connect on launch" preference in UserDefaults.
4+ /// Default is `false` (opt-in) — auto-connecting without user consent would be
5+ /// intrusive given the sudo prompt cascade on a misconfigured machine.
6+ enum AutoConnectPreference {
7+ private static let preferenceKey = " autoConnectOnLaunchEnabled "
8+
9+ static var isEnabled : Bool {
10+ get { UserDefaults . standard. bool ( forKey: preferenceKey) }
11+ set { UserDefaults . standard. set ( newValue, forKey: preferenceKey) }
12+ }
13+ }
Original file line number Diff line number Diff line change 55 <link >https://github.com/CoderZCC/VPNMenuBar</link >
66 <description >VPN MenuBar update feed</description >
77 <language >en</language >
8+ <item >
9+ <title >Version 0.2.6</title >
10+ <sparkle : version >8</sparkle : version >
11+ <sparkle : shortVersionString >0.2.6</sparkle : shortVersionString >
12+ <sparkle : minimumSystemVersion >13.0</sparkle : minimumSystemVersion >
13+ <description ><![CDATA[
14+ <ul>
15+ <li>Added a new Settings toggle "Auto-connect on launch" — when enabled, the app automatically connects to VPN about 5 seconds after launch</li>
16+ <li>The auto-connect only fires when setup is complete (all required fields filled), so it never triggers spurious failures on a half-configured install</li>
17+ <li>Once the auto-connect handshake succeeds, the existing network-drop auto-reconnect path takes over, so switching WiFi or sleeping/waking transparently recovers the tunnel</li>
18+ </ul>
19+ ]]> </description >
20+ <pubDate >Fri, 24 Apr 2026 20:40:00 +0800</pubDate >
21+ <enclosure
22+ url =" https://github.com/CoderZCC/VPNMenuBar/releases/download/v0.2.6/VPNMenuBar-0.2.6.zip"
23+ type =" application/octet-stream"
24+ sparkle : edSignature =" mK2YBz3uWr8hejXPNLNgzx4k+134sxOfCqxlNc/JKQcoh9nS9a2hcVtAqlL5nkK4CXsAL1n8G6O5zZCfK8QqAg=="
25+ length =" 1788132"
26+ />
27+ </item >
828 <item >
929 <title >Version 0.2.5</title >
1030 <sparkle : version >7</sparkle : version >
Original file line number Diff line number Diff line change @@ -36,8 +36,8 @@ targets:
3636 properties :
3737 CFBundleName : VPNMenuBar
3838 CFBundleDisplayName : VPN MenuBar
39- CFBundleShortVersionString : " 0.2.5 "
40- CFBundleVersion : " 7 "
39+ CFBundleShortVersionString : " 0.2.6 "
40+ CFBundleVersion : " 8 "
4141 LSMinimumSystemVersion : " 13.0"
4242 LSUIElement : true
4343 NSUserNotificationAlertStyle : alert
You can’t perform that action at this time.
0 commit comments