- Small widget card sized to actual system-small content (158×158pt + padding) instead of filling available width; medium keeps 338×158pt - Wallpaper now mimics the iOS default (dark navy→black in dark mode, soft blue-grey in light) via colorScheme-adaptive gradient - Added 10-widgets-light.png; re-captured 9-widgets-dark.png with data - 95/95 tests green; Release IPA rebuilt + re-served
108 lines
4.4 KiB
Swift
108 lines
4.4 KiB
Swift
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 {
|
||
@Environment(\.colorScheme) private var colorScheme
|
||
|
||
var body: some View {
|
||
ZStack {
|
||
wallpaper
|
||
.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(.primary)
|
||
Text("Cheapest fuel near you")
|
||
.font(.subheadline)
|
||
.foregroundStyle(.secondary)
|
||
}
|
||
}
|
||
.padding(.top, 8)
|
||
|
||
widgetCard(.systemSmall, label: "Small widget")
|
||
widgetCard(.systemMedium, label: "Medium widget")
|
||
|
||
Spacer(minLength: 0)
|
||
}
|
||
.padding(30)
|
||
}
|
||
}
|
||
|
||
/// iOS-default-style wallpaper (dark navy → black in dark mode, soft
|
||
/// blue-grey in light), matching the system default look.
|
||
private var wallpaper: some View {
|
||
Group {
|
||
if colorScheme == .dark {
|
||
LinearGradient(
|
||
colors: [
|
||
Color(red: 0.09, green: 0.14, blue: 0.26),
|
||
Color(red: 0.05, green: 0.08, blue: 0.15),
|
||
Color(red: 0.02, green: 0.03, blue: 0.06)
|
||
],
|
||
startPoint: .topLeading, endPoint: .bottomTrailing
|
||
)
|
||
} else {
|
||
LinearGradient(
|
||
colors: [
|
||
Color(red: 0.72, green: 0.80, blue: 0.94),
|
||
Color(red: 0.85, green: 0.90, blue: 0.97),
|
||
Color(red: 0.94, green: 0.96, blue: 0.99)
|
||
],
|
||
startPoint: .topLeading, endPoint: .bottomTrailing
|
||
)
|
||
}
|
||
}
|
||
}
|
||
|
||
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()
|
||
)
|
||
}
|
||
}
|