8f8f8b2755
macOS menu bar app providing NHL game situational awareness with league-wide scoreboard, dynamic polling, notifications with team logos, and configurable display options.
99 lines
2.9 KiB
Swift
99 lines
2.9 KiB
Swift
//
|
|
// 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() {}
|
|
}
|