aboutsummaryrefslogtreecommitdiff
path: root/Sources/phbar/Models/AppDelegate.swift
diff options
context:
space:
mode:
authorTommaso Negri <me@tommasongr.com>2026-07-27 16:18:34 +0200
committerTommaso Negri <me@tommasongr.com>2026-07-27 16:18:34 +0200
commit535b42a7b8304340182ca1367aa42f047eb06bff (patch)
tree88e15512f874a00886fc7b97861feb5e92c6aaf5 /Sources/phbar/Models/AppDelegate.swift
parent6d165c74a5a6b471c155b12ab15ef833d6b2aa36 (diff)
downloadbar-535b42a7b8304340182ca1367aa42f047eb06bff.tar.gz
bar-535b42a7b8304340182ca1367aa42f047eb06bff.zip
scaffold basic structure
Diffstat (limited to 'Sources/phbar/Models/AppDelegate.swift')
-rw-r--r--Sources/phbar/Models/AppDelegate.swift47
1 files changed, 47 insertions, 0 deletions
diff --git a/Sources/phbar/Models/AppDelegate.swift b/Sources/phbar/Models/AppDelegate.swift
new file mode 100644
index 0000000..a7ecb5a
--- /dev/null
+++ b/Sources/phbar/Models/AppDelegate.swift
@@ -0,0 +1,47 @@
+import AppKit
+import SwiftUI
+
+@MainActor
+final class AppDelegate: NSObject, NSApplicationDelegate {
+ private var windows: [BarWindow] = []
+ private var blocks: [Block] = Config.blocks.map(\.resolved)
+ private var tokens: [UnsafeMutableRawPointer] = []
+
+ func applicationDidFinishLaunching(_ notification: Notification) {
+ for screen in NSScreen.screens {
+ let frame = Screen.barFrame(screen, position: Config.position, height: Config.height)
+ let window = BarWindow(contentRect: frame)
+ window.contentView = NSHostingView(rootView: BarView(blocks: blocks))
+ window.orderFrontRegardless()
+ windows.append(window)
+ }
+
+ // Register one listener per unique name; a single post fans out to every
+ // block with that name (see Notifier).
+ for name in Set(blocks.map(\.name)) {
+ let token = Notifier.register(name) { [weak self] in
+ self?.handleRefresh(name)
+ }
+ tokens.append(token)
+ }
+
+ for block in blocks { block.start() }
+ }
+
+ func applicationWillTerminate(_ notification: Notification) {
+ for block in blocks { block.stop() }
+ for token in tokens { Notifier.cancel(token) }
+ }
+
+ /// Called from a Darwin notification handler. Marked `nonisolated` because
+ /// libnotify's delivery contract isn't statically visible to Swift, so we
+ /// hop back to the main actor explicitly.
+ nonisolated func handleRefresh(_ name: String) {
+ Task { @MainActor [weak self] in
+ guard let self else { return }
+ for block in self.blocks where block.name == name {
+ block.runScript()
+ }
+ }
+ }
+}