mirror of
https://github.com/acamarata/curtain.git
synced 2026-06-30 18:54:25 +00:00
Rework Curtain into a proper menu-bar app (Caffeine-style): - SwiftUI settings window: app, on-start, on-idle, on-end, security, displays - Modular ActionSet/ActionRunner — per-event toggles (disconnect/lock/screen-off/deactivate) - Configurable idle timeout; open-at-login via SMAppService; optional menu bar - Settings persisted in UserDefaults (shared with @AppStorage); salted-SHA256 password - Drawn curtains logo (menu-bar template + offscreen-rendered app icon) - Split into single-responsibility modules with comment blocks
43 lines
1.8 KiB
Swift
43 lines
1.8 KiB
Swift
import Cocoa
|
|
|
|
/// Purpose: App entry orchestration. Owns the coordinator, the optional menu bar,
|
|
/// and the settings window. Keeps logic out of the UI: it just wires
|
|
/// callbacks between the pieces.
|
|
/// SPORT: MASTER-APP
|
|
final class AppDelegate: NSObject, NSApplicationDelegate {
|
|
private let coordinator = SessionCoordinator()
|
|
private lazy var menuBar = MenuBarController(coordinator: coordinator)
|
|
private lazy var prefs = PreferencesWindowController(coordinator: coordinator)
|
|
|
|
func applicationDidFinishLaunching(_ n: Notification) {
|
|
Settings.registerDefaults()
|
|
|
|
coordinator.onStateChange = { [weak self] active in self?.menuBar.reflect(active: active) }
|
|
coordinator.start()
|
|
|
|
menuBar.onOpenSettings = { [weak self] in self?.prefs.show() }
|
|
menuBar.onQuit = { [weak self] in self?.quit() }
|
|
if Settings.showInMenuBar { menuBar.show() }
|
|
|
|
prefs.onMenuBarToggle = { [weak self] on in on ? self?.menuBar.show() : self?.menuBar.hide() }
|
|
|
|
// First run: no password and no menu bar would be confusing — open settings.
|
|
if !Settings.hasPassword && !Settings.showInMenuBar { prefs.show() }
|
|
if !AXIsProcessTrusted() { requestAccessibility() }
|
|
|
|
// Reconcile the login-item state with the saved preference.
|
|
LoginItem.set(Settings.launchAtLogin)
|
|
}
|
|
|
|
/// Re-opening the app from Finder shows the settings window.
|
|
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
|
|
prefs.show(); return true
|
|
}
|
|
|
|
private func quit() { coordinator.deactivateNow(); NSApp.terminate(nil) }
|
|
|
|
private func requestAccessibility() {
|
|
let opts = [kAXTrustedCheckOptionPrompt.takeUnretainedValue(): true] as CFDictionary
|
|
_ = AXIsProcessTrustedWithOptions(opts)
|
|
}
|
|
}
|