fix: multiple bug fixes and improvements

- Fix suggested trips showing wrong sports for cross-country trips
- Remove quick start sections from home variants (Classic, Spotify)
- Remove dead quickActions code from HomeView
- Fix pace capsule animation in TripCreationView
- Add text wrapping to achievement descriptions
- Improve poll parsing with better error handling
- Various sharing system improvements

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-01-14 09:35:18 -06:00
parent fe36f99bca
commit d034ee8612
22 changed files with 422 additions and 242 deletions

View File

@@ -466,7 +466,7 @@ final class PDFGenerator {
.font: UIFont.systemFont(ofSize: 11),
.foregroundColor: UIColor.darkGray
]
let venueText = "\(richGame.stadium.name) | \(richGame.game.gameTime)"
let venueText = "\(richGame.stadium.name) | \(richGame.localGameTimeShort)"
(venueText as NSString).draw(
at: CGPoint(x: margin + 110, y: currentY + 30),
withAttributes: venueAttributes

View File

@@ -137,6 +137,8 @@ private struct AchievementSpotlightView: View {
Text(achievement.definition.name)
.font(.system(size: 56, weight: .bold, design: .rounded))
.foregroundStyle(theme.textColor)
.multilineTextAlignment(.center)
.fixedSize(horizontal: false, vertical: true)
// Description
Text(achievement.definition.description)
@@ -188,7 +190,7 @@ private struct AchievementCollectionView: View {
VStack(spacing: 40) {
// Header
Text("My \(year) Achievements")
Text("My \(String(year)) Achievements")
.font(.system(size: 48, weight: .bold, design: .rounded))
.foregroundStyle(theme.textColor)
@@ -271,6 +273,8 @@ private struct AchievementMilestoneView: View {
Text(achievement.definition.name)
.font(.system(size: 56, weight: .bold, design: .rounded))
.foregroundStyle(theme.textColor)
.multilineTextAlignment(.center)
.fixedSize(horizontal: false, vertical: true)
// Description
Text(achievement.definition.description)

View File

@@ -13,7 +13,6 @@ import UIKit
struct ProgressShareContent: ShareableContent {
let progress: LeagueProgress
let tripCount: Int
let username: String?
var cardType: ShareCardType { .stadiumProgress }
@@ -29,7 +28,6 @@ struct ProgressShareContent: ShareableContent {
let cardView = ProgressCardView(
progress: progress,
tripCount: tripCount,
username: username,
theme: theme,
mapSnapshot: mapSnapshot
)
@@ -50,7 +48,6 @@ struct ProgressShareContent: ShareableContent {
private struct ProgressCardView: View {
let progress: LeagueProgress
let tripCount: Int
let username: String?
let theme: ShareTheme
let mapSnapshot: UIImage?
@@ -103,7 +100,7 @@ private struct ProgressCardView: View {
Spacer()
ShareCardFooter(theme: theme, username: username)
ShareCardFooter(theme: theme)
}
.padding(ShareCardDimensions.padding)
}

View File

@@ -56,20 +56,9 @@ struct ShareCardHeader: View {
struct ShareCardFooter: View {
let theme: ShareTheme
var username: String? = nil
var body: some View {
VStack(spacing: 12) {
if let username = username, !username.isEmpty {
HStack(spacing: 8) {
Image(systemName: "person.circle.fill")
.font(.system(size: 24))
Text("@\(username)")
.font(.system(size: 28, weight: .medium))
}
.foregroundStyle(theme.secondaryTextColor)
}
HStack(spacing: 8) {
Image(systemName: "sportscourt.fill")
.font(.system(size: 20))

View File

@@ -57,8 +57,8 @@ extension ShareButton where Content == TripShareContent {
}
extension ShareButton where Content == ProgressShareContent {
init(progress: LeagueProgress, tripCount: Int = 0, username: String? = nil, style: ShareButtonStyle = .icon) {
self.content = ProgressShareContent(progress: progress, tripCount: tripCount, username: username)
init(progress: LeagueProgress, tripCount: Int = 0, style: ShareButtonStyle = .icon) {
self.content = ProgressShareContent(progress: progress, tripCount: tripCount)
self.style = style
}
}

View File

@@ -19,10 +19,6 @@ struct SharePreviewView<Content: ShareableContent>: View {
@State private var error: String?
@State private var showCopiedToast = false
// Progress-specific options
@State private var includeUsername = true
@State private var username = ""
init(content: Content) {
self.content = content
_selectedTheme = State(initialValue: ShareThemePreferences.theme(for: content.cardType))
@@ -38,11 +34,6 @@ struct SharePreviewView<Content: ShareableContent>: View {
// Theme selector
themeSelector
// Username toggle (progress cards only)
if content.cardType == .stadiumProgress {
usernameSection
}
// Action buttons
actionButtons
}
@@ -158,32 +149,6 @@ struct SharePreviewView<Content: ShareableContent>: View {
.buttonStyle(.plain)
}
// MARK: - Username Section
private var usernameSection: some View {
VStack(spacing: Theme.Spacing.sm) {
Toggle(isOn: $includeUsername) {
Text("Include username")
}
.onChange(of: includeUsername) { _, _ in
Task { await generatePreview() }
}
if includeUsername {
TextField("@username", text: $username)
.textFieldStyle(.roundedBorder)
.autocorrectionDisabled()
.textInputAutocapitalization(.never)
.onChange(of: username) { _, _ in
Task { await generatePreview() }
}
}
}
.padding()
.background(Theme.cardBackground(colorScheme))
.clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
}
// MARK: - Action Buttons
private var actionButtons: some View {
@@ -204,39 +169,21 @@ struct SharePreviewView<Content: ShareableContent>: View {
}
.disabled(generatedImage == nil)
HStack(spacing: Theme.Spacing.sm) {
// Copy Image
Button {
copyImage()
} label: {
HStack {
Image(systemName: "doc.on.doc")
Text("Copy")
}
.frame(maxWidth: .infinity)
.padding(Theme.Spacing.md)
.background(Theme.cardBackgroundElevated(colorScheme))
.foregroundStyle(Theme.textPrimary(colorScheme))
.clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
// Copy Image
Button {
copyImage()
} label: {
HStack {
Image(systemName: "doc.on.doc")
Text("Copy to Clipboard")
}
.disabled(generatedImage == nil)
// More Options
Button {
showSystemShare()
} label: {
HStack {
Image(systemName: "ellipsis.circle")
Text("More")
}
.frame(maxWidth: .infinity)
.padding(Theme.Spacing.md)
.background(Theme.cardBackgroundElevated(colorScheme))
.foregroundStyle(Theme.textPrimary(colorScheme))
.clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
}
.disabled(generatedImage == nil)
.frame(maxWidth: .infinity)
.padding(Theme.Spacing.md)
.background(Theme.cardBackgroundElevated(colorScheme))
.foregroundStyle(Theme.textPrimary(colorScheme))
.clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
}
.disabled(generatedImage == nil)
}
}
@@ -264,18 +211,7 @@ struct SharePreviewView<Content: ShareableContent>: View {
isGenerating = true
do {
// For progress content, we may need to inject username
if let progressContent = content as? ProgressShareContent {
// This is a workaround - ideally we'd have a more elegant solution
let modifiedContent = ProgressShareContent(
progress: progressContent.progress,
tripCount: progressContent.tripCount,
username: includeUsername ? (username.isEmpty ? nil : username) : nil
)
generatedImage = try await modifiedContent.render(theme: selectedTheme)
} else {
generatedImage = try await content.render(theme: selectedTheme)
}
generatedImage = try await content.render(theme: selectedTheme)
} catch {
self.error = error.localizedDescription
}