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:
@@ -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() {}
|
||||
}
|
||||
Reference in New Issue
Block a user