live activity: select rich vs compact by actual GeometryReader width

ViewThatFits measures each child's IDEAL (untruncated) width to decide
fit, and a flexible .frame(maxWidth:.infinity) middle column does not cap
that ideal — so a long station name (e.g. 5-mi Phoenix Filling Stations)
inflated richBody's ideal past the iPhone Lock Screen width and fell back
to the compact strip. Replace the ViewThatFits branch with a
GeometryReader that reads the ACTUAL proposed width and shows the full
three-column card at/above 280pt, compact below. Content-independent, so a
long name can no longer collapse the iPhone card.
This commit is contained in:
FuelBoard Contributor
2026-08-19 22:08:07 +01:00
parent 227cce4aa6
commit a6620d36f7
@@ -65,27 +65,26 @@ struct FuelBoardLiveActivity: Widget {
private struct FuelBoardLiveActivityView: View { private struct FuelBoardLiveActivityView: View {
let context: ActivityViewContext<FuelBoardLiveActivityAttributes> let context: ActivityViewContext<FuelBoardLiveActivityAttributes>
/// Full card needs at least this much width; iPhone/iPad Lock Screen is /// Below this ACTUAL proposed width we show the compact strip (CarPlay
/// always wider, so they always get it. Only genuinely small slots /// small / Watch smart stack); at/above it we show the full card. The
/// (CarPlay small / Watch smart stack) fall through to `compactBody`. /// decision is made from the real space the system hands the body via
private let richMinWidth: CGFloat = 280 /// GeometryReader, NOT from ViewThatFits ideal-width measurement the
/// Cap the compact strip so a mid-width surface can't sneak it in. /// latter is broken for truncating text (a long station name inflates the
private let compactMaxWidth: CGFloat = 230 /// "ideal" width past the iPhone Lock Screen and collapses the full card).
private let compactWidthThreshold: CGFloat = 280
var body: some View { var body: some View {
Link(destination: context.state.mapsURL) { Link(destination: context.state.mapsURL) {
ViewThatFits(in: .horizontal) { GeometryReader { geo in
// rich FIRST wins on the full-width iPhone/iPad Lock Screen. // Branch on the ACTUAL proposed width. iPhone/iPad offer the
// Its middle column is flexible + line-limited, so a LONG // full Lock Screen width (>= threshold) rich card, no matter
// station name truncates in place and never inflates the ideal // how long the station name is. Truly small slots (CarPlay /
// width (which used to trick ViewThatFits into falling back to // Watch) offer much less compact strip.
// compact on iPhone). if geo.size.width >= compactWidthThreshold {
richBody richBody
.frame(minWidth: richMinWidth) } else {
// compact fallback the small CarPlay / Watch smart-stack
// strip: fuel · price · station distance (no app name).
compactBody compactBody
.frame(maxWidth: compactMaxWidth) }
} }
} }
} }