Files
fuelboard/FuelBoard/WidgetMockScreen.swift
T
FuelBoard Contributor 015368faaf Real iPhone wallpaper + populated Favourites captures
- PreviewWallpaper image set: the actual iPhone wallpaper extracted from the
  iOS 26.3 sim runtime (ActionButtonSelector Display.ca, 1320x2870 native
  res, JPEG ~180 KB) — replaces the gradient backdrop in the widget mock
- -seedFavourite <substring> launch hook: pins the first matching station
  for Unleaded via the normal keychain+app-group save path, so the
  Favourites tab can be captured populated (Ring Road Service Station,
  129.9, 59.1 mi, TOP badge)
- Re-captured 2-favourites (light), 6-favourites-dark, 9-widgets-dark,
  10-widgets-light with real data
- 95/95 tests green; Release IPA rebuilt + re-served
2026-08-15 16:49:09 +01:00

86 lines
3.6 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import SwiftUI
import WidgetKit
/// Full-screen widget preview (launch arg `-widgets`): the real app icon
/// plus the REAL widget faces (Shared/FuelPriceWidgetViews.swift — the same
/// code the widget extension renders) at small + medium sizes. Used for App
/// Store screenshot captures; not reachable from the UI.
struct WidgetMockScreen: View {
var body: some View {
ZStack {
// Real iPhone wallpaper (extracted from the iOS 26.3 sim runtime —
// ActionButtonSelector Display.ca asset, 1320×2870 native res).
Image("PreviewWallpaper")
.resizable()
.scaledToFill()
.ignoresSafeArea()
VStack(alignment: .leading, spacing: 26) {
// App icon + name, home-screen style
HStack(spacing: 16) {
Image("AppIconPreview")
.resizable()
.frame(width: 76, height: 76)
.clipShape(RoundedRectangle(cornerRadius: 17, style: .continuous))
VStack(alignment: .leading, spacing: 3) {
Text("FuelBoard")
.font(.title2.bold())
.foregroundStyle(.white)
.shadow(radius: 2, y: 1)
Text("Cheapest fuel near you")
.font(.subheadline)
.foregroundStyle(.white.opacity(0.9))
.shadow(radius: 2, y: 1)
}
}
.padding(.top, 8)
widgetCard(.systemSmall, label: "Small widget")
widgetCard(.systemMedium, label: "Medium widget")
Spacer(minLength: 0)
}
.padding(30)
}
}
private func widgetCard(_ family: WidgetFamily, label: String) -> some View {
// Real widget proportions: system small content is 158×158pt,
// medium 338×158pt (card adds the 14pt padding each side).
let contentW: CGFloat = family == .systemSmall ? 158 : 338
let cardW: CGFloat = contentW + 28
let cardH: CGFloat = contentW + 28
return VStack(alignment: .leading, spacing: 10) {
Text(label.uppercased())
.font(.caption.weight(.semibold))
.tracking(1)
.foregroundStyle(.secondary)
FuelPriceWidgetContent(entry: mockEntry(family: family), family: family, isWidget: false)
.padding(14)
.frame(width: cardW, height: cardH, alignment: .leading)
.background(Color(.systemBackground), in: RoundedRectangle(cornerRadius: 24, style: .continuous))
}
}
/// Real stations (loaded dump), cheapest-first for the chosen fuel — the
/// same selection the widget's own provider makes.
private func mockEntry(family: WidgetFamily) -> FuelPriceWidgetEntryData {
let fuel = FuelType.e10
let all = FuelStore.loadStations()
let selling = all.filter { $0.prices[fuel] != nil }
.sorted { ($0.prices[fuel] ?? .infinity) < ($1.prices[fuel] ?? .infinity) }
let location = FuelStore.loadLocation().map { Coordinate(lat: $0.lat, lng: $0.lng) }
let count = family == .systemSmall ? 1 : 3
return FuelPriceWidgetEntryData(
date: Date(),
stations: Array(selling.prefix(count)),
fuel: fuel,
sort: .cheapest,
isFavourites: false,
location: location,
locationSource: location != nil ? "live" : "none",
unit: FuelStore.loadDistanceUnit()
)
}
}