Initial commit: IceGlass NHL game tracker

macOS menu bar app providing NHL game situational awareness with
league-wide scoreboard, dynamic polling, notifications with team
logos, and configurable display options.
This commit is contained in:
2026-04-13 21:44:08 -04:00
commit 8f8f8b2755
158 changed files with 2752 additions and 0 deletions
+98
View File
@@ -0,0 +1,98 @@
//
// AppSettings.swift
// IceGlass
//
// Copyright 2026 Rouslan Zenetl. All Rights Reserved.
//
import ServiceManagement
class AppSettings: @unchecked Sendable {
private let logger = IceGlassLogger(
subsystem: Bundle.main.bundleIdentifier ?? "dev.rzen.indie.IceGlass",
category: "AppSettings"
)
static let shared = AppSettings()
private enum UserDefaultsKey {
static let launchAtLogin = "launchAtLogin"
static let selectedTeam = "selectedTeam"
static let displayOption = "displayOption"
}
/// Controls which days are shown in the menu and counted in the status bar
enum DisplayOption: String, CaseIterable {
case yesterdayTodayTomorrow = "yesterdayTodayTomorrow"
case todayTomorrow = "todayTomorrow"
case todayOnly = "todayOnly"
var title: String {
switch self {
case .yesterdayTodayTomorrow: return "Yesterday / Today / Tomorrow"
case .todayTomorrow: return "Today / Tomorrow"
case .todayOnly: return "Today"
}
}
/// Which date strings to include
func includedDates() -> Set<String> {
switch self {
case .yesterdayTodayTomorrow:
return [Date.yesterdayET, Date.todayET, Date.tomorrowET]
case .todayTomorrow:
return [Date.todayET, Date.tomorrowET]
case .todayOnly:
return [Date.todayET]
}
}
}
// Launch at login
var launchAtLogin: Bool {
get {
UserDefaults.standard.bool(forKey: UserDefaultsKey.launchAtLogin)
}
set {
UserDefaults.standard.set(newValue, forKey: UserDefaultsKey.launchAtLogin)
}
}
// Selected team filter (nil = all teams)
var selectedTeam: String? {
get {
UserDefaults.standard.string(forKey: UserDefaultsKey.selectedTeam)
}
set {
UserDefaults.standard.set(newValue, forKey: UserDefaultsKey.selectedTeam)
}
}
// Display option
var displayOption: DisplayOption {
get {
if let rawValue = UserDefaults.standard.string(forKey: UserDefaultsKey.displayOption),
let option = DisplayOption(rawValue: rawValue) {
return option
}
return .yesterdayTodayTomorrow
}
set {
UserDefaults.standard.set(newValue.rawValue, forKey: UserDefaultsKey.displayOption)
}
}
func updateLoginItem(enabled: Bool) {
do {
if enabled {
try SMAppService.mainApp.register()
} else {
try SMAppService.mainApp.unregister()
}
} catch {
logger.error("Failed to \(enabled ? "enable" : "disable") launch at login: \(error.localizedDescription)")
}
}
private init() {}
}