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() ) } }