@@ -11,18 +11,26 @@ import SwiftUI
1111import MapLibre
1212import LXMFSwift
1313
14+ /// Returns the OpenFreeMap style URL for the active color scheme.
15+ /// MLNOfflineStorage caches the style JSON + tiles during region download,
16+ /// so loading this URL offline serves everything from the local cache —
17+ /// but cached regions are pinned to one style at download time, so the
18+ /// dark style assets are not served offline if a region was downloaded
19+ /// while light was active. TODO(#59 follow-up): cache both style packs.
20+ func mapStyleURL( forDarkMode dark: Bool ) -> URL {
21+ URL ( string: dark
22+ ? " https://tiles.openfreemap.org/styles/dark "
23+ : " https://tiles.openfreemap.org/styles/liberty " ) !
24+ }
25+
1426@available ( iOS 17 . 0 , * )
1527struct MapLibreMapView : UIViewRepresentable {
1628 @Binding var centerOnUser : Bool
1729 @Binding var metersPerPixel : Double
1830 var showsUserLocation : Bool
1931 var peerLocations : [ PeerLocation ]
2032 var httpEnabled : Bool
21-
22- /// Style URL from OpenFreeMap — used for both online and offline modes.
23- /// MLNOfflineStorage caches the style JSON + tiles during region download,
24- /// so loading this URL offline serves everything from the local cache.
25- private static let styleURL = URL ( string: " https://tiles.openfreemap.org/styles/liberty " ) !
33+ var isDark : Bool
2634
2735 func makeUIView( context: Context ) -> MLNMapView {
2836 // Set up network delegate to block HTTP when toggle is off.
@@ -31,7 +39,9 @@ struct MapLibreMapView: UIViewRepresentable {
3139 context. coordinator. httpEnabled = httpEnabled
3240 MLNNetworkConfiguration . sharedManager. delegate = context. coordinator
3341
34- let mapView = MLNMapView ( frame: . zero, styleURL: Self . styleURL)
42+ let initialStyleURL = mapStyleURL ( forDarkMode: isDark)
43+ context. coordinator. lastStyleURL = initialStyleURL
44+ let mapView = MLNMapView ( frame: . zero, styleURL: initialStyleURL)
3545 mapView. autoresizingMask = [ . flexibleWidth, . flexibleHeight]
3646 mapView. showsUserLocation = showsUserLocation
3747 mapView. delegate = context. coordinator
@@ -53,6 +63,15 @@ struct MapLibreMapView: UIViewRepresentable {
5363 // Update network blocking state when HTTP toggle changes
5464 context. coordinator. httpEnabled = httpEnabled
5565
66+ // Swap style URL when color scheme changes; lastStyleURL avoids
67+ // a no-op assignment (which would still trigger a reload) on every
68+ // peer-location tick.
69+ let desiredStyleURL = mapStyleURL ( forDarkMode: isDark)
70+ if context. coordinator. lastStyleURL != desiredStyleURL {
71+ context. coordinator. lastStyleURL = desiredStyleURL
72+ mapView. styleURL = desiredStyleURL
73+ }
74+
5675 if centerOnUser {
5776 DispatchQueue . main. async {
5877 centerOnUser = false
@@ -131,6 +150,11 @@ struct MapLibreMapView: UIViewRepresentable {
131150 /// Whether HTTP tile fetching is allowed.
132151 var httpEnabled = true
133152
153+ /// Last style URL applied to the underlying MLNMapView; used to skip
154+ /// no-op assignments on the frequent SwiftUI updates that don't change
155+ /// the color scheme.
156+ var lastStyleURL : URL ?
157+
134158 /// Tracks peer annotations by hash for efficient updates.
135159 var peerAnnotations : [ Data : PeerPointAnnotation ] = [ : ]
136160
0 commit comments