Assorted updates

This commit is contained in:
Garth Vander Houwen 2023-11-26 10:45:03 -08:00
parent 44859fb985
commit 24868b4a28
9 changed files with 264 additions and 32 deletions

View file

@ -22,6 +22,7 @@
DD1933762B0835D500771CD5 /* PositionAltitudeChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1933752B0835D500771CD5 /* PositionAltitudeChart.swift */; };
DD1933782B084F4200771CD5 /* Measurement.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1933772B084F4200771CD5 /* Measurement.swift */; };
DD1BF2F92776FE2E008C8D2F /* UserMessageList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1BF2F82776FE2E008C8D2F /* UserMessageList.swift */; };
DD21007F2B0E571300F2F116 /* Settings2.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD21007E2B0E571300F2F116 /* Settings2.swift */; };
DD2160AF28C5552500C17253 /* MQTTConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD2160AE28C5552500C17253 /* MQTTConfig.swift */; };
DD23A50F26FD1B4400D9B90C /* PeripheralModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */; };
DD2553572855B02500E55709 /* LoRaConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD2553562855B02500E55709 /* LoRaConfig.swift */; };
@ -231,6 +232,7 @@
DD1933752B0835D500771CD5 /* PositionAltitudeChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionAltitudeChart.swift; sourceTree = "<group>"; };
DD1933772B084F4200771CD5 /* Measurement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Measurement.swift; sourceTree = "<group>"; };
DD1BF2F82776FE2E008C8D2F /* UserMessageList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserMessageList.swift; sourceTree = "<group>"; };
DD21007E2B0E571300F2F116 /* Settings2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings2.swift; sourceTree = "<group>"; };
DD2160AE28C5552500C17253 /* MQTTConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MQTTConfig.swift; sourceTree = "<group>"; };
DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeripheralModel.swift; sourceTree = "<group>"; };
DD2553562855B02500E55709 /* LoRaConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoRaConfig.swift; sourceTree = "<group>"; };
@ -482,6 +484,21 @@
path = CoreData;
sourceTree = "<group>";
};
DD2100802B0E676E00F2F116 /* Routes */ = {
isa = PBXGroup;
children = (
DD2100832B0E67AD00F2F116 /* RouteMap */,
);
path = Routes;
sourceTree = "<group>";
};
DD2100832B0E67AD00F2F116 /* RouteMap */ = {
isa = PBXGroup;
children = (
);
path = RouteMap;
sourceTree = "<group>";
};
DD47E3CA26F0E50300029299 /* Nodes */ = {
isa = PBXGroup;
children = (
@ -509,6 +526,7 @@
DD4A911C2708C57100501B7E /* Settings */ = {
isa = PBXGroup;
children = (
DD2100802B0E676E00F2F116 /* Routes */,
DD97E96728EFE9A00056DDA4 /* About.swift */,
DD0F791A28713C8A00A6FDAD /* AdminMessageList.swift */,
DD4A911D2708C65400501B7E /* AppSettings.swift */,
@ -518,6 +536,7 @@
DD8169FA271F1F3A00F4AB02 /* MeshLog.swift */,
DD86D40B287F401000BAEB7A /* SaveChannelQRCode.swift */,
DD3501882852FC3B000FC853 /* Settings.swift */,
DD21007E2B0E571300F2F116 /* Settings2.swift */,
DD3CC6B428E33FD100FA9159 /* ShareChannels.swift */,
DDCE4E2B2869F92900BE9F8F /* UserConfig.swift */,
DD61937A2863876A00E59241 /* Config */,
@ -1091,6 +1110,7 @@
DD457188293C7E63000C49FB /* BLESignalStrengthIndicator.swift in Sources */,
DDFEB3BB29900C1200EE7472 /* CurrentConditionsCompact.swift in Sources */,
DD836AE726F6B38600ABCC23 /* Connect.swift in Sources */,
DD21007F2B0E571300F2F116 /* Settings2.swift in Sources */,
DD5E523F298F5A9E00D21B61 /* AirQualityIndexCompact.swift in Sources */,
DD964FBF296E76EF007C176F /* WaypointFormMapKit.swift in Sources */,
DD3501892852FC3B000FC853 /* Settings.swift in Sources */,

View file

@ -612,7 +612,9 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
}
}
case .neighborinfoApp:
MeshLogger.log("🕸️ MESH PACKET received for Neighbor Info App App UNHANDLED \((try? decodedInfo.packet.jsonString()) ?? "JSON Decode Failure")")
if let neighborInfo = try? NeighborInfo(serializedData: decodedInfo.packet.decoded.payload) {
MeshLogger.log("🕸️ MESH PACKET received for Neighbor Info App App UNHANDLED \(neighborInfo)")
}
case .UNRECOGNIZED:
MeshLogger.log("🕸️ MESH PACKET received for Other App UNHANDLED \(try! decodedInfo.packet.jsonString())")
case .max:

View file

@ -22,7 +22,7 @@ struct MapSettingsForm: View {
var body: some View {
VStack {
NavigationStack {
Form {
Section(header: Text("Map Options")) {
Picker(selection: $mapLayer, label: Text("")) {

View file

@ -80,6 +80,7 @@ struct NodeListItem: View {
HStack {
let preset = ModemPresets(rawValue: Int(modemPreset))
LoRaSignalStrengthMeter(snr: node.snr, rssi: node.rssi, preset: preset ?? ModemPresets.longFast, compact: true)
.padding(.top, 2)
}
}
HStack {

View file

@ -54,6 +54,10 @@ struct MeshMap: View {
format: "expire == nil || expire >= %@", Date() as NSDate
), animation: .none)
private var waypoints: FetchedResults<WaypointEntity>
@FetchRequest(sortDescriptors: [NSSortDescriptor(key: "name", ascending: true)],
predicate: NSPredicate(format: "enabled == true", ""), animation: .none)
private var routes: FetchedResults<RouteEntity>
var body: some View {
@ -123,7 +127,39 @@ struct MeshMap: View {
selectedPosition = (selectedPosition == position ? nil : position)
}
}
/// Route Lines
/// Routes
ForEach(Array(routes), id: \.id) { route in
let routeLocations = Array(route.locations!) as! [LocationEntity]
let routeCoords = routeLocations.compactMap({(loc) -> CLLocationCoordinate2D in
return loc.locationCoordinate ?? LocationHelper.DefaultLocation
})
Annotation("Start", coordinate: routeCoords.first ?? LocationHelper.DefaultLocation) {
ZStack {
Circle()
.fill(Color(.green))
.strokeBorder(.white, lineWidth: 3)
.frame(width: 15, height: 15)
}
}
.annotationTitles(.automatic)
Annotation("Finish", coordinate: routeCoords.last ?? LocationHelper.DefaultLocation) {
ZStack {
Circle()
.fill(Color(.black))
.strokeBorder(.white, lineWidth: 3)
.frame(width: 15, height: 15)
}
}
.annotationTitles(.automatic)
let dashed = StrokeStyle(
lineWidth: 3,
lineCap: .round, lineJoin: .round, dash: [7, 10]
)
MapPolyline(coordinates: routeCoords)
.stroke(Color(UIColor(hex: UInt32(route.color))), style: dashed)
}
/// Node Route Lines
if showRouteLines {
let nodePositions = Array(position.nodePosition!.positions!) as! [PositionEntity]
let routeCoords = nodePositions.compactMap({(pos) -> CLLocationCoordinate2D in
@ -173,6 +209,19 @@ struct MeshMap: View {
}
}
}
.mapScope(mapScope)
.mapStyle(mapStyle)
.mapControls {
MapScaleView(scope: mapScope)
.mapControlVisibility(.automatic)
MapUserLocationButton(scope: mapScope)
.mapControlVisibility(showUserLocation ? .visible : .hidden)
MapPitchToggle(scope: mapScope)
.mapControlVisibility(.automatic)
MapCompass(scope: mapScope)
.mapControlVisibility(.automatic)
}
.controlSize(.regular)
.onTapGesture(count: 1, perform: { location in
newWaypointCoord = reader.convert(location , from: .local)
})
@ -185,23 +234,10 @@ struct MeshMap: View {
editingWaypoint!.expire = Date.now.addingTimeInterval(60 * 480)
editingWaypoint!.id = 0
}
}
}
.mapScope(mapScope)
.mapStyle(mapStyle)
.mapControls {
MapScaleView(scope: mapScope)
.mapControlVisibility(.visible)
if showUserLocation {
MapUserLocationButton(scope: mapScope)
.mapControlVisibility(.visible)
}
MapPitchToggle(scope: mapScope)
.mapControlVisibility(.visible)
MapCompass(scope: mapScope)
.mapControlVisibility(.visible)
}
.controlSize(.regular)
.sheet(item: $selectedPosition) { selection in
PositionPopover(position: selection, popover: false)
.padding()

View file

@ -142,7 +142,7 @@ struct Channels: View {
Picker("Key Size", selection: $channelKeySize) {
Text("Empty").tag(0)
Text("Default").tag(-1)
Text("1 bit").tag(1)
Text("1 byte").tag(1)
Text("128 bit").tag(16)
Text("192 bit").tag(24)
Text("256 bit").tag(32)

View file

@ -19,11 +19,12 @@ struct Routes: View {
@State private var importing = false
@State private var isShowingBadFileAlert = false
@FetchRequest(sortDescriptors: [], animation: .default)
@FetchRequest(sortDescriptors: [NSSortDescriptor(key: "enabled", ascending: false), NSSortDescriptor(key: "name", ascending: true), NSSortDescriptor(key: "date", ascending: false)], animation: .default)
var routes: FetchedResults<RouteEntity>
var body: some View {
NavigationSplitView(columnVisibility: $columnVisibility) {
//VStack {
Button("Import Route") {
importing = true
}
@ -152,6 +153,7 @@ struct Routes: View {
}
.navigationTitle("Route List")
} detail: {
VStack {
if selectedRoute != nil {
let locationArray = selectedRoute?.locations?.array as? [LocationEntity] ?? []
@ -169,7 +171,7 @@ struct Routes: View {
}
}
.annotationTitles(.automatic)
Annotation("Finish", coordinate: locationArray.last?.locationCoordinate ?? LocationHelper.DefaultLocation) {
Annotation("Finish", coordinate: lineCoords.last ?? LocationHelper.DefaultLocation) {
ZStack {
Circle()
.fill(Color(.black))

View file

@ -278,17 +278,17 @@ struct Settings: View {
}
.tag(SettingsSidebar.adminMessageLog)
}
Section(header: Text("Firmware")) {
NavigationLink {
Firmware(node: nodes.first(where: { $0.num == preferredNodeNum }))
} label: {
Image(systemName: "arrow.up.arrow.down.square")
.symbolRenderingMode(.hierarchical)
Text("Firmware Updates")
}
.tag(SettingsSidebar.about)
.disabled(selectedNode > 0 && selectedNode != preferredNodeNum)
}
// Section(header: Text("Firmware")) {
// NavigationLink {
// Firmware(node: nodes.first(where: { $0.num == preferredNodeNum }))
// } label: {
// Image(systemName: "arrow.up.arrow.down.square")
// .symbolRenderingMode(.hierarchical)
// Text("Firmware Updates")
// }
// .tag(SettingsSidebar.about)
// .disabled(selectedNode > 0 && selectedNode != preferredNodeNum)
// }
}
}
.onAppear {

View file

@ -0,0 +1,171 @@
//
// Settings.swift
// MeshtasticApple
//
// Copyright (c) Garth Vander Houwen 6/9/22.
//
import SwiftUI
enum SettingsSidebar: CaseIterable {
case about
case appSettings
case routes
case radioConfig
case moduleConfig
case meshLog
case adminMessageLog
var name: String {
switch self {
case .about:
return "about.meshtastic".localized
case .appSettings:
return "app.settings".localized
case .routes:
return "routes".localized
case .radioConfig:
return "radio.configuration".localized
case .moduleConfig:
return "module.configuration".localized
case .meshLog:
return "mesh.log".localized
case .adminMessageLog:
return "admin.log".localized
}
}
var icon: String {
switch self {
case .about:
return "questionmark.app"
case .appSettings:
return "gearshape".localized
case .routes:
return "routes".localized
case .radioConfig:
return "flipphone".localized
case .moduleConfig:
return "module.configuration".localized
case .meshLog:
return "mesh.log".localized
case .adminMessageLog:
return "admin.log".localized
}
}
}
extension SettingsSidebar: Identifiable {
var id: Self { self }
}
@available(iOS 17.0, macOS 14.0, *)
struct Settings2: View {
@State private var compactColumn = NavigationSplitViewColumn.detail
@State private var columnVisibility = NavigationSplitViewVisibility.automatic
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@FetchRequest(sortDescriptors: [NSSortDescriptor(key: "user.longName", ascending: true)], animation: .default)
private var nodes: FetchedResults<NodeInfoEntity>
@State private var selectedNode: Int = 0
@State private var preferredNodeNum: Int = 0
@State private var selection: SettingsSidebar = .about
enum SettingsContent {
case appSettings
case routes
case shareChannels
case userConfig
case loraConfig
case channelConfig
case bluetoothConfig
case deviceConfig
case displayConfig
case networkConfig
case positionConfig
case cannedMessagesConfig
case detectionSensorConfig
case externalNotificationConfig
case mqttConfig
case rangeTestConfig
case ringtoneConfig
case serialConfig
case telemetryConfig
case meshLog
case adminMessageLog
case about
}
var body: some View {
NavigationSplitView(columnVisibility: $columnVisibility, preferredCompactColumn: $compactColumn) {
List(SettingsSidebar.allCases) { item in
switch(item) {
case .about:
NavigationLink { AboutMeshtastic() } label: {
Image(systemName: item.icon)
.symbolRenderingMode(.hierarchical)
Text(item.name.localized)
}
.tag(item)
case .appSettings:
NavigationLink { AppSettings() } label: {
Image(systemName: item.icon)
.symbolRenderingMode(.hierarchical)
Text(item.name.localized)
}
.tag(item)
case .routes:
NavigationLink { Routes() } label: {
Image(systemName: item.icon)
.symbolRenderingMode(.hierarchical)
Text(item.name.localized)
}
.tag(item)
case .radioConfig:
NavigationLink { Routes() } label: {
Image(systemName: item.icon)
.symbolRenderingMode(.hierarchical)
Text(item.name.localized)
}
.tag(item)
case .moduleConfig:
NavigationLink { Routes() } label: {
Image(systemName: item.icon)
.symbolRenderingMode(.hierarchical)
Text(item.name.localized)
}
.tag(item)
case .meshLog:
NavigationLink { MeshLog() } label: {
Image(systemName: item.icon)
.symbolRenderingMode(.hierarchical)
Text(item.name.localized)
}
.tag(item)
case .adminMessageLog:
NavigationLink { AdminMessageList() } label: {
Image(systemName: item.icon)
.symbolRenderingMode(.hierarchical)
Text(item.name.localized)
}
.tag(item)
}
}
.listStyle(GroupedListStyle())
.navigationTitle("settings")
.navigationBarItems(leading: MeshtasticLogo())
} content: {
List {
if selection == .routes {
Text("Routes Bitechs")
}
}
}
detail: {
Text("Detail")
ContentUnavailableView("select.menu.item", systemImage: "gear")
}
.onChange(of: selection) { value in
columnVisibility = .doubleColumn
compactColumn = .sidebar
}
}
}