mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Merge pull request #42 from meshtastic/import_mbtiles_file
Import offline map file
This commit is contained in:
commit
ed2463c085
6 changed files with 62 additions and 42 deletions
|
|
@ -10,7 +10,6 @@
|
|||
C9483F6D2773017500998F6B /* MapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9483F6C2773017500998F6B /* MapView.swift */; };
|
||||
C9697F9D279336B700250207 /* LocalMBTileOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9697F9C279336B700250207 /* LocalMBTileOverlay.swift */; };
|
||||
C9697FA527933B8C00250207 /* SQLite in Frameworks */ = {isa = PBXBuildFile; productRef = C9697FA427933B8C00250207 /* SQLite */; };
|
||||
C9697FA72793F9FB00250207 /* MTAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9697FA62793F9FB00250207 /* MTAppDelegate.swift */; };
|
||||
C9A7BC1027759A9600760B50 /* PositionAnnotationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9A7BC0F27759A9600760B50 /* PositionAnnotationView.swift */; };
|
||||
C9A88B55278B503C00BD810A /* MapViewModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9A88B54278B503C00BD810A /* MapViewModule.swift */; };
|
||||
C9A88B57278B559900BD810A /* apponly.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9A88B56278B559900BD810A /* apponly.pb.swift */; };
|
||||
|
|
@ -78,7 +77,6 @@
|
|||
/* Begin PBXFileReference section */
|
||||
C9483F6C2773017500998F6B /* MapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapView.swift; sourceTree = "<group>"; };
|
||||
C9697F9C279336B700250207 /* LocalMBTileOverlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalMBTileOverlay.swift; sourceTree = "<group>"; };
|
||||
C9697FA62793F9FB00250207 /* MTAppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MTAppDelegate.swift; sourceTree = "<group>"; };
|
||||
C9A7BC0F27759A9600760B50 /* PositionAnnotationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionAnnotationView.swift; sourceTree = "<group>"; };
|
||||
C9A88B54278B503C00BD810A /* MapViewModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapViewModule.swift; sourceTree = "<group>"; };
|
||||
C9A88B56278B559900BD810A /* apponly.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = apponly.pb.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -265,7 +263,6 @@
|
|||
DDC2E18826CE24EE0042C5E4 /* Model */,
|
||||
DDC2E18926CE24F70042C5E4 /* Resources */,
|
||||
DDC2E15726CE248E0042C5E4 /* MeshtasticClientApp.swift */,
|
||||
C9697FA62793F9FB00250207 /* MTAppDelegate.swift */,
|
||||
DDC2E16526CE248F0042C5E4 /* Info.plist */,
|
||||
DDC2E15D26CE248F0042C5E4 /* Preview Content */,
|
||||
);
|
||||
|
|
@ -562,7 +559,6 @@
|
|||
DDAF8C6326ED0A230058C060 /* admin.pb.swift in Sources */,
|
||||
C9483F6D2773017500998F6B /* MapView.swift in Sources */,
|
||||
DDAF8C5826ED07FD0058C060 /* mesh.pb.swift in Sources */,
|
||||
C9697FA72793F9FB00250207 /* MTAppDelegate.swift in Sources */,
|
||||
DD8169FB271F1F3A00F4AB02 /* MeshLog.swift in Sources */,
|
||||
DD2E65262767A01F00E45FC5 /* NodeDetail.swift in Sources */,
|
||||
C9A88B57278B559900BD810A /* apponly.pb.swift in Sources */,
|
||||
|
|
@ -738,7 +734,7 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 18;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"MeshtasticClient/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = GCH7VS5Y9R;
|
||||
DEVELOPMENT_TEAM = 37C534H572;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = MeshtasticClient/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,28 +0,0 @@
|
|||
//
|
||||
// AppDelegate.swift
|
||||
// MeshtasticClient
|
||||
//
|
||||
// Created by Joshua Pirihi on 16/01/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
class MTAppDelegate: NSObject, UIApplicationDelegate {
|
||||
|
||||
func applicationDidFinishLaunching(_ application: UIApplication) {
|
||||
}
|
||||
|
||||
func application(
|
||||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
|
||||
) -> Bool {
|
||||
// ...
|
||||
return true
|
||||
}
|
||||
|
||||
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
|
||||
print("We received a file")
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -3,8 +3,6 @@ import CoreData
|
|||
|
||||
@main
|
||||
struct MeshtasticClientApp: App {
|
||||
|
||||
@UIApplicationDelegateAdaptor var delegate: MTAppDelegate
|
||||
|
||||
let persistenceController = PersistenceController.shared
|
||||
|
||||
|
|
@ -19,6 +17,33 @@ struct MeshtasticClientApp: App {
|
|||
.environment(\.managedObjectContext, persistenceController.container.viewContext)
|
||||
.environmentObject(bleManager)
|
||||
.environmentObject(userSettings)
|
||||
.onOpenURL(perform: { (url) in
|
||||
//we are expecting a .mbtiles map file that contains raster data
|
||||
//save it to the documents directory, and name it offline_map.mbtiles
|
||||
let fileManager = FileManager.default
|
||||
let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||
let destination = documentsDirectory.appendingPathComponent("offline_map.mbtiles", isDirectory: false)
|
||||
|
||||
//do we need to delete an old one?
|
||||
if (fileManager.fileExists(atPath: destination.path)) {
|
||||
print("ℹ️ Found an old map file. Deleting it")
|
||||
try? fileManager.removeItem(atPath: destination.path)
|
||||
}
|
||||
|
||||
try? fileManager.copyItem(at: url, to: destination)
|
||||
|
||||
if (fileManager.fileExists(atPath: destination.path)) {
|
||||
print("ℹ️ Saved the map file")
|
||||
|
||||
//need to tell the map view that it needs to update and try loading the new overlay
|
||||
UserDefaults.standard.set(Date().timeIntervalSince1970, forKey: "lastUpdatedLocalMapFile")
|
||||
|
||||
} else {
|
||||
print("💥 Didn't save the map file")
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
}
|
||||
.onChange(of: scenePhase) { (newScenePhase) in
|
||||
switch newScenePhase {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ extension MKMapRect {
|
|||
}
|
||||
}
|
||||
|
||||
enum MapTileError: Error {
|
||||
case invalidFormat
|
||||
case other
|
||||
}
|
||||
|
||||
class LocalMBTileOverlay: MKTileOverlay {
|
||||
|
||||
var path: String!
|
||||
|
|
@ -46,7 +51,7 @@ class LocalMBTileOverlay: MKTileOverlay {
|
|||
}
|
||||
}
|
||||
|
||||
init(mbTilePath path: String) {
|
||||
init?(mbTilePath path: String) {
|
||||
|
||||
super.init(urlTemplate: nil)
|
||||
self.path = path
|
||||
|
|
@ -58,6 +63,12 @@ class LocalMBTileOverlay: MKTileOverlay {
|
|||
let name = Expression<String>("name")
|
||||
let value = Expression<String>("value")
|
||||
|
||||
//make sure it's raster
|
||||
let formatQuery = try mb.pluck(metadata.select(value).filter(name == "format"))
|
||||
if formatQuery?[value] == nil || (formatQuery![value] != "jpg" && formatQuery![value] != "png") {
|
||||
throw MapTileError.invalidFormat
|
||||
}
|
||||
|
||||
let minZQuery = try mb.pluck(metadata.select(value).filter(name == "minzoom"))
|
||||
self.minimumZ = Int(minZQuery![value])!
|
||||
|
||||
|
|
@ -78,7 +89,8 @@ class LocalMBTileOverlay: MKTileOverlay {
|
|||
|
||||
|
||||
} catch {
|
||||
//print("MAP ERROR \(error)")
|
||||
print("💥 Map tile error: \(error)")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,10 @@ public struct MapView: UIViewRepresentable {
|
|||
|
||||
//@Binding private var region: MKCoordinateRegion
|
||||
|
||||
//make this view dependent on the UserDefault that is updated when importing a new map file
|
||||
@AppStorage("lastUpdatedLocalMapFile") private var lastUpdatedLocalMapFile = 0
|
||||
@State private var loadedLastUpdatedLocalMapFile = 0
|
||||
|
||||
private var customMapOverlay: CustomMapOverlay?
|
||||
@State private var presentCustomMapOverlayHash: CustomMapOverlay?
|
||||
|
||||
|
|
@ -138,20 +142,31 @@ public struct MapView: UIViewRepresentable {
|
|||
//mapView.region = self.region
|
||||
//}
|
||||
|
||||
if self.customMapOverlay != self.presentCustomMapOverlayHash {
|
||||
if self.customMapOverlay != self.presentCustomMapOverlayHash || self.loadedLastUpdatedLocalMapFile != self.lastUpdatedLocalMapFile {
|
||||
mapView.removeOverlays(mapView.overlays)
|
||||
if let customMapOverlay = self.customMapOverlay {
|
||||
|
||||
if let tilePath = Bundle.main.path(forResource: "offline_map", ofType: "mbtiles") {
|
||||
let overlay = LocalMBTileOverlay(mbTilePath: tilePath)
|
||||
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) {
|
||||
//if let tilePath = Bundle.main.path(forResource: "offline_map", ofType: "mbtiles") {
|
||||
|
||||
overlay.canReplaceMapContent = false//customMapOverlay.canReplaceMapContent
|
||||
print("Loading local map file")
|
||||
|
||||
mapView.addOverlay(overlay)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue