Tie alerts: no map, body tap doesn't direct

A tied-cheapest notification now delivers immediately with the choice
buttons and NO map snapshot (a map would only show one arbitrary
station). Tapping the notification body of a tie no longer opens
directions — nothing has been chosen; only the option buttons trigger
directions. Single-station alerts keep the embedded map + tap-to-route.
This commit is contained in:
FuelBoard Contributor
2026-08-12 11:05:21 +01:00
parent 9f579051e5
commit 6f4b6882c9
+27 -14
View File
@@ -259,12 +259,25 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
}
let identifier = UUID().uuidString
// Render the map FIRST, then deliver ONE notification with the map
// attached. (Earlier, delivering immediately and "replacing" via a
// second add() showed up as two notifications in LiveContainer the
// replace-in-place contract isn't honoured there.) A timeout
// guarantees the alert still fires, without the map, if the snapshot
// hangs.
// Tie case: no map. A snapshot would only show one arbitrary station
// (the primary), which is misleading the user must pick from the
// action buttons. Deliver immediately with the choice buttons.
if !ties.isEmpty {
self.registerTieCategory(identifier: identifier, ties: ties)
content.categoryIdentifier = "tie-\(identifier)"
mapStatus?("map: none (tie — pick a station)")
UNUserNotificationCenter.current().add(
UNNotificationRequest(identifier: identifier, content: content, trigger: nil)
)
return
}
// Single-station case: render the map FIRST, then deliver ONE
// notification with the map attached. (Earlier, delivering
// immediately and "replacing" via a second add() showed up as two
// notifications in LiveContainer the replace-in-place contract
// isn't honoured there.) A timeout guarantees the alert still fires,
// without the map, if the snapshot hangs.
mapStatus?("map: preparing…")
let options = MKMapSnapshotter.Options()
@@ -280,10 +293,6 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
let deliver: (String) -> Void = { status in
guard !finished else { return }
finished = true
if !ties.isEmpty {
self.registerTieCategory(identifier: identifier, ties: ties)
content.categoryIdentifier = "tie-\(identifier)"
}
mapStatus?(status)
UNUserNotificationCenter.current().add(
UNNotificationRequest(identifier: identifier, content: content, trigger: nil)
@@ -491,14 +500,16 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
///
/// When the notification carried tie-choice action buttons, the tapped
/// button's identifier ("tie_0", "tie_1", ) selects the corresponding
/// station from userInfo["tieStations"]; tapping the body itself falls
/// back to the primary station.
/// station from userInfo["tieStations"]. Tapping the body of a tie
/// notification does NOT open directions nothing has been chosen yet;
/// only the option buttons make a choice.
nonisolated func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
let userInfo = response.notification.request.content.userInfo
let isTie = userInfo["tieStations"] != nil
let name = userInfo["stationName"] as? String
let lat = userInfo["stationLat"] as? Double
let lng = userInfo["stationLng"] as? Double
@@ -511,12 +522,14 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
let tieLat = ties[index]["lat"] as? Double,
let tieLng = ties[index]["lng"] as? Double {
openDirections(to: tieName, latitude: tieLat, longitude: tieLng)
} else if let name, let lat, let lng {
} else if !isTie, let name, let lat, let lng {
openDirections(to: name, latitude: lat, longitude: lng)
}
}
// Tie body tap: intentionally no directions the user must pick
// an option button to choose a station.
completionHandler()
}
}
/// Opens Apple Maps with driving directions to the station; falls back to
/// the in-app map sheet when the hand-off fails.