ReviewOS

also looking at this

craft-native/craft

feat(maps): add key-free native Android maps and shared map controls

#363
Merged chris wants to merge codex/wildloop-native-map-providers into main
28 files +1857 -481

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

packages/ios/templates/CraftNativeScreen.swiftmodified+17-1
Changes to packages/ios/templates/CraftNativeScreen.swift
@@ -1233,6 +1233,7 @@ private final class CraftNativeMapView: MKMapView, MKMapViewDelegate {
12331233 var nextMarkers: [String: (coordinate: CLLocationCoordinate2D, title: String?)] = [:]
12341234 var nextHandlers: [String: String] = [:]
12351235 var nextPolylines: [String: (coordinates: [CLLocationCoordinate2D], color: UIColor, width: CGFloat)] = [:]
1236 var nextPolylineIDs: [String] = []
12361237 for (index, child) in children.enumerated() {
12371238 guard let node = child as? [String: Any], let rawType = node["type"] as? String else { continue }
12381239 let type = rawType.lowercased()
@@ -1258,6 +1259,7 @@ private final class CraftNativeMapView: MKMapView, MKMapViewDelegate {
12581259 let authoredWidth = Self.numeric(childProps["strokeWidth"]) ?? 3
12591260 let width = CGFloat(authoredWidth)
12601261 guard authoredWidth.isFinite, width.isFinite, width > 0 else { continue }
1262 if nextPolylines[id] == nil { nextPolylineIDs.append(id) }
12611263 nextPolylines[id] = (points, Self.color(childProps["strokeColor"] as? String), width)
12621264 }
12631265 }
@@ -1290,7 +1292,8 @@ private final class CraftNativeMapView: MKMapView, MKMapViewDelegate {
12901292 }
12911293 overlayCoordinatesByID.removeValue(forKey: id)
12921294 }
1293 for (id, value) in nextPolylines {
1295 for id in nextPolylineIDs {
1296 guard let value = nextPolylines[id] else { continue }
12941297 if let overlay = overlaysByID[id],
12951298 let coordinates = overlayCoordinatesByID[id],
12961299 Self.coordinatesEqual(coordinates, value.coordinates),
@@ -1310,6 +1313,19 @@ private final class CraftNativeMapView: MKMapView, MKMapViewDelegate {
13101313 overlayWidths[ObjectIdentifier(overlay)] = value.width
13111314 addOverlay(overlay)
13121315 }
1316 // Keep authored casing/foreground order when an earlier line changes
1317 // or retained children move. Exchanging native overlays preserves the
1318 // unchanged objects, tile levels and current camera.
1319 let ownedOverlayIDs = Set(overlaysByID.values.map { ObjectIdentifier($0) })
1320 var orderedOverlays = overlays.compactMap { $0 as? MKPolyline }
1321 .filter { ownedOverlayIDs.contains(ObjectIdentifier($0)) }
1322 for (index, id) in nextPolylineIDs.enumerated() {
1323 guard let overlay = overlaysByID[id], index < orderedOverlays.count,
1324 orderedOverlays[index] !== overlay,
1325 let previousIndex = orderedOverlays.firstIndex(where: { $0 === overlay }) else { continue }
1326 exchangeOverlay(orderedOverlays[index], with: orderedOverlays[previousIndex])
1327 orderedOverlays.swapAt(index, previousIndex)
1328 }
13131329
13141330 if let region = Self.region(props["region"]) {
13151331 // `region` is controlled: an authored change is allowed to move