diff --git a/IceGlass-iOS/Views/GameRow.swift b/IceGlass-iOS/Views/GameRow.swift index 1b9f039..f8a94f5 100644 --- a/IceGlass-iOS/Views/GameRow.swift +++ b/IceGlass-iOS/Views/GameRow.swift @@ -12,7 +12,7 @@ struct GameRow: View { var body: some View { Button(action: open) { - HStack(spacing: 12) { + HStack(spacing: 10) { if game.gameType == 2 { Text("#\(game.seasonGameNumber)") .font(.caption2.monospacedDigit()) @@ -20,12 +20,9 @@ struct GameRow: View { .frame(width: 44, alignment: .leading) } - Text("\(game.awayTeam.abbrev) @ \(game.homeTeam.abbrev)") - .font(.body) - .fontWeight(.medium) - .foregroundStyle(.primary) + matchupBlock - Spacer() + Spacer(minLength: 8) rightContent } @@ -36,6 +33,24 @@ struct GameRow: View { .buttonStyle(.plain) } + private var matchupBlock: some View { + HStack(spacing: 6) { + TeamLogo(abbrev: game.awayTeam.abbrev) + Text(game.awayTeam.abbrev) + .font(.body.monospaced()) + .fontWeight(.medium) + .foregroundStyle(.primary) + Text("@") + .font(.subheadline) + .foregroundStyle(.tertiary) + TeamLogo(abbrev: game.homeTeam.abbrev) + Text(game.homeTeam.abbrev) + .font(.body.monospaced()) + .fontWeight(.medium) + .foregroundStyle(.primary) + } + } + @ViewBuilder private var rightContent: some View { let state = game.parsedGameState diff --git a/IceGlass-iOS/Views/SeriesRow.swift b/IceGlass-iOS/Views/SeriesRow.swift index 4d187df..3187977 100644 --- a/IceGlass-iOS/Views/SeriesRow.swift +++ b/IceGlass-iOS/Views/SeriesRow.swift @@ -12,17 +12,9 @@ struct SeriesRow: View { var body: some View { Button(action: open) { - HStack(alignment: .center, spacing: 12) { - VStack(alignment: .leading, spacing: 2) { - Text(matchupText) - .font(.body) - .fontWeight(.medium) - .foregroundStyle(.primary) - Text(scoreText) - .font(.caption) - .foregroundStyle(.secondary) - } - Spacer() + HStack(alignment: .center, spacing: 10) { + matchupBlock + Spacer(minLength: 8) VStack(alignment: .trailing, spacing: 2) { Text(statusText) .font(.caption) @@ -42,10 +34,29 @@ struct SeriesRow: View { .buttonStyle(.plain) } - private var matchupText: String { - let top = item.series.topSeedTeam?.abbrev ?? "TBD" + private var matchupBlock: some View { let bottom = item.series.bottomSeedTeam?.abbrev ?? "TBD" - return "\(bottom) @ \(top)" + let top = item.series.topSeedTeam?.abbrev ?? "TBD" + return VStack(alignment: .leading, spacing: 4) { + HStack(spacing: 6) { + TeamLogo(abbrev: bottom) + Text(bottom) + .font(.body.monospaced()) + .fontWeight(.medium) + .foregroundStyle(.primary) + Text("@") + .font(.subheadline) + .foregroundStyle(.tertiary) + TeamLogo(abbrev: top) + Text(top) + .font(.body.monospaced()) + .fontWeight(.medium) + .foregroundStyle(.primary) + } + Text(scoreText) + .font(.caption.monospacedDigit()) + .foregroundStyle(.secondary) + } } private var scoreText: String { diff --git a/IceGlass-iOS/Views/TeamLogo.swift b/IceGlass-iOS/Views/TeamLogo.swift new file mode 100644 index 0000000..b635706 --- /dev/null +++ b/IceGlass-iOS/Views/TeamLogo.swift @@ -0,0 +1,49 @@ +// +// TeamLogo.swift +// IceGlass-iOS +// +// Copyright 2026 Rouslan Zenetl. All Rights Reserved. +// + +import SwiftUI +import UIKit + +/// Loads a bundled team logo PNG from `TeamLogos/{abbrev}.png`. Falls back to +/// an SF Symbol if the file is missing (e.g. abbrev is "TBD" for unfilled +/// playoff matchups). +struct TeamLogo: View { + let abbrev: String + var size: CGFloat = 22 + + var body: some View { + Group { + if let image = Self.loadImage(for: abbrev) { + Image(uiImage: image) + .resizable() + .interpolation(.high) + .scaledToFit() + } else { + Image(systemName: "shield") + .resizable() + .scaledToFit() + .foregroundStyle(.tertiary) + } + } + .frame(width: size, height: size) + } + + /// Bundle lookup is trivial but image decoding isn't free — cache by + /// abbrev so scrolling through 16+ rows doesn't repeatedly hit disk. + private static var cache: [String: UIImage] = [:] + + private static func loadImage(for abbrev: String) -> UIImage? { + if let cached = cache[abbrev] { return cached } + guard let url = Bundle.main.url( + forResource: abbrev, withExtension: "png", subdirectory: "TeamLogos" + ), let image = UIImage(contentsOfFile: url.path) else { + return nil + } + cache[abbrev] = image + return image + } +}