Rebake team logos at 72×72 for crisp notification thumbnails
The notification thumbnail's native display size is ~48 physical pixels (measured empirically with a size-ladder test attached via the dev menu). Shipping logos at 512×342 forced macOS to downsample ~10×, which is what was producing the blurry/aliased team logos in banner thumbnails. - Pre-render logos at 72×72 (1.5× over native; stays sharp, gives a little extra detail for retina displays without triggering aliasing) - Trim transparent margins before fitting: NHL brand SVGs pad their viewBox generously, so the actual logo was only ~60% of the bundled image. square_logo.swift now scans the alpha channel, crops to the tight bounding box, then fits aspect-preserved into the 72×72 canvas. - Drop the 32 unused TeamLogo_*.imageset asset-catalog entries (dead code since the team-filter feature was removed); notifications load PNGs from the filesystem bundle subdir - Move TeamLogos/ → Resources/TeamLogos/ and update project.yml source paths; excludes: on the recursive scan prevents duplicate flat copies that were bloating the bundle - Simplify NotificationManager: drop SVG fallback (macOS doesn't accept SVG attachments) and content-hash identifier experiments; back to the minimal working config - Dev menu: add "Thumbnail Size Test" which fires a ladder of 10 test notifications (16…128px) for future sizing verification - Fire a test game-start notification on startup in DEBUG builds so the dev loop doesn't require clicking through the menu after each launch - Scripts/square_logo.swift: alpha-bbox trim + aspect-preserved fit
This commit is contained in:
@@ -220,6 +220,9 @@ class MenuManager: @unchecked Sendable {
|
||||
devSubmenu.addItem(
|
||||
NSMenuItem(title: "Test Goal Scored Notification", action: #selector(triggerTestGoalScored), keyEquivalent: "").withTarget(self)
|
||||
)
|
||||
devSubmenu.addItem(
|
||||
NSMenuItem(title: "Thumbnail Size Test", action: #selector(triggerThumbnailSizeTest), keyEquivalent: "").withTarget(self)
|
||||
)
|
||||
devMenuItem.submenu = devSubmenu
|
||||
menu.addItem(devMenuItem)
|
||||
#endif
|
||||
@@ -304,6 +307,10 @@ class MenuManager: @unchecked Sendable {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func triggerThumbnailSizeTest() {
|
||||
NotificationManager.shared.sendThumbnailSizeTest()
|
||||
}
|
||||
#endif
|
||||
|
||||
@objc private func showAbout() {
|
||||
@@ -365,6 +372,10 @@ class MenuManager: @unchecked Sendable {
|
||||
}
|
||||
|
||||
private static func nextGameLabel(for game: Scoreboard.Game) -> String {
|
||||
let state = game.parsedGameState
|
||||
if state.isLive {
|
||||
return state.shortTag
|
||||
}
|
||||
let dayLabel: String
|
||||
switch game.gameDate {
|
||||
case Date.todayET: dayLabel = "Today"
|
||||
@@ -381,6 +392,7 @@ class MenuManager: @unchecked Sendable {
|
||||
}
|
||||
}
|
||||
let time = game.startTimeET.trimmingCharacters(in: .whitespaces)
|
||||
return "\(dayLabel) \(time)"
|
||||
let base = "\(dayLabel) \(time)"
|
||||
return state == .pre ? "\(base) (PRE)" : base
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user