mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Assorted updates
This commit is contained in:
parent
44859fb985
commit
24868b4a28
9 changed files with 264 additions and 32 deletions
|
|
@ -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 */,
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ struct MapSettingsForm: View {
|
|||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
NavigationStack {
|
||||
Form {
|
||||
Section(header: Text("Map Options")) {
|
||||
Picker(selection: $mapLayer, label: Text("")) {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
171
Meshtastic/Views/Settings/Settings2.swift
Normal file
171
Meshtastic/Views/Settings/Settings2.swift
Normal 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
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue