Replace Feed with highlights, remove duplicate live shelf, drop Intel schedule
Feed tab: Replaced news/transaction feed with league-wide highlights and condensed game replays. FeedViewModel now fetches highlights from all games concurrently, splits into condensed games vs individual highlights. Cards show team color thumbnails with play button overlay. Today tab: Removed duplicate Live games shelf — LiveSituationBar already shows all live games at the top, so the shelf was redundant. Intel tab: Removed schedule section (already on Today tab). Updated header description and stat pills. Added division hydration to standings API call so division names display correctly instead of "Division". Focus: Added .platformFocusable() to standings cards and leaderboard cards so tvOS remote can scroll horizontally through them. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -34,7 +34,6 @@ struct LeagueCenterView: View {
|
||||
messagePanel(overviewErrorMessage, tint: .orange)
|
||||
}
|
||||
|
||||
scheduleSection
|
||||
standingsSection
|
||||
|
||||
// League Leaders
|
||||
@@ -79,7 +78,7 @@ struct LeagueCenterView: View {
|
||||
.font(.system(size: 42, weight: .bold, design: .rounded))
|
||||
.foregroundStyle(.white)
|
||||
|
||||
Text("Schedules, standings, team context, roster access, and player snapshots in one control room.")
|
||||
Text("Standings, league leaders, team context, roster access, and player snapshots in one control room.")
|
||||
.font(.system(size: 16, weight: .medium))
|
||||
.foregroundStyle(.white.opacity(0.58))
|
||||
}
|
||||
@@ -87,7 +86,7 @@ struct LeagueCenterView: View {
|
||||
Spacer()
|
||||
|
||||
HStack(spacing: 12) {
|
||||
infoPill(title: "\(viewModel.scheduleGames.count)", label: "Games", color: .blue)
|
||||
infoPill(title: "\(viewModel.leagueLeaders.count)", label: "Leaders", color: .blue)
|
||||
infoPill(title: "\(viewModel.teams.count)", label: "Teams", color: .green)
|
||||
infoPill(title: "\(viewModel.standings.count)", label: "Divisions", color: .orange)
|
||||
}
|
||||
@@ -144,8 +143,10 @@ struct LeagueCenterView: View {
|
||||
selectedGame = linkedGame
|
||||
}
|
||||
} label: {
|
||||
HStack(spacing: 18) {
|
||||
HStack(spacing: 0) {
|
||||
teamMiniColumn(team: game.teams.away)
|
||||
.frame(width: scheduleTeamColWidth, alignment: .leading)
|
||||
|
||||
VStack(spacing: 6) {
|
||||
Text(scoreText(for: game))
|
||||
.font(.system(size: 28, weight: .black, design: .rounded))
|
||||
@@ -156,11 +157,10 @@ struct LeagueCenterView: View {
|
||||
.font(.system(size: 14, weight: .semibold))
|
||||
.foregroundStyle(statusColor(for: game))
|
||||
}
|
||||
.frame(width: 160)
|
||||
.frame(width: scheduleScoreColWidth)
|
||||
|
||||
teamMiniColumn(team: game.teams.home, alignTrailing: true)
|
||||
|
||||
Spacer()
|
||||
.frame(width: scheduleTeamColWidth, alignment: .trailing)
|
||||
|
||||
VStack(alignment: .trailing, spacing: 6) {
|
||||
if let venue = game.venue?.name {
|
||||
@@ -174,6 +174,7 @@ struct LeagueCenterView: View {
|
||||
.font(.system(size: 13, weight: .bold, design: .rounded))
|
||||
.foregroundStyle(linkedGame != nil ? .blue.opacity(0.95) : .white.opacity(0.34))
|
||||
}
|
||||
.frame(width: scheduleVenueColWidth, alignment: .trailing)
|
||||
}
|
||||
.padding(22)
|
||||
.background(sectionPanel)
|
||||
@@ -182,6 +183,16 @@ struct LeagueCenterView: View {
|
||||
.disabled(linkedGame == nil)
|
||||
}
|
||||
|
||||
#if os(tvOS)
|
||||
private var scheduleTeamColWidth: CGFloat { 340 }
|
||||
private var scheduleScoreColWidth: CGFloat { 160 }
|
||||
private var scheduleVenueColWidth: CGFloat { 220 }
|
||||
#else
|
||||
private var scheduleTeamColWidth: CGFloat { 200 }
|
||||
private var scheduleScoreColWidth: CGFloat { 120 }
|
||||
private var scheduleVenueColWidth: CGFloat { 160 }
|
||||
#endif
|
||||
|
||||
private func teamMiniColumn(team: StatsTeamGameInfo, alignTrailing: Bool = false) -> some View {
|
||||
let info = TeamInfo(
|
||||
code: team.team.abbreviation ?? "MLB",
|
||||
@@ -217,7 +228,6 @@ struct LeagueCenterView: View {
|
||||
TeamLogoView(team: info, size: 56)
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: alignTrailing ? .trailing : .leading)
|
||||
}
|
||||
|
||||
private var leadersSection: some View {
|
||||
@@ -239,10 +249,12 @@ struct LeagueCenterView: View {
|
||||
ForEach(viewModel.leagueLeaders) { category in
|
||||
LeaderboardView(category: category)
|
||||
.frame(width: leaderCardWidth)
|
||||
.platformFocusable()
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
.platformFocusSection()
|
||||
.scrollClipDisabled()
|
||||
}
|
||||
}
|
||||
@@ -265,13 +277,14 @@ struct LeagueCenterView: View {
|
||||
loadingPanel(title: "Loading standings...")
|
||||
} else {
|
||||
ScrollView(.horizontal) {
|
||||
HStack(spacing: 18) {
|
||||
LazyHStack(spacing: 18) {
|
||||
ForEach(viewModel.standings, id: \.division?.id) { record in
|
||||
standingsCard(record)
|
||||
.frame(width: 360)
|
||||
.platformFocusable()
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 4)
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
.platformFocusSection()
|
||||
.scrollClipDisabled()
|
||||
|
||||
Reference in New Issue
Block a user