// // AppDelegate.swift // IceGlass // // Copyright 2026 Rouslan Zenetl. All Rights Reserved. // import UserNotifications import AppKit import CoreServices class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDelegate { private let logger = IceGlassLogger( subsystem: Bundle.main.bundleIdentifier ?? "dev.rzen.indie.IceGlass", category: "AppDelegate" ) private var mainService = MainService.shared private let observerAdapter = MacObserverAdapter() func applicationDidFinishLaunching(_ notification: Notification) { logger.info("applicationDidFinishLaunching") UNUserNotificationCenter.current().delegate = self // Install MainService → AppKit bridge before any data flows in. mainService.observer = observerAdapter // Force re-register with Launch Services to refresh cached icon LSRegisterURL(Bundle.main.bundleURL as CFURL, true) // Set app icon explicitly from .icns (NSImage(named:) doesn't work for App Icon assets) if let icnsPath = Bundle.main.path(forResource: "AppIcon", ofType: "icns"), let icon = NSImage(contentsOfFile: icnsPath) { NSApp.applicationIconImage = icon } } func applicationWillTerminate(_ notification: Notification) { // nothing to deinit } // Notification click handler — opens URLs func userNotificationCenter( _ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void ) { if let urlString = response.notification.request.content.userInfo["url"] as? String, let url = URL(string: urlString) { NSWorkspace.shared.open(url) } completionHandler() } } /// Bridges MainService callbacks to the macOS-only managers so MainService /// stays AppKit-free and shareable with the iOS target. @MainActor final class MacObserverAdapter: MainServiceObserver { func mainServiceDidUpdate() { StatusItemManager.shared.updateStatusText(MainService.shared.statusBarText) MenuManager.shared.scoreboardChanged() } func mainServiceDidDetectGameStart(_ game: Scoreboard.Game) { NotificationManager.shared.notifyGameStarted(game) } func mainServiceDidDetectGoal( _ game: Scoreboard.Game, scoringTeam: Scoreboard.Game.Team, scorer: GoalScorer? ) { NotificationManager.shared.notifyGoalScored(game, scoringTeam: scoringTeam, scorer: scorer) } func mainServiceDidDetectGameEnd(_ game: Scoreboard.Game) { NotificationManager.shared.notifyGameEnded(game) } }