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:
2026-04-19 20:59:33 -04:00
parent 57358797e1
commit 89060d7177
137 changed files with 320 additions and 595 deletions
+35 -37
View File
@@ -1,21 +1,32 @@
#!/bin/bash
#
# download_team_logos.sh
# Downloads NHL team logos (SVG) from the NHL assets CDN.
# Downloads NHL team logos from the NHL assets CDN.
#
# Usage: ./Scripts/download_team_logos.sh [season]
# season: e.g. 20252026 (defaults to current season)
#
# SVGs are saved to Assets.xcassets imagesets for UI use.
# PNGs (80x80) are saved to TeamLogos/ for notification attachments.
# Downloads SVGs to /tmp, rasterizes to PNGs sized for the macOS notification
# thumbnail (72×72 square, aspect-preserved with transparent padding). Output
# goes to IceGlass/Resources/TeamLogos/ — used as notification attachments via
# Bundle.main.url(forResource:withExtension:subdirectory:"TeamLogos").
#
# Native notification thumbnail size was measured empirically at ~48 physical
# pixels. 72px is a small 1.5x over-sample that stays crisp without any
# visible downsample aliasing (tested at 48/72/96/128 — 4872 are sharp).
#
# Pipeline: rsvg renders the SVG at a generous intermediate resolution;
# square_logo.swift then trims the transparent margins (which NHL brand SVGs
# pad the viewBox with) so the logo fills the final square, then scales
# aspect-preserved into the 72×72 target.
#
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
ASSETS_DIR="$PROJECT_DIR/IceGlass/Assets.xcassets"
LOGOS_DIR="$PROJECT_DIR/IceGlass/TeamLogos"
LOGOS_DIR="$PROJECT_DIR/IceGlass/Resources/TeamLogos"
TMP_DIR="$(mktemp -d)"
# Determine season
if [ -n "$1" ]; then
@@ -30,7 +41,10 @@ else
fi
fi
echo "Downloading NHL team logos for season $SEASON"
TARGET_SIZE=72
INTERMEDIATE_WIDTH=1024 # high-res intermediate so the trim+downscale has detail
echo "Downloading NHL team logos for season $SEASON (target size ${TARGET_SIZE}×${TARGET_SIZE})"
TEAMS=(
ANA BOS BUF CAR CBJ CGY CHI COL DAL DET
@@ -39,57 +53,41 @@ TEAMS=(
WPG WSH
)
# Create logos directory for notification attachments
mkdir -p "$LOGOS_DIR"
for TEAM in "${TEAMS[@]}"; do
IMAGESET_DIR="$ASSETS_DIR/TeamLogo_${TEAM}.imageset"
mkdir -p "$IMAGESET_DIR"
SVG_URL="https://assets.nhle.com/logos/nhl/svg/${TEAM}_light.svg"
SVG_FILE="$IMAGESET_DIR/${TEAM}_light.svg"
SVG_FILE="$TMP_DIR/${TEAM}_light.svg"
INTERMEDIATE="$TMP_DIR/${TEAM}_native.png"
LOGO_PNG="$LOGOS_DIR/${TEAM}.png"
echo " Downloading $TEAM..."
curl -s -o "$SVG_FILE" "${SVG_URL}?season=${SEASON}"
# Convert SVG to PNG (200px wide, aspect-ratio preserved) for notification attachments
# Rasterize SVG at high-res intermediate width (aspect-preserved, transparent)
if command -v rsvg-convert &>/dev/null; then
rsvg-convert -w 200 -h 200 --keep-aspect-ratio --background-color=transparent "$SVG_FILE" -o "$LOGO_PNG" 2>/dev/null
rsvg-convert -w "$INTERMEDIATE_WIDTH" --keep-aspect-ratio --background-color=transparent "$SVG_FILE" -o "$INTERMEDIATE" 2>/dev/null
else
python3 -c "
try:
import cairosvg
cairosvg.svg2png(url='$SVG_FILE', write_to='$LOGO_PNG', output_width=200)
cairosvg.svg2png(url='$SVG_FILE', write_to='$INTERMEDIATE', output_width=$INTERMEDIATE_WIDTH)
except ImportError:
pass
" 2>/dev/null || true
fi
# Write Contents.json for the imageset (SVG only, no PNG)
cat > "$IMAGESET_DIR/Contents.json" << EOJSON
{
"images" : [
{
"filename" : "${TEAM}_light.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "original"
}
}
EOJSON
if [ ! -f "$INTERMEDIATE" ]; then
echo " warning: failed to rasterize $TEAM svg"
continue
fi
# Composite onto a target-size square transparent canvas (aspect-preserved, centered)
swift "$SCRIPT_DIR/square_logo.swift" "$INTERMEDIATE" "$LOGO_PNG" "$TARGET_SIZE"
done
rm -rf "$TMP_DIR"
echo ""
echo "Done! Downloaded ${#TEAMS[@]} team logos to:"
echo " Asset catalogs: $ASSETS_DIR/TeamLogo_*.imageset/ (SVG)"
echo " Notifications: $LOGOS_DIR/ (PNG 80x80)"
echo ""
echo "Done! Downloaded ${#TEAMS[@]} team logos to $LOGOS_DIR (${TARGET_SIZE}×${TARGET_SIZE})"
echo "Season: $SEASON"