Widgets: merge small+medium into one kind (both sizes, one gallery entry)

This commit is contained in:
FuelBoard Contributor
2026-08-14 09:52:50 +01:00
parent e62177ae2e
commit 3dd567a5cc
3 changed files with 20 additions and 100 deletions
+17 -50
View File
@@ -17,13 +17,14 @@ private extension FuelType {
}
}
// FuelBoard widget petrol stations near you.
// FuelPriceWidget (medium): top 3 stations with price + distance, each row
// opens Maps. Per-widget fuel + sort (+ distance for Cheapest).
// FuelPriceSmallWidget (small): single station, whole widget opens Maps.
// Same knobs as the medium the small face shows the first of the
// configured result (cheapest/closest station, or the cheapest favourite
// of the chosen fuel in Favourites mode).
// FuelBoard widget petrol stations near you. ONE widget kind, TWO sizes:
// .systemSmall: single station (the first of the configured result the
// cheapest/closest station, or the cheapest favourite of the chosen fuel
// in Favourites mode); the whole face opens Maps.
// .systemMedium: top 3 stations with price + distance, each row opens Maps.
// Per-widget fuel + sort (+ distance for Cheapest) via one config intent.
// The view branches on widgetFamily, not kind the small face renders the
// first station, the medium face the list.
// Taps deep-link to Apple Maps directions (maps://?daddr=). On the Home
// Screen the system either opens Maps directly or delivers the URL to
// FuelBoard, whose onOpenURL forwards it (and also still handles legacy
@@ -49,6 +50,13 @@ private extension FuelType {
// (no permission yet / timeout) it falls back to the app's cached location,
// then to price-only sorting. So the widget is location-driven the moment the
// app has been opened once and permission granted.
//
// History: a separate "small" kind existed (FuelPriceWidgetSmall) and was
// merged here on 2026-08-14. The small kind had gained .systemMedium so the
// iOS long-press app-icon menu (which shows only the FIRST-registered kind's
// sizes) would offer both tiles but that duplicated the medium gallery
// entry. Merging keeps both size tiles in the icon menu AND one gallery entry
// with both sizes.
struct FuelPriceWidget: Widget {
let kind = "FuelPriceWidget"
@@ -70,49 +78,8 @@ struct FuelPriceWidget: Widget {
}
.configurationDisplayName("FuelBoard Prices")
.description("Fuel prices near you. Configure fuel + sort per widget.")
.supportedFamilies([.systemMedium])
.disfavoredLocations([.carPlay], for: [.systemMedium])
}
}
// Small widget exactly ONE station (the first of the configured result)
// when rendered at systemSmall; the SAME kind also supports .systemMedium,
// where the shared view renders the station list (identical content to the
// medium widget the view branches on family, not kind).
//
// WHY medium is here (2026-08-14): the iOS 18+ long-press app-icon menu
// ("turn app icon into a widget") shows the supported SIZES of the
// FIRST-registered widget kind only it does NOT list widget kinds, and it
// is NOT keyed by configuration-intent type (a two-intent experiment,
// 6375af4, changed nothing on-device). So the bundle's first kind decides
// which size tiles the icon menu offers: small-only meant the menu showed
// only the small tile even though the app has a medium widget. Giving this
// first-registered kind BOTH .systemSmall and .systemMedium puts both size
// tiles in the icon menu (ChatGPT/Safari show multiple sizes the same way
// their first kind supports several families). The gallery still lists both
// widget kinds in bundle order (small, then medium); this kind's entry just
// gains a medium variant. Favourites sort on the small face shows the
// cheapest favourite of the chosen fuel.
struct FuelPriceSmallWidget: Widget {
let kind = "FuelPriceWidgetSmall"
var body: some WidgetConfiguration {
AppIntentConfiguration(
kind: kind,
intent: FuelBoardSmallWidgetConfigurationIntent.self,
provider: FuelPriceTimelineProvider<FuelBoardSmallWidgetConfigurationIntent>(
beaconTag: "FuelBoardSmallWidget"
)
) { entry in
FuelPriceWidgetView(entry: entry)
.containerBackground(for: .widget) {
Color(.systemBackground)
}
}
.configurationDisplayName("FuelBoard Small")
.description("Fuel prices near you. Configure fuel + sort per widget.")
.supportedFamilies([.systemSmall, .systemMedium])
.disfavoredLocations([.carPlay], for: [.systemSmall])
.disfavoredLocations([.carPlay], for: [.systemSmall, .systemMedium])
}
}
@@ -250,7 +217,7 @@ struct FuelPriceTimelineProvider<Configuration: WidgetConfigurationIntent & Widg
// the cheapest favourite of the chosen fuel. (The old per-widget
// pinned-favourite picker was removed: its AppEntity params made
// fresh-widget default-config resolution fail at the system level
// see FuelPriceSmallWidget.)
// the merged widget uses the minimal fuel/sort/distance intent.)
let fuelFavourites = favourites
.filter { $0.fuel == fuel && $0.station.prices[fuel] != nil }
.map(\.station)