Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions Docs/2025-08-22-fix-detail-screen-distance-and-events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Fix Detail Screen Distance Display and Event Times

## Date: 2025-08-22

## Problem Statement
The SwiftUI detail screen had two issues:
1. Distance was displayed in meters instead of feet
2. "All Day" events only showed "All Day" without actual start/end times

## Solution Overview
Fixed both issues and added walk/bike time estimates as a separate cell for better user experience.

## Key Changes

### 1. Distance Display Fix
**File**: `iBurn/Detail/Views/DetailView.swift`
- Modified `DetailDistanceCell` to convert meters to feet (1 meter = 3.28084 feet)
- Changed display format from "Distance: X meters" to "Distance: X ft"

### 2. Added Walk/Bike Time Estimates
**Files Modified**:
- `iBurn/Detail/Models/DetailCellType.swift`: Added new `.travelTime(CLLocationDistance)` case
- `iBurn/Detail/Views/DetailView.swift`:
- Created new `DetailTravelTimeCell` view
- Added case handling in `DetailCellView`
- Updated `isCellTappable` function
- `iBurn/Detail/ViewModels/DetailViewModel.swift`: Added travel time cell after distance cell

The new cell uses the existing `TTTLocationFormatter.brc_humanizedString(forDistance:)` to display:
- Walking time with emoji 馃毝馃徑
- Biking time with emoji 馃毚馃徑
- Color coding (green/orange/red) based on difficulty

### 3. All Day Event Times Fix
**File**: `iBurn/Detail/ViewModels/DetailViewModel.swift`
- Modified `formatEventSchedule` method
- Changed "All Day" events to display: "All Day (startTime - endTime)"
- Provides clarity on actual event hours while maintaining "All Day" designation

## Technical Details

### Code Snippets

#### Distance Cell Update
```swift
struct DetailDistanceCell: View {
let distance: CLLocationDistance
@Environment(\.themeColors) var themeColors

var body: some View {
HStack {
Image(systemName: "ruler")
.foregroundColor(themeColors.detailColor)
Text("Distance: \(formattedDistance)")
.foregroundColor(themeColors.detailColor)
Spacer()
}
}

private var formattedDistance: String {
let meters = Measurement(value: distance, unit: UnitLength.meters)
let feet = meters.converted(to: .feet)

let formatter = MeasurementFormatter()
formatter.unitStyle = .short
formatter.unitOptions = .providedUnit
formatter.numberFormatter.maximumFractionDigits = 0

return formatter.string(from: feet)
}
}
```

#### New Travel Time Cell
```swift
struct DetailTravelTimeCell: View {
let distance: CLLocationDistance
@Environment(\.themeColors) var themeColors

var body: some View {
if let attributedString = TTTLocationFormatter.brc_humanizedString(forDistance: distance) {
HStack {
Text(AttributedString(attributedString))
.frame(maxWidth: .infinity, alignment: .leading)
Spacer()
}
}
}
}
```

#### All Day Event Fix
```swift
if event.isAllDay {
let start = timeFormatter.string(from: startDate)
let end = timeFormatter.string(from: endDate)
timeString = "All Day (\(start) - \(end))"
} else {
let start = timeFormatter.string(from: startDate)
let end = timeFormatter.string(from: endDate)
timeString = "\(start) - \(end)"
}
```

## Testing
- Build succeeded with only expected warnings
- Changes are isolated to SwiftUI detail view
- No impact on legacy Objective-C detail view
- Maintains consistency with existing app patterns

## Expected Outcomes
- Users will see distance in feet (more familiar unit for Burning Man context)
- Walk/bike time estimates help with planning navigation at the event
- "All Day" events now show specific hours for better planning

## Notes
- Uses Foundation's MeasurementFormatter for proper unit conversion instead of hardcoded factor
- TTTLocationFormatter already provides walking/biking time calculations with color coding
- These changes only affect the new SwiftUI detail screen, not the legacy implementation
- MeasurementFormatter provides locale-aware formatting and proper iOS patterns
1 change: 1 addition & 0 deletions iBurn/Detail/Models/DetailCellType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ enum DetailCellType {
case allHostEvents(count: Int, hostName: String)
case playaAddress(String, tappable: Bool)
case distance(CLLocationDistance)
case travelTime(CLLocationDistance)
case audio(BRCArtObject, isPlaying: Bool)
case userNotes(String)
case date(Date, format: String)
Expand Down
5 changes: 4 additions & 1 deletion iBurn/Detail/ViewModels/DetailViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,9 @@ class DetailViewModel: ObservableObject {
var timeString: String

if event.isAllDay {
timeString = "All Day"
let start = timeFormatter.string(from: startDate)
let end = timeFormatter.string(from: endDate)
timeString = "All Day (\(start) - \(end))"
} else {
let start = timeFormatter.string(from: startDate)
let end = timeFormatter.string(from: endDate)
Expand Down Expand Up @@ -618,6 +620,7 @@ class DetailViewModel: ObservableObject {
// Distance
if let distance = locationService.distanceToObject(dataObject) {
cells.append(.distance(distance))
cells.append(.travelTime(distance))
}

// User notes
Expand Down
34 changes: 32 additions & 2 deletions iBurn/Detail/Views/DetailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ struct DetailCellView: View {
case .distance(let distance):
DetailDistanceCell(distance: distance)

case .travelTime(let distance):
DetailTravelTimeCell(distance: distance)

case .userNotes(let notes):
DetailUserNotesCell(notes: notes)

Expand Down Expand Up @@ -247,7 +250,7 @@ struct DetailCellView: View {
return true
case .playaAddress(_, let tappable):
return tappable
case .text, .distance, .schedule, .date, .landmark, .eventType:
case .text, .distance, .travelTime, .schedule, .date, .landmark, .eventType:
return false
case .image:
return true
Expand Down Expand Up @@ -401,11 +404,38 @@ struct DetailDistanceCell: View {
HStack {
Image(systemName: "ruler")
.foregroundColor(themeColors.detailColor)
Text("Distance: \(distance, specifier: "%.0f") meters")
Text("Distance: \(formattedDistance)")
.foregroundColor(themeColors.detailColor)
Spacer()
}
}

private var formattedDistance: String {
let meters = Measurement(value: distance, unit: UnitLength.meters)
let feet = meters.converted(to: .feet)

let formatter = MeasurementFormatter()
formatter.unitStyle = .short
formatter.unitOptions = .providedUnit
formatter.numberFormatter.maximumFractionDigits = 0

return formatter.string(from: feet)
}
}

struct DetailTravelTimeCell: View {
let distance: CLLocationDistance
@Environment(\.themeColors) var themeColors

var body: some View {
if let attributedString = TTTLocationFormatter.brc_humanizedString(forDistance: distance) {
HStack {
Text(AttributedString(attributedString))
.frame(maxWidth: .infinity, alignment: .leading)
Spacer()
}
}
}
}

struct DetailUserNotesCell: View {
Expand Down
Loading