diff --git a/FuelBoard/SiriShortcuts.swift b/FuelBoard/SiriShortcuts.swift index 7a550b0..ded13a0 100644 --- a/FuelBoard/SiriShortcuts.swift +++ b/FuelBoard/SiriShortcuts.swift @@ -15,7 +15,11 @@ import SwiftUI /// - Location: last-known location fallback (background CoreLocation from a /// Siri-launched process is slow/unreliable). /// - Phrases stay literal/boring for App Store review; `\.applicationName` -/// appears in one phrase per the review guidance. +/// appears in EVERY phrase (iOS 26 metadata-processor requirement — +/// without it the metadata exports ZERO utterances). +/// - Fuel case labels use UK speech ("Petrol", "Super Unleaded") so Siri's +/// phrase matching maps how people actually ask; the app UI's own +/// FuelType.displayName ("Unleaded") is unaffected. // MARK: - Fuel parameter @@ -23,8 +27,8 @@ extension FuelType: AppEnum { static var typeDisplayRepresentation: TypeDisplayRepresentation = "Fuel" static var caseDisplayRepresentations: [FuelType: DisplayRepresentation] = [ - .e10: "Unleaded", - .e5: "Premium", + .e10: "Petrol", + .e5: "Super Unleaded", .diesel: "Diesel", ] } @@ -40,6 +44,20 @@ struct CheapestFuelIntent: AppIntent { @Parameter(title: "Fuel") var fuel: FuelType + /// Plain construction — Siri resolves the fuel parameter from the + /// utterance. Defaults to petrol if the parameter is unresolved. + init() { + self.fuel = .e10 + } + + /// Fixed-fuel construction for the per-fuel App Shortcuts: the fuel word + /// becomes literal phrase text so Siri matches "unleaded"/"petrol"/ + /// "diesel" directly instead of resolving the parameter (which was flaky + /// on-device — "cheapest diesel" matched, "cheapest unleaded" didn't). + init(fuel: FuelType) { + self.fuel = fuel + } + func perform() async throws -> some IntentResult & ProvidesDialog & ShowsSnippetView & ReturnsValue { let stations = FuelStore.loadStations() @@ -162,15 +180,50 @@ struct CheapestFuelMessage: View { struct FuelBoardShortcuts: AppShortcutsProvider { static var appShortcuts: [AppShortcut] { + // Generic parameterized shortcut — matches whatever fuel word Siri + // resolves. Parameter resolution is flaky on-device ("cheapest diesel" + // matched, "cheapest unleaded" didn't), which is why the fixed-fuel + // entries below carry the fuel word as LITERAL phrase text. AppShortcut( intent: CheapestFuelIntent(), phrases: [ "Ask \(.applicationName) what's the cheapest \(\.$fuel) near me", - "Find the cheapest \(\.$fuel) near me \(.applicationName)", - "Cheapest \(\.$fuel) near me \(.applicationName)", ], shortTitle: "Cheapest Fuel", systemImageName: "fuelpump" ) + + AppShortcut( + intent: CheapestFuelIntent(fuel: .e10), + phrases: [ + "Ask \(.applicationName) for the cheapest unleaded near me", + "Ask \(.applicationName) for the cheapest petrol near me", + "Find the cheapest petrol near me \(.applicationName)", + ], + shortTitle: "Cheapest Petrol", + systemImageName: "fuelpump" + ) + + AppShortcut( + intent: CheapestFuelIntent(fuel: .e5), + phrases: [ + "Ask \(.applicationName) for the cheapest premium near me", + "Ask \(.applicationName) for the cheapest super unleaded near me", + "Find the cheapest super unleaded near me \(.applicationName)", + ], + shortTitle: "Cheapest Super Unleaded", + systemImageName: "fuelpump" + ) + + AppShortcut( + intent: CheapestFuelIntent(fuel: .diesel), + phrases: [ + "Ask \(.applicationName) for the cheapest diesel near me", + "Find the cheapest diesel near me \(.applicationName)", + "Cheapest diesel near me \(.applicationName)", + ], + shortTitle: "Cheapest Diesel", + systemImageName: "fuelpump" + ) } }