live activity: explicit badge (dark circle + bright pump); fix alignment look

fuelpump.circle.fill's first hierarchical style hits the PUMP, not the
circle, so the earlier darkened colour landed on the pump and the circle
stayed white (user: 'I didn't want the fuel pump darker I wanted the
white circle darker'). Rebuild the brand glyph from two explicit shapes:
a light-grey (.86) Circle badge + a bright fuel-tinted fuelpump.fill, so
circle vs pump colours are unambiguous and the badge centres cleanly with
the two-line text block.

Add a DEBUG-only -qaLiveActivity <fuel> launch hook that starts a Live
Activity with a long station name so the Lock Screen can be rendered in
the Simulator and verified by pixels (pump bright green 43,193,81; badge
grey 202,201,202).
This commit is contained in:
FuelBoard Contributor
2026-08-19 22:46:57 +01:00
parent bdfbbc605f
commit 1d62204a7a
2 changed files with 64 additions and 11 deletions
+43
View File
@@ -1,7 +1,22 @@
import ActivityKit
import SwiftUI import SwiftUI
@main @main
struct FuelBoardApp: App { struct FuelBoardApp: App {
init() {
#if DEBUG
// QA hook (Debug builds only): `-qaLiveActivity e10|e5|diesel` starts a
// Live Activity with a long station name so the Lock Screen / island
// layout can be rendered in the Simulator for visual QA.
let args = ProcessInfo.processInfo.arguments
if let idx = args.firstIndex(of: "-qaLiveActivity"),
args.indices.contains(idx + 1),
let fuel = FuelType(rawValue: args[idx + 1]) {
startQALiveActivity(fuel: fuel)
}
#endif
}
var body: some Scene { var body: some Scene {
WindowGroup { WindowGroup {
ContentView() ContentView()
@@ -9,6 +24,34 @@ struct FuelBoardApp: App {
} }
} }
#if DEBUG
private func startQALiveActivity(fuel: FuelType) {
let state = FuelBoardLiveActivityAttributes.ContentState(
fuel: fuel,
stationID: "qa-phoenix",
stationName: "Phoenix Filling Stations",
brand: "Phoenix",
pricePence: 1499,
priceDisplayStyle: FuelStore.loadPriceDisplayStyle(),
distanceKM: 8.0,
lat: 51.5,
lng: -0.12,
updatedAt: Date()
)
let attrs = FuelBoardLiveActivityAttributes()
do {
let activity = try Activity.request(
attributes: attrs,
content: .init(state: state, staleDate: nil),
pushType: nil
)
print("QA-LIVE-ACTIVITY STARTED id=\(activity.id)")
} catch {
print("QA-LIVE-ACTIVITY FAILED: \(error)")
}
}
#endif
/// Handles deep links that end up in the app. Widget taps arrive here in /// Handles deep links that end up in the app. Widget taps arrive here in
/// two cases: /// two cases:
/// - legacy/cached widget timelines using the `fuelboard://` relay, or /// - legacy/cached widget timelines using the `fuelboard://` relay, or
@@ -73,12 +73,13 @@ private struct FuelBoardLiveActivityView: View {
/// "ideal" width past the iPhone Lock Screen and collapses the full card). /// "ideal" width past the iPhone Lock Screen and collapses the full card).
private let compactWidthThreshold: CGFloat = 280 private let compactWidthThreshold: CGFloat = 280
/// Slightly darkened fuel tint for the pump circle so the white pump /// The badge circle behind the pump. The user calls this "the white
/// symbol keeps contrast against the bright Lock Screen / card background /// circle" and wants it slightly darkened for contrast against the bright
/// (the raw palette colours like yellow #FFD60A are too light to sit under /// fuel pump. Built as an explicit grey disc (the light-grey "white circle
/// a white glyph). /// darker") NOT part of the SF Symbol glyph, so it can never swallow the
private var pumpCircleColor: Color { /// darkened colour the way `fuelpump.circle.fill` did.
context.state.fuel.tintColor.mix(with: .black, by: 0.18) private var badgeCircleColor: Color {
Color(white: 0.86)
} }
var body: some View { var body: some View {
@@ -107,10 +108,19 @@ private struct FuelBoardLiveActivityView: View {
/// Full three-column design (unchanged): brand glyph · fuel+station · price. /// Full three-column design (unchanged): brand glyph · fuel+station · price.
private var richBody: some View { private var richBody: some View {
HStack(spacing: 12) { HStack(spacing: 12) {
// LEFT station brand glyph // LEFT station brand badge: an explicit darkened circle with a
Image(systemName: "fuelpump.circle.fill") // bright fuel-tinted pump. Built from two shapes so the circle
.font(.system(size: 32)) // colour and pump colour are unambiguous (the myth that
.foregroundStyle(pumpCircleColor, .white) // fuelpump.circle.fill's first style is the circle is what put the
// darkened colour on the pump).
ZStack {
Circle()
.fill(badgeCircleColor)
.frame(width: 40, height: 40)
Image(systemName: "fuelpump.fill")
.font(.system(size: 19, weight: .semibold))
.foregroundStyle(context.state.fuel.tintColor)
}
.frame(width: 40, height: 40) .frame(width: 40, height: 40)
// MIDDLE fuel + station // MIDDLE fuel + station