Files
iceglass/IceGlass/Managers/StatusItemManager.swift
T
rzen 8f8f8b2755 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.
2026-04-13 21:44:08 -04:00

74 lines
2.2 KiB
Swift

//
// StatusItemManager.swift
// IceGlass
//
// Copyright 2026 Rouslan Zenetl. All Rights Reserved.
//
import AppKit
final class StatusItemManager: @unchecked Sendable {
private let logger = IceGlassLogger(
subsystem: Bundle.main.bundleIdentifier ?? "dev.rzen.indie.IceGlass",
category: "StatusItemManager"
)
static let shared = StatusItemManager()
var statusItem: NSStatusItem?
private init() {
DispatchQueue.main.async { [weak self] in
guard let self = self else {
AppTerminator.terminate()
return
}
self.setupStatusItem()
}
}
private func setupStatusItem() {
logger.debug("Initializing")
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
updateIcon()
}
func updateIcon() {
Task { @MainActor in
guard let button = self.statusItem?.button else { return }
guard let baseImage = NSImage(named: NSImage.Name("NHLShield")) else {
button.title = "NHL"
return
}
let pointSize = button.frame.size.height > 0 ? button.frame.size.height : 22
let resizedImage = NSImage(size: NSSize(width: pointSize, height: pointSize))
resizedImage.lockFocus()
baseImage.draw(
in: NSRect(x: 0, y: 0, width: pointSize, height: pointSize),
from: NSRect(x: 0, y: 0, width: baseImage.size.width, height: baseImage.size.height),
operation: .copy,
fraction: 1.0
)
resizedImage.unlockFocus()
button.image = resizedImage
button.imageScaling = .scaleProportionallyDown
}
}
/// Update status bar text with per-day game counts (e.g. "6/10/9" or "10/9")
func updateGameCounts(_ gameDays: [Scoreboard.GameDay]) {
Task { @MainActor in
guard let button = self.statusItem?.button else { return }
if gameDays.isEmpty {
button.title = ""
return
}
let counts = gameDays.map { "\($0.games.count)" }.joined(separator: "/")
button.title = " \(counts)"
}
}
}