Siri: Directions to Cheapest [fuel] AppShortcuts — OpenURLIntent hands off to Apple Maps (universal link)

This commit is contained in:
FuelBoard Contributor
2026-08-14 13:55:03 +01:00
parent a3b6f37843
commit caadf184f2
3 changed files with 127 additions and 0 deletions
+104
View File
@@ -125,6 +125,67 @@ struct CheapestFuelIntent: AppIntent {
}
}
// MARK: - Directions intent
/// Opens Apple Maps with turn-by-turn directions to the cheapest station
/// selling `fuel` within the saved search radius. Shares the exact same
/// radius-scoped lookup as `CheapestFuelIntent`; the only difference is the
/// result it hands off to Maps instead of speaking the price.
struct DirectionsToCheapestFuelIntent: AppIntent {
static var title: LocalizedStringResource = "Directions to Cheapest Fuel Near Me"
static var description = IntentDescription(
"Opens Apple Maps directions to the cheapest station selling a fuel near you, using the latest cached prices."
)
@Parameter(title: "Fuel")
var fuel: FuelType
init() {
self.fuel = .e10
}
init(fuel: FuelType) {
self.fuel = fuel
}
func perform() async throws -> some IntentResult & OpensIntent {
let stations = FuelStore.loadStations()
guard !stations.isEmpty else {
throw DirectionsError("I don't have any price data yet. Open FuelBoard once to download the latest prices, then ask me again.")
}
guard let coordinate = FuelStore.loadLocationWithDate()?.coordinate else {
throw DirectionsError("I don't know your location yet. Open FuelBoard and allow location access, then ask me again.")
}
let radiusMiles = Double(FuelStore.loadStationLimit())
guard let station = SiriCheapestLookup.cheapest(
in: stations,
fuel: fuel,
fromLat: coordinate.lat,
lng: coordinate.lng,
withinMiles: radiusMiles
) else {
let fuelName = fuel.displayName.lowercased()
let radiusText = radiusMiles == 1 ? "1 mile" : "\(Int(radiusMiles)) miles"
throw DirectionsError("I couldn't find any station selling \(fuelName) within \(radiusText) of you.")
}
let url = SiriCheapestLookup.mapsURL(latitude: station.lat, longitude: station.lng)
return .result(opensIntent: OpenURLIntent(url))
}
}
/// Localized error thrown when directions can't be produced (no data, no
/// location, or no station within the radius). Siri presents the message
/// directly.
private struct DirectionsError: LocalizedError {
let message: String
init(_ message: String) { self.message = message }
var errorDescription: String? { message }
}
// MARK: - Snippets
/// Price card shown in Shortcuts / Siri results.
@@ -227,5 +288,48 @@ struct FuelBoardShortcuts: AppShortcutsProvider {
shortTitle: "Cheapest Diesel",
systemImageName: "fuelpump"
)
// Directions separate intent so the price queries stay answer-only
// and only the explicit directions query hands off to Apple Maps.
// Phrases use direction verbs ("directions to", "get directions") to
// stay distinct from the price shortcut phrases.
AppShortcut(
intent: DirectionsToCheapestFuelIntent(),
phrases: [
"Ask \(.applicationName) for directions to the cheapest \(\.$fuel) near me",
],
shortTitle: "Directions to Cheapest Fuel",
systemImageName: "map"
)
AppShortcut(
intent: DirectionsToCheapestFuelIntent(fuel: .e10),
phrases: [
"Ask \(.applicationName) for directions to the cheapest unleaded near me",
"Get directions to the cheapest petrol near me \(.applicationName)",
],
shortTitle: "Directions to Cheapest Unleaded",
systemImageName: "map"
)
AppShortcut(
intent: DirectionsToCheapestFuelIntent(fuel: .e5),
phrases: [
"Ask \(.applicationName) for directions to the cheapest premium near me",
"Get directions to the cheapest super unleaded near me \(.applicationName)",
],
shortTitle: "Directions to Cheapest Premium",
systemImageName: "map"
)
AppShortcut(
intent: DirectionsToCheapestFuelIntent(fuel: .diesel),
phrases: [
"Ask \(.applicationName) for directions to the cheapest diesel near me",
"Get directions to the cheapest diesel near me \(.applicationName)",
],
shortTitle: "Directions to Cheapest Diesel",
systemImageName: "map"
)
}
}