Widget config sheet: revert WidgetSort to String-backed AppEnum. parameterSummary When(\.$sort, .equalTo, …) silently falls back to the otherwise branch for AppEntity parameters (iOS 17+ bug FB13263902), which hid the Favourite/Favourite Fuel rows on the small widget — the metadata compared against a literal 'WidgetSort.favourites' string instead of the enum case. String AppEnums match reliably (the d8506a0 form). Tradeoff: the Sort picker always offers Favourites; picking it with no favourites shows the empty state. FavouriteFuel entity + IntentParameterDependency filtering unchanged.
This commit is contained in:
@@ -21,48 +21,24 @@ enum WidgetFuel: String, AppEnum, CaseIterable, Codable {
|
||||
]
|
||||
}
|
||||
|
||||
// Per-widget sort order. Modelled as an AppEntity (not an AppEnum) so the
|
||||
// options can be dynamic: "Favourites" only appears when the user actually
|
||||
// has favourites — an empty favourite list makes the option dead weight.
|
||||
struct WidgetSort: AppEntity, Identifiable, Hashable, Codable {
|
||||
enum Kind: String, Codable {
|
||||
// Per-widget sort order. A String-backed AppEnum (NOT an AppEntity): the
|
||||
// parameterSummary conditionals (When(\.$sort, .equalTo, …)) fall back to the
|
||||
// otherwise branch for AppEntity parameters (iOS 17+ bug FB13263902), which
|
||||
// hid the Favourite picker. String AppEnums match reliably. Tradeoff: the
|
||||
// option set is static — "Favourites" always appears, and picking it with no
|
||||
// favourites shows the empty state.
|
||||
enum WidgetSort: String, AppEnum, CaseIterable, Codable {
|
||||
case cheapest
|
||||
case closest
|
||||
case favourites
|
||||
}
|
||||
|
||||
let id: String
|
||||
|
||||
var kind: Kind { Kind(rawValue: id) ?? .cheapest }
|
||||
|
||||
static let cheapest = WidgetSort(id: "cheapest")
|
||||
static let closest = WidgetSort(id: "closest")
|
||||
static let favourites = WidgetSort(id: "favourites")
|
||||
|
||||
var displayRepresentation: DisplayRepresentation {
|
||||
switch kind {
|
||||
case .cheapest: return DisplayRepresentation(stringLiteral: "Cheapest")
|
||||
case .closest: return DisplayRepresentation(stringLiteral: "Closest")
|
||||
case .favourites: return DisplayRepresentation(stringLiteral: "Favourites")
|
||||
}
|
||||
}
|
||||
|
||||
static var typeDisplayRepresentation: TypeDisplayRepresentation = "Sort by"
|
||||
static var defaultQuery = WidgetSortQuery()
|
||||
}
|
||||
|
||||
struct WidgetSortQuery: EntityQuery {
|
||||
func entities(for identifiers: [String]) async throws -> [WidgetSort] {
|
||||
identifiers.map { WidgetSort(id: $0) }
|
||||
}
|
||||
|
||||
func suggestedEntities() async throws -> [WidgetSort] {
|
||||
var sorts = [WidgetSort.cheapest, WidgetSort.closest]
|
||||
if !FuelStore.loadFavourites().isEmpty {
|
||||
sorts.append(.favourites)
|
||||
}
|
||||
return sorts
|
||||
}
|
||||
static var caseDisplayRepresentations: [WidgetSort: DisplayRepresentation] = [
|
||||
.cheapest: "Cheapest",
|
||||
.closest: "Closest",
|
||||
.favourites: "Favourites",
|
||||
]
|
||||
}
|
||||
|
||||
// Per-widget distance filter. Modelled as an AppEntity (not an AppEnum) so
|
||||
|
||||
Reference in New Issue
Block a user