From 617e07d53dd4b352a1f30a76df3c5634bfa9e2b0 Mon Sep 17 00:00:00 2001 From: maxsoch Date: Mon, 6 Jul 2026 22:05:14 +0200 Subject: [PATCH] add launch-at-login setting via SMAppService MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Checkbox registers/unregisters SMAppService.mainApp (macOS 13+ API, no helper app needed). Deliberately not mirrored in UserDefaults: the service status is the single source of truth, and syncUI reads it live so changes made in System Settings > Login Items stay in sync. Failures revert the checkbox and surface the error in an alert. Note: registration points at the app bundle's current path, so it only behaves properly once BrewBar runs from a stable location like /Applications — debug builds may register the build folder copy. Co-Authored-By: Claude Fable 5 --- BrewBar/SettingsWindowController.swift | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/BrewBar/SettingsWindowController.swift b/BrewBar/SettingsWindowController.swift index 48579c4..ef962c7 100644 --- a/BrewBar/SettingsWindowController.swift +++ b/BrewBar/SettingsWindowController.swift @@ -1,4 +1,5 @@ import Cocoa +import ServiceManagement class SettingsWindowController: NSWindowController { weak var appDelegate: AppDelegate? @@ -13,6 +14,7 @@ class SettingsWindowController: NSWindowController { var intervalPopup: NSPopUpButton! var customMinutesField: NSTextField! + var launchAtLoginCheckbox: NSButton! convenience init(appDelegate: AppDelegate) { let window = NSWindow( @@ -66,9 +68,17 @@ class SettingsWindowController: NSWindowController { ]) customRow.orientation = .horizontal + launchAtLoginCheckbox = NSButton( + checkboxWithTitle: "Launch BrewBar at login", + target: self, + action: #selector(toggleLaunchAtLogin(_:)) + ) + let stack = NSStackView(views: [ frequencyRow, customRow, + separator(), + launchAtLoginCheckbox, ]) stack.orientation = .vertical stack.alignment = .leading @@ -99,6 +109,16 @@ class SettingsWindowController: NSWindowController { intervalPopup.selectItem(at: presets.count) // Custom } customMinutesField.stringValue = "\(Int(interval / 60))" + + // SMAppService is the source of truth — the user may have changed + // this in System Settings > Login Items while we weren't looking + launchAtLoginCheckbox.state = SMAppService.mainApp.status == .enabled ? .on : .off + } + + func separator() -> NSBox { + let box = NSBox() + box.boxType = .separator + return box } // MARK: - Actions @@ -124,4 +144,22 @@ class SettingsWindowController: NSWindowController { appDelegate?.restartTimer() syncUI() } + + @objc func toggleLaunchAtLogin(_ sender: NSButton) { + do { + if sender.state == .on { + try SMAppService.mainApp.register() + } else { + try SMAppService.mainApp.unregister() + } + } catch { + sender.state = sender.state == .on ? .off : .on // revert on failure + + let alert = NSAlert() + alert.alertStyle = .warning + alert.messageText = "Could not change login item" + alert.informativeText = error.localizedDescription + alert.runModal() + } + } }