@@ -78,6 +78,7 @@ final class DragHandleView: NSView {
7878class SettingsWindowController : NSWindowController , NSTableViewDataSource , NSTableViewDelegate {
7979 private var appTableView : NSTableView !
8080 private var termTableView : NSTableView !
81+ private var loginCheck : NSButton ?
8182 private let inputSources = listInputSources ( )
8283
8384 convenience init ( ) {
@@ -90,6 +91,19 @@ class SettingsWindowController: NSWindowController, NSTableViewDataSource, NSTab
9091 w. isReleasedWhenClosed = false
9192 self . init ( window: w)
9293 buildUI ( )
94+ // The General tab is built once and the controller is cached, so a
95+ // launch-at-login change made elsewhere (the user toggling our entry
96+ // in System Settings → Login Items) would leave the checkbox stale.
97+ // macOS sends us no notification for that, so re-read the live
98+ // SMAppService status every time the window comes forward.
99+ NotificationCenter . default. addObserver ( self , selector: #selector( syncExternalState) ,
100+ name: NSWindow . didBecomeKeyNotification, object: w)
101+ }
102+
103+ deinit { NotificationCenter . default. removeObserver ( self ) }
104+
105+ @objc private func syncExternalState( ) {
106+ loginCheck? . state = LaunchAtLogin . isEnabled ? . on : . off
93107 }
94108
95109 // MARK: Tab Builder
@@ -161,6 +175,12 @@ class SettingsWindowController: NSWindowController, NSTableViewDataSource, NSTab
161175 let appLabel = label ( " Application " )
162176 appLabel. font = . systemFont( ofSize: 13 , weight: . semibold)
163177
178+ let loginCheck = NSButton ( checkboxWithTitle: " Launch at login " ,
179+ target: self , action: #selector( launchAtLoginToggled ( _: ) ) )
180+ loginCheck. translatesAutoresizingMaskIntoConstraints = false
181+ loginCheck. state = LaunchAtLogin . isEnabled ? . on : . off
182+ self . loginCheck = loginCheck
183+
164184 let hideCheck = NSButton ( checkboxWithTitle: " Hide menu bar icon (reopen app to show Settings) " ,
165185 target: self , action: #selector( hideIconToggled ( _: ) ) )
166186 hideCheck. translatesAutoresizingMaskIntoConstraints = false
@@ -181,7 +201,7 @@ class SettingsWindowController: NSWindowController, NSTableViewDataSource, NSTab
181201 clearBtn. controlSize = . regular
182202
183203 for sub in [ defLabel, defPopup, sep1, indLabel, indCheck, posLabel, posPopup,
184- sep2, appLabel, hideCheck,
204+ sep2, appLabel, loginCheck , hideCheck,
185205 sep3, debugLabel, debugCheck, clearBtn] { v. addSubview ( sub) }
186206 NSLayoutConstraint . activate ( [
187207 defLabel. topAnchor. constraint ( equalTo: v. topAnchor, constant: 20 ) ,
@@ -210,7 +230,9 @@ class SettingsWindowController: NSWindowController, NSTableViewDataSource, NSTab
210230
211231 appLabel. topAnchor. constraint ( equalTo: sep2. bottomAnchor, constant: 16 ) ,
212232 appLabel. leadingAnchor. constraint ( equalTo: v. leadingAnchor, constant: 16 ) ,
213- hideCheck. topAnchor. constraint ( equalTo: appLabel. bottomAnchor, constant: 10 ) ,
233+ loginCheck. topAnchor. constraint ( equalTo: appLabel. bottomAnchor, constant: 10 ) ,
234+ loginCheck. leadingAnchor. constraint ( equalTo: v. leadingAnchor, constant: 16 ) ,
235+ hideCheck. topAnchor. constraint ( equalTo: loginCheck. bottomAnchor, constant: 8 ) ,
214236 hideCheck. leadingAnchor. constraint ( equalTo: v. leadingAnchor, constant: 16 ) ,
215237
216238 sep3. topAnchor. constraint ( equalTo: hideCheck. bottomAnchor, constant: 20 ) ,
@@ -242,6 +264,9 @@ class SettingsWindowController: NSWindowController, NSTableViewDataSource, NSTab
242264 @objc private func indicatorPosChanged( _ sender: NSPopUpButton ) {
243265 RuleStore . shared. indicatorPosition = IndicatorPosition . allCases [ sender. indexOfSelectedItem]
244266 }
267+ @objc private func launchAtLoginToggled( _ sender: NSButton ) {
268+ LaunchAtLogin . setEnabled ( sender. state == . on)
269+ }
245270 @objc private func hideIconToggled( _ sender: NSButton ) {
246271 RuleStore . shared. hideMenuBarIcon = sender. state == . on
247272 }
0 commit comments