mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Tidy up offline maps
This commit is contained in:
parent
0596e93bbf
commit
8af95d7248
4 changed files with 94 additions and 106 deletions
|
|
@ -30,6 +30,18 @@ extension String {
|
|||
|
||||
var localized: String { NSLocalizedString(self, comment: self) }
|
||||
|
||||
|
||||
|
||||
func isEmoji() -> Bool {
|
||||
// Emoji are no more than 4 bytes
|
||||
if self.count > 4 {
|
||||
return false
|
||||
} else {
|
||||
let characters = Array(self)
|
||||
return characters[0].isEmoji
|
||||
}
|
||||
}
|
||||
|
||||
func onlyEmojis() -> Bool {
|
||||
return count > 0 && !contains { !$0.isEmoji }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,6 +104,14 @@ extension UserDefaults {
|
|||
UserDefaults.standard.set(newValue, forKey: "enableOfflineMaps")
|
||||
}
|
||||
}
|
||||
static var enableOfflineMapsMBTiles: Bool {
|
||||
get {
|
||||
UserDefaults.standard.bool(forKey: "enableOfflineMapsMBTiles")
|
||||
}
|
||||
set {
|
||||
UserDefaults.standard.set(newValue, forKey: "enableOfflineMapsMBTiles")
|
||||
}
|
||||
}
|
||||
|
||||
static var mapTileServer: String {
|
||||
get {
|
||||
|
|
|
|||
|
|
@ -90,21 +90,23 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
#endif
|
||||
}
|
||||
|
||||
private func setOverlays(mapView: MKMapView) {
|
||||
private func setMapLayer(mapView: MKMapView) {
|
||||
// Avoid refreshing UI if selectedLayer has not changed
|
||||
guard currentMapLayer != selectedMapLayer else { return }
|
||||
currentMapLayer = selectedMapLayer
|
||||
for overlay in mapView.overlays {
|
||||
if overlay is TileOverlay {
|
||||
if overlay is MKTileOverlay {
|
||||
mapView.removeOverlay(overlay)
|
||||
}
|
||||
}
|
||||
switch selectedMapLayer {
|
||||
case .offline:
|
||||
let overlay = TileOverlay()
|
||||
overlay.canReplaceMapContent = false
|
||||
mapView.mapType = .standard
|
||||
mapView.addOverlay(overlay, level: .aboveRoads)
|
||||
if !UserDefaults.enableOfflineMapsMBTiles {
|
||||
let overlay = TileOverlay()
|
||||
overlay.canReplaceMapContent = false
|
||||
mapView.addOverlay(overlay, level: .aboveLabels)
|
||||
}
|
||||
case .satellite:
|
||||
mapView.mapType = .satellite
|
||||
case .hybrid:
|
||||
|
|
@ -114,39 +116,6 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
}
|
||||
}
|
||||
|
||||
private func setUserTracking(mapView: MKMapView, headingView: UIImageView?) {
|
||||
// switch selectedTracking {
|
||||
// case .bounding:
|
||||
// guard let firstBoundingBox = trails.first?.polyline.boundingMapRect else {
|
||||
// self.selectedTracking = .enabled
|
||||
// return
|
||||
// }
|
||||
// let boundingBox = trails
|
||||
// .map { $0.polyline.boundingMapRect }
|
||||
// .reduce(firstBoundingBox) { (boundingBox, nextResult) -> MKMapRect in
|
||||
// let minX = nextResult.minX < boundingBox.minX ? nextResult.minX : boundingBox.minX
|
||||
// let maxX = nextResult.maxX > boundingBox.maxX ? nextResult.maxX : boundingBox.maxX
|
||||
// let minY = nextResult.minY < boundingBox.minY ? nextResult.minY : boundingBox.minY
|
||||
// let maxY = nextResult.maxY > boundingBox.maxY ? nextResult.maxY : boundingBox.maxY
|
||||
// return MKMapRect(origin: MKMapPoint(x: minX, y: minY), size: MKMapSize(width: maxX-minX, height: maxY-minY))
|
||||
// }
|
||||
// var region = MKCoordinateRegion(boundingBox)
|
||||
// region.span.latitudeDelta += 0.01
|
||||
// region.span.longitudeDelta += 0.01
|
||||
// mapView.setRegion(region, animated: false)
|
||||
// case .disabled:
|
||||
// mapView.setUserTrackingMode(.none, animated: true)
|
||||
// locationManager.updateHeading = false
|
||||
// headingView?.isHidden = true
|
||||
// case .enabled:
|
||||
// mapView.setUserTrackingMode(.follow, animated: true)
|
||||
// locationManager.updateHeading = true
|
||||
// case .heading:
|
||||
// mapView.setUserTrackingMode(.followWithHeading, animated: true)
|
||||
// headingView?.isHidden = true
|
||||
// }
|
||||
}
|
||||
|
||||
func makeUIView(context: Context) -> MKMapView {
|
||||
currentMapLayer = nil
|
||||
mapView.delegate = context.coordinator
|
||||
|
|
@ -156,39 +125,41 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
|
||||
func updateUIView(_ mapView: MKMapView, context: Context) {
|
||||
|
||||
|
||||
// MBTiles Offline maps and tile server settings
|
||||
// if UserDefaults.enableOfflineMaps && UserDefaults.mapTileServer == "" {
|
||||
// MBTiles Offline
|
||||
if UserDefaults.enableOfflineMaps && UserDefaults.enableOfflineMapsMBTiles {
|
||||
|
||||
// if self.customMapOverlay != self.presentCustomMapOverlayHash || self.loadedLastUpdatedLocalMapFile != self.lastUpdatedLocalMapFile {
|
||||
// mapView.removeOverlays(mapView.overlays)
|
||||
// if self.customMapOverlay != nil {
|
||||
//
|
||||
// let fileManager = FileManager.default
|
||||
// let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||
// let tilePath = documentsDirectory.appendingPathComponent("offline_map.mbtiles", isDirectory: false).path
|
||||
// if fileManager.fileExists(atPath: tilePath) {
|
||||
// print("Loading local map file")
|
||||
// if let overlay = LocalMBTileOverlay(mbTilePath: tilePath) {
|
||||
// overlay.canReplaceMapContent = true// customMapOverlay.canReplaceMapContent
|
||||
// mapView.addOverlay(overlay)
|
||||
// }
|
||||
// } else {
|
||||
// print("Couldn't find a local map file to load")
|
||||
// }
|
||||
// }
|
||||
// DispatchQueue.main.async {
|
||||
// self.presentCustomMapOverlayHash = self.customMapOverlay
|
||||
// self.loadedLastUpdatedLocalMapFile = self.lastUpdatedLocalMapFile
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if self.customMapOverlay != self.presentCustomMapOverlayHash || self.loadedLastUpdatedLocalMapFile != self.lastUpdatedLocalMapFile {
|
||||
mapView.removeOverlays(mapView.overlays)
|
||||
if self.customMapOverlay != nil {
|
||||
|
||||
let fileManager = FileManager.default
|
||||
let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||
let tilePath = documentsDirectory.appendingPathComponent("offline_map.mbtiles", isDirectory: false).path
|
||||
if fileManager.fileExists(atPath: tilePath) {
|
||||
print("Loading local map file")
|
||||
if let overlay = LocalMBTileOverlay(mbTilePath: tilePath) {
|
||||
overlay.canReplaceMapContent = false// customMapOverlay.canReplaceMapContent
|
||||
mapView.addOverlay(overlay)
|
||||
}
|
||||
} else {
|
||||
print("Couldn't find a local map file to load")
|
||||
}
|
||||
}
|
||||
DispatchQueue.main.async {
|
||||
self.presentCustomMapOverlayHash = self.customMapOverlay
|
||||
self.loadedLastUpdatedLocalMapFile = self.lastUpdatedLocalMapFile
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set selected map layer
|
||||
setMapLayer(mapView: mapView)
|
||||
|
||||
let latest = positions
|
||||
.filter { $0.latest == true }
|
||||
.sorted { $0.nodePosition?.num ?? 0 > $1.nodePosition?.num ?? -1 }
|
||||
|
||||
// Node Route Lines
|
||||
if true {//showRouteLines {
|
||||
if showRouteLines {
|
||||
// Remove all existing PolyLine Overlays
|
||||
for overlay in mapView.overlays {
|
||||
if overlay is MKPolyline {
|
||||
|
|
@ -221,9 +192,6 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
}
|
||||
}
|
||||
|
||||
/// Set selected map layer
|
||||
setOverlays(mapView: mapView)
|
||||
|
||||
let annotationCount = waypoints.count + (showNodeHistory ? positions.count : latest.count)
|
||||
if annotationCount != mapView.annotations.count {
|
||||
print("Annotation Count: \(annotationCount) Map Annotations: \(mapView.annotations.count)")
|
||||
|
|
@ -255,7 +223,6 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
}
|
||||
|
||||
func makeCoordinator() -> MapCoordinator {
|
||||
//return Coordinator(self)
|
||||
return Coordinator(self)
|
||||
}
|
||||
|
||||
|
|
@ -443,18 +410,19 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
}
|
||||
|
||||
public func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
|
||||
|
||||
switch overlay {
|
||||
case let overlay as MKTileOverlay:
|
||||
return MKTileOverlayRenderer(tileOverlay: overlay)
|
||||
case let polyline as MKPolyline:
|
||||
let polylineRenderer = MKPolylineRenderer(overlay: overlay)
|
||||
let titleString = polyline.title ?? "0"
|
||||
let renderer = MKPolylineRenderer(polyline: polyline)
|
||||
renderer.strokeColor = UIColor(hex: UInt32(titleString) ?? 0)
|
||||
renderer.lineWidth = 8
|
||||
return polylineRenderer
|
||||
default: return MKOverlayRenderer()
|
||||
|
||||
if let tileOverlay = overlay as? MKTileOverlay {
|
||||
return MKTileOverlayRenderer(tileOverlay: tileOverlay)
|
||||
} else {
|
||||
if let routePolyline = overlay as? MKPolyline {
|
||||
|
||||
let titleString = routePolyline.title ?? "0"
|
||||
let renderer = MKPolylineRenderer(polyline: routePolyline)
|
||||
renderer.strokeColor = UIColor(hex: UInt32(titleString) ?? 0)
|
||||
renderer.lineWidth = 8
|
||||
return renderer
|
||||
}
|
||||
return MKOverlayRenderer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ struct NodeMap: View {
|
|||
@State var enableMapNodeHistoryPins: Bool = UserDefaults.enableMapNodeHistoryPins
|
||||
@State var enableOfflineMaps: Bool = UserDefaults.enableOfflineMaps
|
||||
@State var mapTileServer: String = UserDefaults.mapTileServer
|
||||
@State var enableOfflineMapsMBTiles: Bool = UserDefaults.enableOfflineMapsMBTiles
|
||||
|
||||
@FetchRequest(sortDescriptors: [NSSortDescriptor(key: "time", ascending: true)],
|
||||
predicate: NSPredicate(format: "time >= %@ && nodePosition != nil", Calendar.current.startOfDay(for: Date()) as NSDate), animation: .none)
|
||||
|
|
@ -149,35 +150,34 @@ struct NodeMap: View {
|
|||
|
||||
if UserDefaults.enableOfflineMaps {
|
||||
VStack {
|
||||
// Picker("Tile Servers", selection: $selectedTileServer) {
|
||||
// ForEach(MapTileServerLinks.allCases) { ts in
|
||||
// Text(ts.description)
|
||||
// // .tag(ts.id)
|
||||
// }
|
||||
// }
|
||||
// .pickerStyle(.menu)
|
||||
// .onChange(of: (selectedTileServer)) { newTileServer in
|
||||
//
|
||||
// mapTileServer = selectedTileServer.tileUrl
|
||||
// }
|
||||
|
||||
// TilesDownloadView(boundingBox: mapRect, name: "All tiles")
|
||||
HStack {
|
||||
Label("Tile Server", systemImage: "square.grid.3x2")
|
||||
TextField(
|
||||
"Tile Server",
|
||||
text: $mapTileServer,
|
||||
axis: .vertical
|
||||
)
|
||||
.foregroundColor(.gray)
|
||||
.font(.caption)
|
||||
.onChange(of: (mapTileServer)) { newMapTileServer in
|
||||
UserDefaults.mapTileServer = newMapTileServer
|
||||
if !enableOfflineMapsMBTiles {
|
||||
|
||||
HStack {
|
||||
Label("Tile Server", systemImage: "square.grid.3x2")
|
||||
TextField(
|
||||
"Tile Server",
|
||||
text: $mapTileServer,
|
||||
axis: .vertical
|
||||
)
|
||||
.keyboardType(.asciiCapable)
|
||||
.disableAutocorrection(true)
|
||||
.foregroundColor(.gray)
|
||||
.font(.caption)
|
||||
.onChange(of: (mapTileServer)) { newMapTileServer in
|
||||
UserDefaults.mapTileServer = newMapTileServer
|
||||
}
|
||||
}
|
||||
}
|
||||
Toggle(isOn: $enableOfflineMapsMBTiles) {
|
||||
Text("Enable MB Tiles")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
.onTapGesture {
|
||||
self.enableOfflineMapsMBTiles.toggle()
|
||||
UserDefaults.enableOfflineMapsMBTiles = self.enableOfflineMapsMBTiles
|
||||
}
|
||||
}
|
||||
.keyboardType(.asciiCapable)
|
||||
.disableAutocorrection(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue