diff --git a/FuelBoard/ProximityMonitor.swift b/FuelBoard/ProximityMonitor.swift index ee00a1d..5bbd82e 100644 --- a/FuelBoard/ProximityMonitor.swift +++ b/FuelBoard/ProximityMonitor.swift @@ -209,13 +209,13 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca ] let identifier = UUID().uuidString - // Deliver the notification IMMEDIATELY — the alert must never wait on - // the map. If the snapshot later succeeds, the same identifier is used - // to replace the delivered notification with the map attached. + // 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…") - UNUserNotificationCenter.current().add( - UNNotificationRequest(identifier: identifier, content: content, trigger: nil) - ) let options = MKMapSnapshotter.Options() options.region = MKCoordinateRegion( @@ -226,24 +226,28 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca options.mapType = .standard let snapshotter = MKMapSnapshotter(options: options) - // Timeout so a hung snapshot can't leave the result line stuck on - // "preparing" forever. var finished = false + let deliver: (String) -> Void = { status in + guard !finished else { return } + finished = true + mapStatus?(status) + UNUserNotificationCenter.current().add( + UNNotificationRequest(identifier: identifier, content: content, trigger: nil) + ) + } + + // Timeout so a hung snapshot can't leave the alert undelivered (and + // the result line stuck on "preparing") forever. let timeout = DispatchWorkItem { Task { @MainActor in - guard !finished else { return } - finished = true - mapStatus?("map: timed out") + deliver("map: timed out — no image") } } - DispatchQueue.main.asyncAfter(deadline: .now() + 8, execute: timeout) + DispatchQueue.main.asyncAfter(deadline: .now() + 10, execute: timeout) snapshotter.start { [content] snapshot, error in timeout.cancel() Task { @MainActor in - guard !finished else { return } - finished = true - let finalContent = content var status = "map: no image" if let snapshot, error == nil, let image = Self.mapImage(snapshot: snapshot, station: station) { @@ -251,18 +255,13 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca .appendingPathComponent("alert-map-\(UUID().uuidString).png") if let data = image.pngData(), (try? data.write(to: url)) != nil, let attachment = try? UNNotificationAttachment(identifier: "map", url: url, options: nil) { - finalContent.attachments = [attachment] + content.attachments = [attachment] status = "map: attached" } } else if let error { status = "map: snapshot failed (\(error.localizedDescription))" } - mapStatus?(status) - // Replace the delivered notification (same identifier) so the - // map appears in place. - UNUserNotificationCenter.current().add( - UNNotificationRequest(identifier: identifier, content: finalContent, trigger: nil) - ) + deliver(status) } } } diff --git a/build-tests/Logs/Launch/LogStoreManifest.plist b/build-tests/Logs/Launch/LogStoreManifest.plist new file mode 100644 index 0000000..236d5e2 --- /dev/null +++ b/build-tests/Logs/Launch/LogStoreManifest.plist @@ -0,0 +1,10 @@ + + + + + logFormatVersion + 12 + logs + + + diff --git a/build-tests/Logs/Localization/LogStoreManifest.plist b/build-tests/Logs/Localization/LogStoreManifest.plist new file mode 100644 index 0000000..236d5e2 --- /dev/null +++ b/build-tests/Logs/Localization/LogStoreManifest.plist @@ -0,0 +1,10 @@ + + + + + logFormatVersion + 12 + logs + + + diff --git a/build-tests/Logs/Package/LogStoreManifest.plist b/build-tests/Logs/Package/LogStoreManifest.plist new file mode 100644 index 0000000..236d5e2 --- /dev/null +++ b/build-tests/Logs/Package/LogStoreManifest.plist @@ -0,0 +1,10 @@ + + + + + logFormatVersion + 12 + logs + + + diff --git a/build-tests/Logs/Test/LogStoreManifest.plist b/build-tests/Logs/Test/LogStoreManifest.plist new file mode 100644 index 0000000..236d5e2 --- /dev/null +++ b/build-tests/Logs/Test/LogStoreManifest.plist @@ -0,0 +1,10 @@ + + + + + logFormatVersion + 12 + logs + + +