diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index 7964d860..424f7dda 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -26,7 +26,6 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { @Published var connectedPeripheral: Peripheral! @Published var lastConnectionError: String @Published var invalidVersion = false - @Published var preferredPeripheral = false @Published var isSwitchedOn: Bool = false @Published var automaticallyReconnect: Bool = true @@ -166,11 +165,11 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { isConnected = true if userSettings?.preferredPeripheralId.count ?? 0 < 1 { userSettings?.preferredPeripheralId = peripheral.identifier.uuidString - preferredPeripheral = true + // preferredPeripheral = true } else if userSettings!.preferredPeripheralId == peripheral.identifier.uuidString { - preferredPeripheral = true + // preferredPeripheral = true } else { - preferredPeripheral = false + // preferredPeripheral = false print("Trying to connect a non prefered peripheral") } UserDefaults.standard.synchronize() @@ -448,8 +447,6 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { let myInfo = myInfoPacket(myInfo: decodedInfo.myInfo, peripheralId: self.connectedPeripheral.id, context: context!) - userSettings?.preferredNodeNum = myInfo?.myNodeNum ?? 0 - if myInfo != nil { connectedPeripheral.num = myInfo!.myNodeNum connectedPeripheral.firmwareVersion = myInfo?.firmwareVersion ?? NSLocalizedString("unknown", comment: "Unknown") diff --git a/Meshtastic/Model/UserSettings.swift b/Meshtastic/Model/UserSettings.swift index 026306bc..0f759ee8 100644 --- a/Meshtastic/Model/UserSettings.swift +++ b/Meshtastic/Model/UserSettings.swift @@ -19,12 +19,6 @@ class UserSettings: ObservableObject { UserDefaults.standard.synchronize() } } - @Published var preferredNodeNum: Int64 { - didSet { - UserDefaults.standard.set(preferredNodeNum, forKey: "preferredNodeNum") - UserDefaults.standard.synchronize() - } - } @Published var provideLocation: Bool { didSet { UserDefaults.standard.set(provideLocation, forKey: "provideLocation") @@ -73,7 +67,6 @@ class UserSettings: ObservableObject { self.meshtasticUsername = UserDefaults.standard.object(forKey: "meshtasticusername") as? String ?? "" self.preferredPeripheralId = UserDefaults.standard.object(forKey: "preferredPeripheralId") as? String ?? "" - self.preferredNodeNum = UserDefaults.standard.object(forKey: "preferredNodeNum") as? Int64 ?? 0 self.provideLocation = UserDefaults.standard.object(forKey: "provideLocation") as? Bool ?? false self.provideLocationInterval = UserDefaults.standard.object(forKey: "provideLocationInterval") as? Int ?? 900 self.keyboardType = UserDefaults.standard.object(forKey: "keyboardType") as? Int ?? 0 diff --git a/Meshtastic/Views/Bluetooth/Connect.swift b/Meshtastic/Views/Bluetooth/Connect.swift index 007afad9..799c20e0 100644 --- a/Meshtastic/Views/Bluetooth/Connect.swift +++ b/Meshtastic/Views/Bluetooth/Connect.swift @@ -20,11 +20,11 @@ struct Connect: View { @EnvironmentObject var bleManager: BLEManager @EnvironmentObject var userSettings: UserSettings @State var node: NodeInfoEntity? = nil - - @State var isPreferredRadio: Bool = false @State var isUnsetRegion = false @State var invalidFirmwareVersion = false @State var liveActivityStarted = false + @State var presentingSwitchPreferredPeripheral = false + @State var selectedPeripherialId = "" var body: some View { @@ -32,7 +32,6 @@ struct Connect: View { VStack { List { if bleManager.isSwitchedOn { - Section(header: Text("connected.radio").font(.title)) { if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.state == .connected { HStack { @@ -85,6 +84,28 @@ struct Connect: View { } } } + .resizable() + .symbolRenderingMode(.hierarchical) + .foregroundColor(.green) + .frame(width: 60, height: 60) + .padding(.trailing) + VStack(alignment: .leading) { + if node != nil { + Text(bleManager.connectedPeripheral.longName).font(.title) + } + Text("ble.name").font(.callout)+Text(": \(bleManager.connectedPeripheral.peripheral.name ?? NSLocalizedString("unknown", comment: "Unknown"))") + .font(.callout).foregroundColor(Color.gray) + if node != nil { + Text("firmware.version").font(.callout)+Text(": \(node?.myInfo?.firmwareVersion ?? NSLocalizedString("unknown", comment: "Unknown"))") + .font(.callout).foregroundColor(Color.gray) + } + if bleManager.isSubscribed { + Text("subscribed").font(.callout) + .foregroundColor(.green) + } else { + Text("communicating").font(.callout) + .foregroundColor(.orange) + } } } .font(.caption).foregroundColor(Color.gray) @@ -94,7 +115,6 @@ struct Connect: View { Button(role: .destructive) { if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.state == CBPeripheralState.connected { bleManager.disconnectPeripheral(reconnect: false) - isPreferredRadio = false } } label: { Label("disconnect", systemImage: "antenna.radiowaves.left.and.right.slash") @@ -189,18 +209,11 @@ struct Connect: View { .imageScale(.large).foregroundColor(.gray) .padding(.trailing) Button(action: { - self.bleManager.stopScanning() - if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.state == CBPeripheralState.connected { - - self.bleManager.disconnectPeripheral() - } - self.bleManager.connectTo(peripheral: peripheral.peripheral) - if userSettings.preferredPeripheralId == peripheral.peripheral.identifier.uuidString { - - isPreferredRadio = true + if userSettings.preferredPeripheralId.count > 0 && peripheral.peripheral.identifier.uuidString != userSettings.preferredPeripheralId { + presentingSwitchPreferredPeripheral = true + selectedPeripherialId = peripheral.peripheral.identifier.uuidString } else { - - isPreferredRadio = false + self.bleManager.connectTo(peripheral: peripheral.peripheral) } }) { Text(peripheral.name).font(.title3) @@ -220,12 +233,29 @@ struct Connect: View { .font(.title) } } + .confirmationDialog("Connecting to a new radio will clear all local app data on the phone.", isPresented: $presentingSwitchPreferredPeripheral, titleVisibility: .visible) { + + Button("Connect to new radio?", role: .destructive) { + bleManager.stopScanning() + bleManager.connectedPeripheral = nil + userSettings.preferredPeripheralId = "" + if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.state == CBPeripheralState.connected { + bleManager.disconnectPeripheral() + } + + clearCoreDataDatabase(context: context) + let radio = bleManager.peripherals.first(where: { $0.peripheral.identifier.uuidString == selectedPeripherialId} ) + bleManager.connectTo(peripheral: radio!.peripheral) + presentingSwitchPreferredPeripheral = false + selectedPeripherialId = "" + } + } HStack(alignment: .center) { Spacer() #if targetEnvironment(macCatalyst) - + if bleManager.connectedPeripheral != nil { Button(role: .destructive, action: { @@ -266,10 +296,10 @@ struct Connect: View { } .onChange(of: (self.bleManager.isSubscribed)) { sub in - if userSettings.preferredNodeNum > 0 && sub { + if userSettings.preferredPeripheralId.count > 0 && sub { let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") - fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(userSettings.preferredNodeNum)) + fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(bleManager.connectedPeripheral.num)) do { @@ -300,11 +330,6 @@ struct Connect: View { print(error.localizedDescription) } } - if self.bleManager.connectedPeripheral != nil && userSettings.preferredPeripheralId == self.bleManager.connectedPeripheral.id { - isPreferredRadio = true - } else { - isPreferredRadio = false - } }) } #if canImport(ActivityKit) diff --git a/Meshtastic/Views/Map/Custom/MapViewSwiftUI.swift b/Meshtastic/Views/Map/Custom/MapViewSwiftUI.swift index 83287947..22d949e7 100644 --- a/Meshtastic/Views/Map/Custom/MapViewSwiftUI.swift +++ b/Meshtastic/Views/Map/Custom/MapViewSwiftUI.swift @@ -19,11 +19,11 @@ struct MapViewSwiftUI: UIViewRepresentable { let positions: [PositionEntity] let waypoints: [WaypointEntity] let mapViewType: MKMapType + let userTrackingMode: MKUserTrackingMode let centeringMode: CenteringMode let centerOnPositionsOnly: Bool @AppStorage("meshMapRecentering") private var recenter: Bool = false - @AppStorage("meshMapUserTrackingMode") private var userTrackingModeId: Int = 0 // Offline Maps //make this view dependent on the UserDefault that is updated when importing a new map file @@ -38,12 +38,12 @@ struct MapViewSwiftUI: UIViewRepresentable { // Map View Parameters mapView.mapType = mapViewType mapView.addAnnotations(waypoints) - mapView.setUserTrackingMode(UserTrackingModes(rawValue: userTrackingModeId )?.MKUserTrackingModeValue() ?? MKUserTrackingMode.none, animated: true) - if UserTrackingModes(rawValue: userTrackingModeId) != UserTrackingModes.none { - let span = MKCoordinateSpan(latitudeDelta: 0.003, longitudeDelta: 0.003) - let center = LocationHelper.currentLocation - let region = MKCoordinateRegion(center: center, span: span) - mapView.setRegion(region, animated: true) + mapView.setUserTrackingMode(userTrackingMode, animated: true) + let span = MKCoordinateSpan(latitudeDelta: 0.003, longitudeDelta: 0.003) + let center = LocationHelper.currentLocation + let region = MKCoordinateRegion(center: center, span: span) + mapView.setRegion(region, animated: true) + if userTrackingMode != MKUserTrackingMode.none { mapView.showsUserLocation = true } else { mapView.showsUserLocation = false @@ -51,11 +51,11 @@ struct MapViewSwiftUI: UIViewRepresentable { switch centeringMode { case .allAnnotations: mapView.addAnnotations(positions) - if UserTrackingModes(rawValue: userTrackingModeId) == UserTrackingModes.none { + if userTrackingMode == MKUserTrackingMode.none { mapView.fitAllAnnotations() } case .allPositions: - if UserTrackingModes(rawValue: userTrackingModeId) == UserTrackingModes.none { + if userTrackingMode != MKUserTrackingMode.none { mapView.fit(annotations: positions, andShow: true) } else { mapView.addAnnotations(positions) @@ -72,14 +72,14 @@ struct MapViewSwiftUI: UIViewRepresentable { mapView.showsScale = true mapView.showsTraffic = true -#if targetEnvironment(macCatalyst) + #if targetEnvironment(macCatalyst) // Show the default always visible compass and the mac only controls mapView.showsCompass = true mapView.showsZoomControls = true mapView.showsPitchControl = true -#else + #else -#if os(iOS) + #if os(iOS) // Hide the default compass that only appears when you are not going north and instead always show the compass in the bottom right corner of the map mapView.showsCompass = false let compassButton = MKCompassButton(mapView: mapView) // Make a new compass @@ -88,9 +88,9 @@ struct MapViewSwiftUI: UIViewRepresentable { compassButton.translatesAutoresizingMaskIntoConstraints = false compassButton.trailingAnchor.constraint(equalTo: mapView.trailingAnchor, constant: -5).isActive = true compassButton.bottomAnchor.constraint(equalTo: mapView.bottomAnchor, constant: -25).isActive = true + #endif -#endif -#endif + #endif mapView.delegate = context.coordinator return mapView } @@ -127,8 +127,8 @@ struct MapViewSwiftUI: UIViewRepresentable { if annotationCount != mapView.annotations.count { mapView.removeAnnotations(mapView.annotations) mapView.addAnnotations(waypoints) - mapView.setUserTrackingMode(UserTrackingModes(rawValue: userTrackingModeId )?.MKUserTrackingModeValue() ?? MKUserTrackingMode.none, animated: true) - if UserTrackingModes(rawValue: userTrackingModeId) != UserTrackingModes.none { + mapView.setUserTrackingMode(userTrackingMode, animated: true) + if userTrackingMode != MKUserTrackingMode.none { mapView.showsUserLocation = true } else { mapView.showsUserLocation = false @@ -136,11 +136,11 @@ struct MapViewSwiftUI: UIViewRepresentable { switch centeringMode { case .allAnnotations: mapView.addAnnotations(positions) - if recenter && UserTrackingModes(rawValue: userTrackingModeId) == UserTrackingModes.none { + if recenter && userTrackingMode == MKUserTrackingMode.none { mapView.fitAllAnnotations() } case .allPositions: - if recenter && UserTrackingModes(rawValue: userTrackingModeId) == UserTrackingModes.none { + if recenter && userTrackingMode == MKUserTrackingMode.none { mapView.fit(annotations: positions, andShow: true) } else { mapView.addAnnotations(positions) @@ -232,7 +232,7 @@ struct MapViewSwiftUI: UIViewRepresentable { } if pf.contains(.Heading){ - if parent.userTrackingModeId != 2 { + if parent.userTrackingMode != MKUserTrackingMode.followWithHeading { annotationView.glyphImage = UIImage(systemName: "location.north.fill")?.rotate(radians: Float(degreesToRadians(Double(positionAnnotation.heading)))) subtitle.text! += "Heading: \(String(positionAnnotation.heading)) \n" } else { diff --git a/Meshtastic/Views/Messages/ChannelMessageList.swift b/Meshtastic/Views/Messages/ChannelMessageList.swift index 31f71bbe..613961d0 100644 --- a/Meshtastic/Views/Messages/ChannelMessageList.swift +++ b/Meshtastic/Views/Messages/ChannelMessageList.swift @@ -38,7 +38,7 @@ struct ChannelMessageList: View { ScrollView { LazyVStack { ForEach( channel.allPrivateMessages ) { (message: MessageEntity) in - let currentUser: Bool = (userSettings.preferredNodeNum == message.fromUser?.num ? true : false) + let currentUser: Bool = (bleManager.connectedPeripheral.num == message.fromUser?.num ? true : false) if message.replyID > 0 { let messageReply = channel.allPrivateMessages.first(where: { $0.messageId == message.replyID }) HStack { diff --git a/Meshtastic/Views/Messages/Contacts.swift b/Meshtastic/Views/Messages/Contacts.swift index 241a694e..75b81102 100644 --- a/Meshtastic/Views/Messages/Contacts.swift +++ b/Meshtastic/Views/Messages/Contacts.swift @@ -141,7 +141,7 @@ struct Contacts: View { } Section(header: Text("direct.messages")) { ForEach(users) { (user: UserEntity) in - if user.num != bleManager.userSettings?.preferredNodeNum ?? 0 { + if user.num != bleManager.connectedPeripheral?.num ?? 0 { NavigationLink(destination: UserMessageList(user: user)) { let mostRecent = user.messageList.last let lastMessageTime = Date(timeIntervalSince1970: TimeInterval(Int64((mostRecent?.messageTimestamp ?? 0 )))) @@ -254,25 +254,19 @@ struct Contacts: View { .onAppear { self.bleManager.userSettings = userSettings self.bleManager.context = context - - if userSettings.preferredNodeNum > 0 { - + if userSettings.preferredPeripheralId.count > 0 { let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") - fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(userSettings.preferredNodeNum)) - + fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(bleManager.connectedPeripheral?.num ?? -1)) do { - let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] // Found a node, check it for a region if !fetchedNode.isEmpty { node = fetchedNode[0] - } } catch { } } - } } detail: { diff --git a/Meshtastic/Views/Messages/UserMessageList.swift b/Meshtastic/Views/Messages/UserMessageList.swift index d696714e..50cb5451 100644 --- a/Meshtastic/Views/Messages/UserMessageList.swift +++ b/Meshtastic/Views/Messages/UserMessageList.swift @@ -37,8 +37,8 @@ struct UserMessageList: View { ScrollView { LazyVStack { ForEach( user.messageList ) { (message: MessageEntity) in - if user.num != userSettings.preferredNodeNum { - let currentUser: Bool = (userSettings.preferredNodeNum == message.fromUser?.num ? true : false) + if user.num != bleManager.connectedPeripheral.num { + let currentUser: Bool = (bleManager.connectedPeripheral.num == message.fromUser?.num ?? -1 ? true : false) if message.replyID > 0 { let messageReply = user.messageList.first(where: { $0.messageId == message.replyID }) diff --git a/Meshtastic/Views/Nodes/NodeDetail.swift b/Meshtastic/Views/Nodes/NodeDetail.swift index 97bc4630..4e19a414 100644 --- a/Meshtastic/Views/Nodes/NodeDetail.swift +++ b/Meshtastic/Views/Nodes/NodeDetail.swift @@ -70,6 +70,7 @@ struct NodeDetail: View { } }, positions: annotations, waypoints: Array(waypoints), mapViewType: mapType, + userTrackingMode: MKUserTrackingMode.none, centeringMode: .allPositions, centerOnPositionsOnly: true, customMapOverlay: self.customMapOverlay, diff --git a/Meshtastic/Views/Nodes/NodeMap.swift b/Meshtastic/Views/Nodes/NodeMap.swift index 9f51b7fe..3d35ae36 100644 --- a/Meshtastic/Views/Nodes/NodeMap.swift +++ b/Meshtastic/Views/Nodes/NodeMap.swift @@ -30,6 +30,7 @@ struct NodeMap: View { } } @AppStorage("meshMapType") private var meshMapType = "hybridFlyover" + @AppStorage("meshMapUserTrackingMode") private var meshMapUserTrackingMode = 0 @AppStorage("meshMapCenteringMode") private var meshMapCenteringMode = 0 //&& nodePosition != nil @@ -44,6 +45,7 @@ struct NodeMap: View { private var waypoints: FetchedResults @State private var mapType: MKMapType = .standard + @State private var userTrackingMode: MKUserTrackingMode = .none @State private var mapCenteringMode: CenteringMode = .allAnnotations @State var waypointCoordinate: CLLocationCoordinate2D = LocationHelper.DefaultLocation @State var editingWaypoint: Int = 0 @@ -76,6 +78,7 @@ struct NodeMap: View { }, positions: Array(positions), waypoints: Array(waypoints), mapViewType: mapType, + userTrackingMode: userTrackingMode, centeringMode: mapCenteringMode, centerOnPositionsOnly: false, customMapOverlay: self.customMapOverlay, @@ -116,6 +119,7 @@ struct NodeMap: View { self.bleManager.context = context self.bleManager.userSettings = userSettings mapCenteringMode = CenteringMode(rawValue: meshMapCenteringMode) ?? CenteringMode.allAnnotations + userTrackingMode = UserTrackingModes(rawValue: meshMapUserTrackingMode)?.MKUserTrackingModeValue() ?? MKUserTrackingMode.none switch meshMapType { case "standard": mapType = .standard