Siri: per-fuel App Shortcuts with literal fuel words (unleaded/petrol/premium/diesel) + UK case labels
This commit is contained in:
@@ -15,7 +15,11 @@ import SwiftUI
|
|||||||
/// - Location: last-known location fallback (background CoreLocation from a
|
/// - Location: last-known location fallback (background CoreLocation from a
|
||||||
/// Siri-launched process is slow/unreliable).
|
/// Siri-launched process is slow/unreliable).
|
||||||
/// - Phrases stay literal/boring for App Store review; `\.applicationName`
|
/// - 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
|
// MARK: - Fuel parameter
|
||||||
|
|
||||||
@@ -23,8 +27,8 @@ extension FuelType: AppEnum {
|
|||||||
static var typeDisplayRepresentation: TypeDisplayRepresentation = "Fuel"
|
static var typeDisplayRepresentation: TypeDisplayRepresentation = "Fuel"
|
||||||
|
|
||||||
static var caseDisplayRepresentations: [FuelType: DisplayRepresentation] = [
|
static var caseDisplayRepresentations: [FuelType: DisplayRepresentation] = [
|
||||||
.e10: "Unleaded",
|
.e10: "Petrol",
|
||||||
.e5: "Premium",
|
.e5: "Super Unleaded",
|
||||||
.diesel: "Diesel",
|
.diesel: "Diesel",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -40,6 +44,20 @@ struct CheapestFuelIntent: AppIntent {
|
|||||||
@Parameter(title: "Fuel")
|
@Parameter(title: "Fuel")
|
||||||
var fuel: FuelType
|
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<String> {
|
func perform() async throws -> some IntentResult & ProvidesDialog & ShowsSnippetView & ReturnsValue<String> {
|
||||||
let stations = FuelStore.loadStations()
|
let stations = FuelStore.loadStations()
|
||||||
|
|
||||||
@@ -162,15 +180,50 @@ struct CheapestFuelMessage: View {
|
|||||||
|
|
||||||
struct FuelBoardShortcuts: AppShortcutsProvider {
|
struct FuelBoardShortcuts: AppShortcutsProvider {
|
||||||
static var appShortcuts: [AppShortcut] {
|
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(
|
AppShortcut(
|
||||||
intent: CheapestFuelIntent(),
|
intent: CheapestFuelIntent(),
|
||||||
phrases: [
|
phrases: [
|
||||||
"Ask \(.applicationName) what's the cheapest \(\.$fuel) near me",
|
"Ask \(.applicationName) what's the cheapest \(\.$fuel) near me",
|
||||||
"Find the cheapest \(\.$fuel) near me \(.applicationName)",
|
|
||||||
"Cheapest \(\.$fuel) near me \(.applicationName)",
|
|
||||||
],
|
],
|
||||||
shortTitle: "Cheapest Fuel",
|
shortTitle: "Cheapest Fuel",
|
||||||
systemImageName: "fuelpump"
|
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"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user