bugger/Sources/AppDelegate.swift

89 lines
2.6 KiB
Swift

import AppKit
import ServiceManagement
import SwiftUI
final class AppDelegate: NSObject, NSApplicationDelegate {
static weak var shared: AppDelegate?
private var statusItem: NSStatusItem!
private var popover: NSPopover!
private var floatingWidget: FloatingWidgetWindow?
private let bugStore = BugStore.shared
func applicationDidFinishLaunching(_ notification: Notification) {
Self.shared = self
NSApp.setActivationPolicy(.accessory)
setupStatusItem()
setupPopover()
if let config = AppStateService.shared.config {
if config.showFloatingWidget {
showFloatingWidget()
}
if config.launchAtLogin {
try? SMAppService.mainApp.register()
}
}
Task {
await PollerService.shared.startIfConfigured()
// Real-time change push is non-blocking; no-op if the subscribe
// base URL isn't configured (falls back to polling).
BitableEventService.shared.connect()
}
}
private func setupStatusItem() {
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
if let button = statusItem.button {
button.image = NSImage(systemSymbolName: "ant.fill", accessibilityDescription: "Bugger")
button.action = #selector(togglePopover)
button.target = self
}
updateBadge(count: bugStore.activeBugs.count)
}
private func setupPopover() {
popover = NSPopover()
popover.contentSize = NSSize(width: 360, height: 500)
popover.behavior = .transient
popover.contentViewController = NSHostingController(rootView: BugListPopover())
}
func updateBadge(count: Int) {
if count > 0 {
statusItem.button?.title = " \(count)"
} else {
statusItem.button?.title = ""
}
}
@objc func togglePopover() {
guard let button = statusItem.button else { return }
if popover.isShown {
closePopover()
} else {
popover.show(relativeTo: button.bounds, of: button, preferredEdge: .minY)
popover.contentViewController?.view.window?.makeKey()
}
}
func closePopover() {
popover.performClose(nil)
}
func showFloatingWidget() {
guard floatingWidget == nil else { return }
floatingWidget = FloatingWidgetWindow()
floatingWidget?.orderFrontRegardless()
}
func hideFloatingWidget() {
floatingWidget?.close()
floatingWidget = nil
}
}