From b1889dacf5f0e9ed8803336a2016be96e9c50d8d Mon Sep 17 00:00:00 2001 From: FuelBoard Contributor Date: Wed, 12 Aug 2026 11:19:51 +0100 Subject: [PATCH] Tie alerts attach the app icon explicitly LiveContainer shows its own icon in the notification header, so tied alerts (which carry no map) now attach the app's compiled AppIcon60x60@2x.png so the FuelBoard identity shows as the banner thumbnail and in the expanded view. Single-station alerts keep the map embed. --- FuelBoard/ProximityMonitor.swift | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/FuelBoard/ProximityMonitor.swift b/FuelBoard/ProximityMonitor.swift index c298ff7..b5c4ee9 100644 --- a/FuelBoard/ProximityMonitor.swift +++ b/FuelBoard/ProximityMonitor.swift @@ -261,11 +261,19 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca // 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. + // action buttons. Deliver immediately with the choice buttons, and + // attach the app icon so the FuelBoard identity shows explicitly + // (the notification header icon is the container's inside + // LiveContainer, so the banner's right-hand thumbnail is the icon). if !ties.isEmpty { self.registerTieCategory(identifier: identifier, ties: ties) content.categoryIdentifier = "tie-\(identifier)" - mapStatus?("map: none (tie — pick a station)") + if let icon = Self.appIconAttachment() { + content.attachments = [icon] + mapStatus?("map: none (tie) · icon: attached") + } else { + mapStatus?("map: none (tie — pick a station)") + } UNUserNotificationCenter.current().add( UNNotificationRequest(identifier: identifier, content: content, trigger: nil) ) @@ -365,6 +373,17 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca } } + /// The app's own icon as a notification attachment, so the FuelBoard + /// identity shows explicitly even though the notification header icon is + /// the container's inside LiveContainer. Pulls the compiled + /// AppIcon60x60@2x.png straight from the bundle. + private static func appIconAttachment() -> UNNotificationAttachment? { + guard let url = Bundle.main.url(forResource: "AppIcon60x60@2x", withExtension: "png") else { + return nil + } + return try? UNNotificationAttachment(identifier: "icon", url: url, options: nil) + } + /// Fires a test alert built from REAL data: the cheapest station selling /// the monitored fuel within the configured alert radius of the current /// location — the same criteria a live geofence entry would apply, minus