diff --git a/Localizable.xcstrings b/Localizable.xcstrings index e284ac42..a1d2ddab 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -1274,9 +1274,6 @@ } } } - }, - "Attribution:" : { - }, "automatic.detection" : { "extractionState" : "migrated", @@ -6819,9 +6816,6 @@ }, "Enable Notifications" : { - }, - "Enable Offline Maps" : { - }, "enabled" : { "localizations" : { @@ -11542,6 +11536,7 @@ } }, "map.recentering" : { + "extractionState" : "stale", "localizations" : { "de" : { "stringUnit" : { @@ -15870,9 +15865,6 @@ } } } - }, - "Offline Maps" : { - }, "OK" : { @@ -16712,9 +16704,6 @@ }, "PWD" : { - }, - "Radar" : { - }, "radio.configuration" : { "localizations" : { @@ -19855,9 +19844,6 @@ }, "Show Alerts" : { - }, - "Show Node History" : { - }, "Show nodes" : { @@ -19867,15 +19853,9 @@ }, "Show on the mesh map." : { - }, - "Show Route Lines" : { - }, "Show Waypoints " : { - }, - "Show Weather" : { - }, "Shut Down" : { @@ -21129,12 +21109,6 @@ }, "This will send a current position from your phone and enable fixed position." : { - }, - "Tile Server" : { - - }, - "Tiles above Labels" : { - }, "Time" : { diff --git a/Meshtastic/Views/Nodes/Helpers/Map/NodeMapSwiftUI.swift b/Meshtastic/Views/Nodes/Helpers/Map/NodeMapSwiftUI.swift index 1120e811..bec035b7 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/NodeMapSwiftUI.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/NodeMapSwiftUI.swift @@ -24,6 +24,7 @@ struct NodeMapSwiftUI: View { @Namespace var mapScope @State var mapStyle: MapStyle = MapStyle.hybrid(elevation: .flat, pointsOfInterest: .all, showsTraffic: true) @State var position = MapCameraPosition.automatic + @State var distance = 0.0 @State var scene: MKLookAroundScene? @State var isLookingAround = false @State var isShowingAltitude = false @@ -44,7 +45,7 @@ struct NodeMapSwiftUI: View { if node.hasPositions { ZStack { MapReader { _ in - Map(position: $position, bounds: MapCameraBounds(minimumDistance: 3000, maximumDistance: .infinity), scope: mapScope) { + Map(position: $position, bounds: MapCameraBounds(minimumDistance: 0, maximumDistance: .infinity), scope: mapScope) { NodeMapContent(node: node) } .mapScope(mapScope) @@ -103,7 +104,7 @@ struct NodeMapSwiftUI: View { if node.positions?.count ?? 0 > 1 { position = .automatic } else { - position = .camera(MapCamera(centerCoordinate: mostRecent!.coordinate, distance: 8000, heading: 0, pitch: 60)) + position = .camera(MapCamera(centerCoordinate: mostRecent!.coordinate, distance: distance, heading: 0, pitch: 0)) } if let mostRecent { Task { @@ -128,7 +129,7 @@ struct NodeMapSwiftUI: View { position = .automatic } else { if let mrCoord = mostRecent?.coordinate { - position = .camera(MapCamera(centerCoordinate: mrCoord, distance: 8000, heading: 0, pitch: 60)) + position = .camera(MapCamera(centerCoordinate: mrCoord, distance: distance, heading: 0, pitch: 0)) } } if self.scene == nil { diff --git a/Meshtastic/Views/Nodes/NodeMap.swift b/Meshtastic/Views/Nodes/NodeMap.swift index 9988f237..e81fc224 100644 --- a/Meshtastic/Views/Nodes/NodeMap.swift +++ b/Meshtastic/Views/Nodes/NodeMap.swift @@ -1,233 +1,233 @@ +//// +//// NodeMap.swift +//// MeshtasticApple +//// +//// Created by Garth Vander Houwen on 8/7/21. +//// // -// NodeMap.swift -// MeshtasticApple +//import SwiftUI +//import MapKit +//import CoreLocation +//import CoreData // -// Created by Garth Vander Houwen on 8/7/21. +//struct NodeMap: View { +// @Environment(\.managedObjectContext) var context +// @EnvironmentObject var bleManager: BLEManager // - -import SwiftUI -import MapKit -import CoreLocation -import CoreData - -struct NodeMap: View { - @Environment(\.managedObjectContext) var context - @EnvironmentObject var bleManager: BLEManager - - @ObservedObject - var router: Router - @State var selectedMapLayer: MapLayer = UserDefaults.mapLayer - @State var enableMapRecentering: Bool = UserDefaults.enableMapRecentering - @State var enableMapRouteLines: Bool = UserDefaults.enableMapRouteLines - @State var enableMapNodeHistoryPins: Bool = UserDefaults.enableMapNodeHistoryPins - @State var enableOfflineMaps: Bool = UserDefaults.enableOfflineMaps - @State var selectedTileServer: MapTileServer = UserDefaults.mapTileServer - @State var enableOverlayServer: Bool = UserDefaults.enableOverlayServer - @State var selectedOverlayServer: MapOverlayServer = UserDefaults.mapOverlayServer - @State var mapTilesAboveLabels: Bool = UserDefaults.mapTilesAboveLabels - let fromDate: NSDate = Calendar.current.date(byAdding: .month, value: -1, to: Date())! as NSDate - @FetchRequest(sortDescriptors: [NSSortDescriptor(key: "time", ascending: true)], - predicate: NSPredicate(format: "nodePosition != nil", Calendar.current.date(byAdding: .day, value: -7, to: Date())! as NSDate), animation: .none) - private var positions: FetchedResults - @FetchRequest(sortDescriptors: [NSSortDescriptor(key: "name", ascending: false)], - predicate: NSPredicate( - format: "expire == nil || expire >= %@", Date() as NSDate - ), animation: .none) - private var waypoints: FetchedResults - @State var waypointCoordinate: WaypointCoordinate? - @State var selectedTracking: UserTrackingModes = .none - @State var isPresentingInfoSheet: Bool = false - @State private var customMapOverlay: MapViewSwiftUI.CustomMapOverlay? = MapViewSwiftUI.CustomMapOverlay( - mapName: "offlinemap", - tileType: "png", - canReplaceMapContent: true - ) - var body: some View { - NavigationStack { - ZStack { - MapViewSwiftUI( - onLongPress: { coord in - waypointCoordinate = WaypointCoordinate(id: .init(), coordinate: coord, waypointId: 0) - }, onWaypointEdit: { wpId in - if wpId > 0 { - waypointCoordinate = WaypointCoordinate(id: .init(), coordinate: nil, waypointId: Int64(wpId)) - } - }, - selectedMapLayer: selectedMapLayer, - positions: Array(positions), - waypoints: Array(waypoints), - userTrackingMode: selectedTracking.MKUserTrackingModeValue(), - showNodeHistory: enableMapNodeHistoryPins, - showRouteLines: enableMapRouteLines, - customMapOverlay: self.customMapOverlay - ) - VStack(alignment: .trailing) { - HStack(alignment: .top) { - Spacer() - MapButtons(tracking: $selectedTracking, isPresentingInfoSheet: $isPresentingInfoSheet) - .padding(.trailing, 8) - .padding(.top, 16) - } - Spacer() - TileDownloadStatus() - .padding(.trailing, 16) - .padding(.bottom, 20) - } - } - .ignoresSafeArea(.all, edges: [.top, .leading, .trailing]) - .frame(maxHeight: .infinity) - .sheet(item: $waypointCoordinate, content: { wpc in - WaypointFormMapKit(coordinate: wpc) - .presentationDetents([.medium, .large]) - .presentationDragIndicator(.automatic) - }) - .sheet(isPresented: $isPresentingInfoSheet) { - VStack { - Form { - Section(header: Text("Map Options")) { - Picker(selection: $selectedMapLayer, label: Text("")) { - ForEach(MapLayer.allCases, id: \.self) { layer in - if layer == MapLayer.offline && enableOfflineMaps { - Text(layer.localized) - } else if layer != MapLayer.offline { - Text(layer.localized) - } - } - } - .pickerStyle(SegmentedPickerStyle()) - .onChange(of: selectedMapLayer) { _, newMapLayer in - UserDefaults.mapLayer = newMapLayer - } - .padding(.top, 5) - .padding(.bottom, 5) - Toggle(isOn: $enableMapRecentering) { - Label("map.recentering", systemImage: "camera.metering.center.weighted") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - .onTapGesture { - self.enableMapRecentering.toggle() - UserDefaults.enableMapRecentering = self.enableMapRecentering - } - Toggle(isOn: $enableMapNodeHistoryPins) { - Label("Show Node History", systemImage: "building.columns.fill") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - .onTapGesture { - self.enableMapNodeHistoryPins.toggle() - UserDefaults.enableMapNodeHistoryPins = self.enableMapNodeHistoryPins - } - Toggle(isOn: $enableMapRouteLines) { - Label("Show Route Lines", systemImage: "road.lanes") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - .onTapGesture { - self.enableMapRouteLines.toggle() - UserDefaults.enableMapRouteLines = self.enableMapRouteLines - } - let locale = Locale.current - if locale.region?.identifier ?? "no locale" == "US" { - Toggle(isOn: $enableOverlayServer) { - Label("Show Weather", systemImage: "cloud.fill") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - .onTapGesture { - self.enableOverlayServer.toggle() - UserDefaults.enableOverlayServer = self.enableOverlayServer - } - if enableOverlayServer { - Picker(selection: $selectedOverlayServer, - label: Text("Radar")) { - ForEach(MapOverlayServer.allCases, id: \.self) { mos in - Text(mos.description) - .font(.footnote) - } - } - .pickerStyle(DefaultPickerStyle()) - .onChange(of: (selectedOverlayServer)) { _, newSelectedOverlayServer in - UserDefaults.mapOverlayServer = newSelectedOverlayServer - } - Text(LocalizedStringKey(selectedOverlayServer.attribution)) - .font(.footnote) - .foregroundColor(.gray) - .padding(0) - } - } - } - Section(header: Text("Offline Maps")) { - Toggle(isOn: $enableOfflineMaps) { - Text("Enable Offline Maps") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - .onChange(of: enableOfflineMaps) { _, newEnableOfflineMaps in - UserDefaults.enableOfflineMaps = newEnableOfflineMaps - if !enableOfflineMaps { - if self.selectedMapLayer == .offline { - self.selectedMapLayer = .standard - } - } - } - if enableOfflineMaps { - VStack(alignment: .leading) { - Picker(selection: $selectedTileServer, - label: Text("Tile Server")) { - ForEach(MapTileServer.allCases, id: \.self) { tsl in - Text(tsl.description) - } - } - .pickerStyle(DefaultPickerStyle()) - .onChange(of: (selectedTileServer)) { _, newSelectedTileServer in - UserDefaults.mapTileServer = newSelectedTileServer - } - Text("Attribution:") - .fontWeight(.semibold) - .font(.footnote) - Text(LocalizedStringKey(selectedTileServer.attribution)) - .font(.footnote) - .foregroundColor(.gray) - .padding(0) - Divider() - Toggle(isOn: $mapTilesAboveLabels) { - Text("Tiles above Labels") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - .onTapGesture { - self.mapTilesAboveLabels.toggle() - UserDefaults.mapTilesAboveLabels = self.mapTilesAboveLabels - } - } - } - } - } - #if targetEnvironment(macCatalyst) - Button { - isPresentingInfoSheet = false - } label: { - Label("close", systemImage: "xmark") - } - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) - .controlSize(.large) - .padding(.bottom) - #endif - } - .presentationDetents([enableOfflineMaps || enableOverlayServer ? .large : .medium]) - .presentationDragIndicator(.visible) - } - } - .navigationBarItems(leading: - MeshtasticLogo(), trailing: - ZStack { - ConnectedDevice( - bluetoothOn: bleManager.isSwitchedOn, - deviceConnected: bleManager.connectedPeripheral != nil, - name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : - "?") - }) - .onAppear(perform: { - UIApplication.shared.isIdleTimerDisabled = true - }) - .onDisappear(perform: { - UIApplication.shared.isIdleTimerDisabled = false - }) - } -} +// @ObservedObject +// var router: Router +// @State var selectedMapLayer: MapLayer = UserDefaults.mapLayer +// @State var enableMapRecentering: Bool = UserDefaults.enableMapRecentering +// @State var enableMapRouteLines: Bool = UserDefaults.enableMapRouteLines +// @State var enableMapNodeHistoryPins: Bool = UserDefaults.enableMapNodeHistoryPins +// @State var enableOfflineMaps: Bool = UserDefaults.enableOfflineMaps +// @State var selectedTileServer: MapTileServer = UserDefaults.mapTileServer +// @State var enableOverlayServer: Bool = UserDefaults.enableOverlayServer +// @State var selectedOverlayServer: MapOverlayServer = UserDefaults.mapOverlayServer +// @State var mapTilesAboveLabels: Bool = UserDefaults.mapTilesAboveLabels +// let fromDate: NSDate = Calendar.current.date(byAdding: .month, value: -1, to: Date())! as NSDate +// @FetchRequest(sortDescriptors: [NSSortDescriptor(key: "time", ascending: true)], +// predicate: NSPredicate(format: "nodePosition != nil", Calendar.current.date(byAdding: .day, value: -7, to: Date())! as NSDate), animation: .none) +// private var positions: FetchedResults +// @FetchRequest(sortDescriptors: [NSSortDescriptor(key: "name", ascending: false)], +// predicate: NSPredicate( +// format: "expire == nil || expire >= %@", Date() as NSDate +// ), animation: .none) +// private var waypoints: FetchedResults +// @State var waypointCoordinate: WaypointCoordinate? +// @State var selectedTracking: UserTrackingModes = .none +// @State var isPresentingInfoSheet: Bool = false +// @State private var customMapOverlay: MapViewSwiftUI.CustomMapOverlay? = MapViewSwiftUI.CustomMapOverlay( +// mapName: "offlinemap", +// tileType: "png", +// canReplaceMapContent: true +// ) +// var body: some View { +// NavigationStack { +// ZStack { +// MapViewSwiftUI( +// onLongPress: { coord in +// waypointCoordinate = WaypointCoordinate(id: .init(), coordinate: coord, waypointId: 0) +// }, onWaypointEdit: { wpId in +// if wpId > 0 { +// waypointCoordinate = WaypointCoordinate(id: .init(), coordinate: nil, waypointId: Int64(wpId)) +// } +// }, +// selectedMapLayer: selectedMapLayer, +// positions: Array(positions), +// waypoints: Array(waypoints), +// userTrackingMode: selectedTracking.MKUserTrackingModeValue(), +// showNodeHistory: enableMapNodeHistoryPins, +// showRouteLines: enableMapRouteLines, +// customMapOverlay: self.customMapOverlay +// ) +// VStack(alignment: .trailing) { +// HStack(alignment: .top) { +// Spacer() +// MapButtons(tracking: $selectedTracking, isPresentingInfoSheet: $isPresentingInfoSheet) +// .padding(.trailing, 8) +// .padding(.top, 16) +// } +// Spacer() +// TileDownloadStatus() +// .padding(.trailing, 16) +// .padding(.bottom, 20) +// } +// } +// .ignoresSafeArea(.all, edges: [.top, .leading, .trailing]) +// .frame(maxHeight: .infinity) +// .sheet(item: $waypointCoordinate, content: { wpc in +// WaypointFormMapKit(coordinate: wpc) +// .presentationDetents([.medium, .large]) +// .presentationDragIndicator(.automatic) +// }) +// .sheet(isPresented: $isPresentingInfoSheet) { +// VStack { +// Form { +// Section(header: Text("Map Options")) { +// Picker(selection: $selectedMapLayer, label: Text("")) { +// ForEach(MapLayer.allCases, id: \.self) { layer in +// if layer == MapLayer.offline && enableOfflineMaps { +// Text(layer.localized) +// } else if layer != MapLayer.offline { +// Text(layer.localized) +// } +// } +// } +// .pickerStyle(SegmentedPickerStyle()) +// .onChange(of: selectedMapLayer) { _, newMapLayer in +// UserDefaults.mapLayer = newMapLayer +// } +// .padding(.top, 5) +// .padding(.bottom, 5) +// Toggle(isOn: $enableMapRecentering) { +// Label("map.recentering", systemImage: "camera.metering.center.weighted") +// } +// .toggleStyle(SwitchToggleStyle(tint: .accentColor)) +// .onTapGesture { +// self.enableMapRecentering.toggle() +// UserDefaults.enableMapRecentering = self.enableMapRecentering +// } +// Toggle(isOn: $enableMapNodeHistoryPins) { +// Label("Show Node History", systemImage: "building.columns.fill") +// } +// .toggleStyle(SwitchToggleStyle(tint: .accentColor)) +// .onTapGesture { +// self.enableMapNodeHistoryPins.toggle() +// UserDefaults.enableMapNodeHistoryPins = self.enableMapNodeHistoryPins +// } +// Toggle(isOn: $enableMapRouteLines) { +// Label("Show Route Lines", systemImage: "road.lanes") +// } +// .toggleStyle(SwitchToggleStyle(tint: .accentColor)) +// .onTapGesture { +// self.enableMapRouteLines.toggle() +// UserDefaults.enableMapRouteLines = self.enableMapRouteLines +// } +// let locale = Locale.current +// if locale.region?.identifier ?? "no locale" == "US" { +// Toggle(isOn: $enableOverlayServer) { +// Label("Show Weather", systemImage: "cloud.fill") +// } +// .toggleStyle(SwitchToggleStyle(tint: .accentColor)) +// .onTapGesture { +// self.enableOverlayServer.toggle() +// UserDefaults.enableOverlayServer = self.enableOverlayServer +// } +// if enableOverlayServer { +// Picker(selection: $selectedOverlayServer, +// label: Text("Radar")) { +// ForEach(MapOverlayServer.allCases, id: \.self) { mos in +// Text(mos.description) +// .font(.footnote) +// } +// } +// .pickerStyle(DefaultPickerStyle()) +// .onChange(of: (selectedOverlayServer)) { _, newSelectedOverlayServer in +// UserDefaults.mapOverlayServer = newSelectedOverlayServer +// } +// Text(LocalizedStringKey(selectedOverlayServer.attribution)) +// .font(.footnote) +// .foregroundColor(.gray) +// .padding(0) +// } +// } +// } +// Section(header: Text("Offline Maps")) { +// Toggle(isOn: $enableOfflineMaps) { +// Text("Enable Offline Maps") +// } +// .toggleStyle(SwitchToggleStyle(tint: .accentColor)) +// .onChange(of: enableOfflineMaps) { _, newEnableOfflineMaps in +// UserDefaults.enableOfflineMaps = newEnableOfflineMaps +// if !enableOfflineMaps { +// if self.selectedMapLayer == .offline { +// self.selectedMapLayer = .standard +// } +// } +// } +// if enableOfflineMaps { +// VStack(alignment: .leading) { +// Picker(selection: $selectedTileServer, +// label: Text("Tile Server")) { +// ForEach(MapTileServer.allCases, id: \.self) { tsl in +// Text(tsl.description) +// } +// } +// .pickerStyle(DefaultPickerStyle()) +// .onChange(of: (selectedTileServer)) { _, newSelectedTileServer in +// UserDefaults.mapTileServer = newSelectedTileServer +// } +// Text("Attribution:") +// .fontWeight(.semibold) +// .font(.footnote) +// Text(LocalizedStringKey(selectedTileServer.attribution)) +// .font(.footnote) +// .foregroundColor(.gray) +// .padding(0) +// Divider() +// Toggle(isOn: $mapTilesAboveLabels) { +// Text("Tiles above Labels") +// } +// .toggleStyle(SwitchToggleStyle(tint: .accentColor)) +// .onTapGesture { +// self.mapTilesAboveLabels.toggle() +// UserDefaults.mapTilesAboveLabels = self.mapTilesAboveLabels +// } +// } +// } +// } +// } +// #if targetEnvironment(macCatalyst) +// Button { +// isPresentingInfoSheet = false +// } label: { +// Label("close", systemImage: "xmark") +// } +// .buttonStyle(.bordered) +// .buttonBorderShape(.capsule) +// .controlSize(.large) +// .padding(.bottom) +// #endif +// } +// .presentationDetents([enableOfflineMaps || enableOverlayServer ? .large : .medium]) +// .presentationDragIndicator(.visible) +// } +// } +// .navigationBarItems(leading: +// MeshtasticLogo(), trailing: +// ZStack { +// ConnectedDevice( +// bluetoothOn: bleManager.isSwitchedOn, +// deviceConnected: bleManager.connectedPeripheral != nil, +// name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : +// "?") +// }) +// .onAppear(perform: { +// UIApplication.shared.isIdleTimerDisabled = true +// }) +// .onDisappear(perform: { +// UIApplication.shared.isIdleTimerDisabled = false +// }) +// } +//}