Compare commits
3
Commits
727ef6e58f
...
5d26509034
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d26509034 | ||
|
|
221b96097d | ||
|
|
b012232012 |
@@ -4,27 +4,25 @@
|
||||
// Shows the cheapest station for the pinned fuel within the app's chosen
|
||||
// radius. Tapping anywhere opens Apple Maps directions to that station.
|
||||
//
|
||||
// ADAPTIVE LAYOUT: ActivityConfiguration shares ONE content view across the
|
||||
// Lock Screen, banner, and the CarPlay small slot — there is no per-platform
|
||||
// closure. So this view provides two layouts and lets ViewThatFits pick by
|
||||
// available width:
|
||||
// • richBody — the full three-column design (glyph · fuel+station · price),
|
||||
// wins wherever there's Lock Screen width (it carries an
|
||||
// explicit minWidth so it can never be squeezed into the car).
|
||||
// • compactBody — a minimal price-strip (glyph+fuel+price, station caption
|
||||
// below) that wins in the CarPlay/Apple Watch Smart Stack
|
||||
// small slot.
|
||||
// ADAPTIVE LAYOUT: the Lock Screen body provides two layouts and lets
|
||||
// ViewThatFits pick by available width, but the narrow `.small` family is NOT
|
||||
// declared (see note on the config), so iPhone/iPad always render the full
|
||||
// three-column card (`richBody`) with proper text sizes. `compactBody` is kept
|
||||
// as a safety fallback should any surface ever hand this view a narrow width.
|
||||
//
|
||||
// IMPORTANT: `.supplementalActivityFamilies([.small])` is deliberately absent —
|
||||
// it made iOS render the squeezed `.small` card on the iPhone Lock Screen.
|
||||
// CarPlay's small form comes from the Dynamic Island compact closures.
|
||||
|
||||
import ActivityKit
|
||||
import SwiftUI
|
||||
import WidgetKit
|
||||
|
||||
/// The Live Activity itself — registered in the widget bundle alongside the
|
||||
/// regular price widget. No CarPlay entitlement involved: this renders on the
|
||||
/// Lock Screen, Dynamic Island, and the car display (CarPlay Ultra, iOS 26+).
|
||||
/// `.supplementalActivityFamilies([.small])` makes it eligible for the car's
|
||||
/// small Live Activity slot — display-only there (FuelBoard is not a
|
||||
/// CarPlay-enabled app, so car-side taps can't launch anything).
|
||||
/// regular price widget. No CarPlay entitlement involved: renders on the
|
||||
/// Lock Screen (full-width card on iPhone/iPad) and the Dynamic Island
|
||||
/// (incl. the island's compact form used in the car, display-only — FuelBoard
|
||||
/// is not a CarPlay-enabled app, so car-side taps can't launch anything).
|
||||
struct FuelBoardLiveActivity: Widget {
|
||||
var body: some WidgetConfiguration {
|
||||
ActivityConfiguration(for: FuelBoardLiveActivityAttributes.self) { context in
|
||||
@@ -51,7 +49,12 @@ struct FuelBoardLiveActivity: Widget {
|
||||
.font(.caption2.bold().monospacedDigit())
|
||||
}
|
||||
}
|
||||
.supplementalActivityFamilies([.small])
|
||||
// NOTE: deliberately NO `.supplementalActivityFamilies([.small])`.
|
||||
// That modifier makes iOS eligible to render this activity in the
|
||||
// narrow `.small` form on the iPhone/iPad Lock Screen, which is what
|
||||
// produced the squeezed, small-text card. Dropping it keeps the
|
||||
// full-width Lock Screen card on iPhone/iPad; CarPlay still shows a
|
||||
// small form via the Dynamic Island compact closures below.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,15 +64,17 @@ private struct FuelBoardLiveActivityView: View {
|
||||
|
||||
var body: some View {
|
||||
Link(destination: context.state.mapsURL) {
|
||||
ViewThatFits(in: .horizontal) {
|
||||
// rich first — wins on full-width Lock Screen / banner
|
||||
// Always the full three-column card. The station caption is
|
||||
// line-limited + scale-down + tail-truncated, so a LONG station
|
||||
// name truncates in place instead of inflating this view's ideal
|
||||
// width and tricking ViewThatFits into falling back to the compact
|
||||
// strip (that is exactly what made 5-mi / long-named activities
|
||||
// render small while 10-15-mi / short names stayed full).
|
||||
//
|
||||
// No ViewThatFits / compactBody: with `.supplementalActivityFamilies`
|
||||
// removed, this body is only ever handed Lock-Screen width, so the
|
||||
// compact fallback was both dead weight and the cause of the bug.
|
||||
richBody
|
||||
// CarPlay / Watch small slot is far narrower than this,
|
||||
// so ViewThatFits reliably falls through to compactBody.
|
||||
.frame(minWidth: 280)
|
||||
// compact fallback — the car's small supplemental slot
|
||||
compactBody
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +95,8 @@ private struct FuelBoardLiveActivityView: View {
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(1)
|
||||
.minimumScaleFactor(0.75)
|
||||
.truncationMode(.tail)
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
@@ -106,30 +113,7 @@ private struct FuelBoardLiveActivityView: View {
|
||||
.padding()
|
||||
}
|
||||
|
||||
/// Minimal strip for the small CarPlay / Watch Smart Stack slot:
|
||||
/// glyph + fuel left, bold price right, truncated station below.
|
||||
private var compactBody: some View {
|
||||
VStack(alignment: .leading, spacing: 3) {
|
||||
HStack(spacing: 5) {
|
||||
Image(systemName: "fuelpump.fill")
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.green)
|
||||
Text(context.state.fuel.displayName)
|
||||
.font(.caption2.weight(.semibold))
|
||||
.lineLimit(1)
|
||||
Spacer(minLength: 4)
|
||||
FuelStore.priceTextAttributed(context.state.pricePence,
|
||||
style: context.state.priceDisplayStyle,
|
||||
size: 15, weight: .bold)
|
||||
.lineLimit(1)
|
||||
}
|
||||
Text("\(context.state.stationName) · \(context.state.distanceText)")
|
||||
.font(.system(size: 9))
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
.padding(8)
|
||||
}
|
||||
// NOTE: `compactBody` was removed — always render `richBody` (see body).
|
||||
}
|
||||
|
||||
/// Dynamic Island expanded regions + compact trailing — price only.
|
||||
|
||||
Reference in New Issue
Block a user