From 38b47eea38accd314fe12940f8c66cb20cb07f8f Mon Sep 17 00:00:00 2001 From: FuelBoard Contributor Date: Thu, 13 Aug 2026 18:39:30 +0100 Subject: [PATCH] Widget gallery order + default-widget skeleton fix. (1) Register FuelPriceSmallWidget BEFORE FuelPriceWidget so the gallery lists small, then medium (bundle order = gallery order). (2) Revert entity resolution to LENIENT: the timeline request resolves the full configuration through the entity queries, and the b1765b5 strict entities(for:) (nil for the empty default favourite 'fuel|') failed resolution for default-config small widgets, stranding them on the iOS skeleton placeholder. entities(for:) now always returns a value; defaultResult() still auto-populates fresh widgets to the first fuel with a favourite / first favourite of that fuel. --- FuelBoardWidgets/FuelBoardWidgetsBundle.swift | 3 +- FuelBoardWidgets/WidgetConfigIntent.swift | 38 ++++++++++--------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/FuelBoardWidgets/FuelBoardWidgetsBundle.swift b/FuelBoardWidgets/FuelBoardWidgetsBundle.swift index 78a2a38..e38f95e 100644 --- a/FuelBoardWidgets/FuelBoardWidgetsBundle.swift +++ b/FuelBoardWidgets/FuelBoardWidgetsBundle.swift @@ -4,8 +4,9 @@ import SwiftUI @main struct FuelBoardWidgetsBundle: WidgetBundle { var body: some Widget { - FuelPriceWidget() + // Gallery order follows registration order: small first, then medium. FuelPriceSmallWidget() + FuelPriceWidget() FuelBoardLiveActivity() } } diff --git a/FuelBoardWidgets/WidgetConfigIntent.swift b/FuelBoardWidgets/WidgetConfigIntent.swift index a3e4465..fa7f43a 100644 --- a/FuelBoardWidgets/WidgetConfigIntent.swift +++ b/FuelBoardWidgets/WidgetConfigIntent.swift @@ -92,16 +92,14 @@ struct FavouriteFuel: AppEntity, Identifiable, Hashable, Codable { } struct FavouriteFuelQuery: EntityQuery { - /// Strict: a fuel only resolves if it ACTUALLY has favourites. A stored - /// value for a fuel that lost all its favourites (or the static .e10 - /// default on a fresh widget) fails resolution and falls back to - /// defaultResult() — the first fuel that has a favourite. + // LENIENT resolution: every valid fuel resolves, even one without + // favourites. The timeline request resolves the FULL configuration + // through these queries, and a nil result fails the whole timeline — a + // default-config widget would hang on the skeleton placeholder. Fresh + // widgets still auto-populate via defaultResult(); the picker options + // stay filtered in suggestedEntities(). func entities(for identifiers: [String]) async throws -> [FavouriteFuel] { - let fuels = Set(FuelStore.loadFavourites().map(\.fuel)) - return identifiers.compactMap { id in - guard let fuel = FuelType(rawValue: id), fuels.contains(fuel) else { return nil } - return FavouriteFuel(fuel: fuel) - } + identifiers.compactMap { FuelType(rawValue: $0) }.map { FavouriteFuel(fuel: $0) } } func suggestedEntities() async throws -> [FavouriteFuel] { @@ -162,18 +160,22 @@ struct WidgetFavouriteQuery: EntityQuery { ) var smallIntent + // LENIENT resolution: every stored identifier resolves to a + // WidgetFavourite (best-effort name lookup). NEVER return nil here — the + // timeline request resolves the whole configuration through this query + // and a failed resolution strands a default-config widget on the skeleton + // placeholder. Fresh widgets auto-populate via defaultResult(). func entities(for identifiers: [String]) async throws -> [WidgetFavourite] { let favourites = FuelStore.loadFavourites() - return identifiers.compactMap { id in - // Strict: only real, existing favourites resolve. The empty - // static default (id "fuel|") and removed favourites fail - // resolution so the sheet falls back to defaultResult(). - guard !id.hasSuffix("|"), - let entry = favourites.first(where: { $0.id == id }) else { return nil } + return identifiers.map { id in + let parts = id.split(separator: "|", maxSplits: 1) + let fuel = FuelType(rawValue: String(parts.first ?? "")) ?? .e10 + let stationID = String(parts.last ?? "") + let entry = favourites.first { $0.id == id } return WidgetFavourite( - fuel: entry.fuel, - stationID: entry.station.id, - stationName: entry.station.name + fuel: fuel, + stationID: stationID, + stationName: entry?.station.name ?? "" ) } }