Merge pull request #61 from meshtastic/feature/project_cleanup

Assorted Project Cleanup
This commit is contained in:
Garth Vander Houwen 2022-03-07 19:35:26 -08:00 committed by GitHub
commit d1dbe80ab4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 105 additions and 322 deletions

View file

@ -20,8 +20,6 @@
DD47E3CE26F103C600029299 /* NodeList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3CD26F103C600029299 /* NodeList.swift */; };
DD47E3D626F17ED900029299 /* CircleText.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3D526F17ED900029299 /* CircleText.swift */; };
DD47E3D926F3093800029299 /* MessageBubble.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3D826F3093800029299 /* MessageBubble.swift */; };
DD47E3DB26F3901B00029299 /* Channels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3DA26F3901A00029299 /* Channels.swift */; };
DD47E3DD26F390A000029299 /* Messages.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3DC26F390A000029299 /* Messages.swift */; };
DD4A911E2708C65400501B7E /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4A911D2708C65400501B7E /* AppSettings.swift */; };
DD4DED9027AD2975004BA27E /* cannedmessages.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4DED8F27AD2975004BA27E /* cannedmessages.pb.swift */; };
DD5394FC276993AD00AD86B1 /* SwiftProtobuf in Frameworks */ = {isa = PBXBuildFile; productRef = DD5394FB276993AD00AD86B1 /* SwiftProtobuf */; };
@ -89,8 +87,6 @@
DD47E3CD26F103C600029299 /* NodeList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeList.swift; sourceTree = "<group>"; };
DD47E3D526F17ED900029299 /* CircleText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleText.swift; sourceTree = "<group>"; };
DD47E3D826F3093800029299 /* MessageBubble.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageBubble.swift; sourceTree = "<group>"; };
DD47E3DA26F3901A00029299 /* Channels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Channels.swift; sourceTree = "<group>"; };
DD47E3DC26F390A000029299 /* Messages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Messages.swift; sourceTree = "<group>"; };
DD4A911D2708C65400501B7E /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = "<group>"; };
DD4DED8F27AD2975004BA27E /* cannedmessages.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = cannedmessages.pb.swift; sourceTree = "<group>"; };
DD5394FD276BA0EF00AD86B1 /* PositionEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionEntityExtension.swift; sourceTree = "<group>"; };
@ -333,8 +329,6 @@
DDC2E18B26CE25A70042C5E4 /* Messages */ = {
isa = PBXGroup;
children = (
DD47E3DA26F3901A00029299 /* Channels.swift */,
DD47E3DC26F390A000029299 /* Messages.swift */,
DD882F5C2772E4640005BF05 /* Contacts.swift */,
DD1BF2F82776FE2E008C8D2F /* UserMessageList.swift */,
);
@ -542,7 +536,6 @@
DDAF8C5326EB1DF10058C060 /* BLEManager.swift in Sources */,
DDC4D568275499A500A4208E /* Persistence.swift in Sources */,
DD90860E26F69BAE00DC5189 /* NodeMap.swift in Sources */,
DD47E3DB26F3901B00029299 /* Channels.swift in Sources */,
DD8169FF272476C700F4AB02 /* LogDocument.swift in Sources */,
DDAF8C6926ED0D070058C060 /* deviceonly.pb.swift in Sources */,
DDAF8C6B26ED0DD80058C060 /* environmental_measurement.pb.swift in Sources */,
@ -573,7 +566,6 @@
DD539502276DAA6A00AD86B1 /* MapLocation.swift in Sources */,
DDAF8C6726ED0C8C0058C060 /* remote_hardware.pb.swift in Sources */,
DDAF8C6526ED0A490058C060 /* channel.pb.swift in Sources */,
DD47E3DD26F390A000029299 /* Messages.swift in Sources */,
DDC2E15826CE248E0042C5E4 /* MeshtasticClientApp.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -738,7 +730,7 @@
CODE_SIGN_ENTITLEMENTS = MeshtasticClient/MeshtasticClient.entitlements;
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 13;
CURRENT_PROJECT_VERSION = 15;
DEVELOPMENT_ASSET_PATHS = "\"MeshtasticClient/Preview Content\"";
DEVELOPMENT_TEAM = GCH7VS5Y9R;
ENABLE_PREVIEWS = YES;
@ -769,7 +761,7 @@
CODE_SIGN_ENTITLEMENTS = MeshtasticClient/MeshtasticClient.entitlements;
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 13;
CURRENT_PROJECT_VERSION = 15;
DEVELOPMENT_ASSET_PATHS = "\"MeshtasticClient/Preview Content\"";
DEVELOPMENT_TEAM = GCH7VS5Y9R;
ENABLE_PREVIEWS = YES;

View file

@ -98,7 +98,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
self.centralManager.stopScan()
self.isScanning = self.centralManager.isScanning
print("🛑 Stopped Scanning")
}
}
@ -177,7 +176,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
peripheralName = name
}
let newPeripheral = Peripheral(id: peripheral.identifier.uuidString, num: 0, name: peripheralName, shortName: String(peripheralName.suffix(3)), longName: peripheralName, firmwareVersion: "Unknown", rssi: RSSI.intValue, channelUtilization: nil, airTime: nil, subscribed: false, peripheral: peripheral)
let newPeripheral = Peripheral(id: peripheral.identifier.uuidString, num: 0, name: peripheralName, shortName: String(peripheralName.suffix(3)), longName: peripheralName, firmwareVersion: "Unknown", rssi: RSSI.intValue, channelUtilization: nil, airTime: nil, lastUpdate: Date(), subscribed: false, peripheral: peripheral)
let peripheralIndex = peripherals.firstIndex(where: { $0.id == newPeripheral.id })
if peripheralIndex != nil && newPeripheral.peripheral.state != CBPeripheralState.connected {
@ -187,13 +186,17 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
peripherals.append(newPeripheral)
} else {
if newPeripheral.peripheral.state != CBPeripheralState.connected {
peripherals.append(newPeripheral)
print(" Adding peripheral: \(peripheralName)")
}
}
let today = Date()
let fiveMinutesAgo = Calendar.current.date(byAdding: .minute, value: -5, to: today)!
peripherals.removeAll(where: { $0.lastUpdate <= fiveMinutesAgo})
}
// Called when a peripheral is connected
@ -379,28 +382,15 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
}
switch characteristic.uuid {
case FROMNUM_UUID:
//Dont need to call readValue here, the value is already here from the notify
//readValue in turn calls this callback so we end up spamming the node with fromnum reads continuously
//peripheral.readValue(for: FROMNUM_characteristic)
let characteristicValue: [UInt8] = [UInt8](characteristic.value!)
let bigEndianUInt32 = characteristicValue.withUnsafeBytes { $0.load(as: UInt32.self) }
let returnValue = CFByteOrderGetCurrent() == CFByteOrder(CFByteOrderLittleEndian.rawValue)
? UInt32(bigEndian: bigEndianUInt32) : bigEndianUInt32
// print(returnValue)
case FROMRADIO_UUID:
if characteristic.value == nil || characteristic.value!.isEmpty {
return
}
// print(characteristic.value ?? "no value")
// print(characteristic.value?.hexDescription ?? "no value")
var decodedInfo = FromRadio()
decodedInfo = try! FromRadio(serializedData: characteristic.value!)
// print("Print DecodedInfo")
// print(decodedInfo)
// MARK: Incoming MyInfo Packet
if decodedInfo.myInfo.myNodeNum != 0 {
@ -417,8 +407,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
myInfo.hasGps = decodedInfo.myInfo.hasGps_p
myInfo.channelUtilization = decodedInfo.myInfo.channelUtilization
// Swift does strings weird, this does work
let lastDotIndex = decodedInfo.myInfo.firmwareVersion.lastIndex(of: ".")//.lastIndex(of: ".", offsetBy: -1)
// Swift does strings weird, this does work to get the version without the github hash
let lastDotIndex = decodedInfo.myInfo.firmwareVersion.lastIndex(of: ".")
var version = decodedInfo.myInfo.firmwareVersion[...(lastDotIndex ?? String.Index(utf16Offset: 6, in: decodedInfo.myInfo.firmwareVersion))]
version = version.dropLast()
myInfo.firmwareVersion = String(version)
@ -494,15 +484,18 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
print("💥 Fetch MyInfo Error")
}
// Use a timer to keep track of position updates, context to pass the radio name with the timer and the RunLoop to prevent
// the timer from running on the main UI thread
if self.positionTimer != nil {
self.positionTimer!.invalidate()
// MARK: Share Location Position Update Timer
// Use context to pass the radio name with the timer
// Use a RunLoop to prevent the timer from running on the main UI thread
if userSettings?.provideLocation ?? false {
if self.positionTimer != nil {
self.positionTimer!.invalidate()
}
let context = ["name": "@\(peripheral.name ?? "Unknown")"]
self.positionTimer = Timer.scheduledTimer(timeInterval: TimeInterval((userSettings?.provideLocationInterval ?? 900)), target: self, selector: #selector(positionTimerFired), userInfo: context, repeats: true)
RunLoop.current.add(self.positionTimer!, forMode: .common)
}
let context = ["name": "@\(peripheral.name ?? "Unknown")"]
self.positionTimer = Timer.scheduledTimer(timeInterval: 30.0, target: self, selector: #selector(positionTimerFired), userInfo: context, repeats: true)
RunLoop.current.add(self.positionTimer!, forMode: .common)
}
// MARK: Incoming Node Info Packet
@ -801,8 +794,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
try context!.save()
if meshLoggingEnabled { MeshLogger.log("💾 Updated NodeInfo SNR and Time from Node Info App Packet For: \(fetchedNode[0].num)")}
print("💾 Updated NodeInfo SNR and Time from Packet For: \(fetchedNode[0].num)")
if meshLoggingEnabled { MeshLogger.log("💾 Updated NodeInfo SNR \(decodedInfo.packet.rxSnr) and Time from Node Info App Packet For: \(fetchedNode[0].num)")}
print("💾 Updated NodeInfo SNR \(decodedInfo.packet.rxSnr) and Time from Packet For: \(fetchedNode[0].num)")
} catch {
@ -873,9 +866,9 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
try context!.save()
if meshLoggingEnabled {
MeshLogger.log("💾 Updated NodeInfo Position Coordinates, SNR and Time from Position App Packet For: \(fetchedNode[0].num)")
MeshLogger.log("💾 Updated NodeInfo Position Coordinates, SNR \(decodedInfo.packet.rxSnr) and Time from Position App Packet For: \(fetchedNode[0].num)")
}
print("💾 Updated NodeInfo Position Coordinates, SNR and Time from Position App Packet For:: \(fetchedNode[0].num)")
print("💾 Updated NodeInfo Position Coordinates, SNR \(decodedInfo.packet.rxSnr) and Time from Position App Packet For:: \(fetchedNode[0].num)")
} catch {
@ -919,10 +912,11 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
let nsError = error as NSError
print("💥 Error Saving ACK for message MessageID \(decodedInfo.packet.id) Error: \(nsError)")
}
}
} else {
if meshLoggingEnabled { MeshLogger.log(" MESH PACKET received for Routing App UNHANDLED \(try decodedInfo.packet.jsonString())") }
print(" MESH PACKET received for Routing App UNHANDLED \(try decodedInfo.packet.jsonString())")
if meshLoggingEnabled { MeshLogger.log(" MESH PACKET received for Routing App UNHANDLED \(try decodedInfo.packet.jsonString())") }
print(" MESH PACKET received for Routing App UNHANDLED \(try decodedInfo.packet.jsonString())")
}
} else if decodedInfo.packet.decoded.portnum == PortNum.environmentalMeasurementApp {
@ -1194,10 +1188,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
print("Failed to send positon to device")
}
}
// Request config to update MyNodeInfo data periodically as well as all nodes
}
}
}

View file

@ -11,10 +11,11 @@ struct Peripheral: Identifiable {
var rssi: Int
var channelUtilization: Float?
var airTime: Float?
var lastUpdate: Date
var subscribed: Bool
var peripheral: CBPeripheral
init(id: String, num: Int64, name: String, shortName: String, longName: String, firmwareVersion: String, rssi: Int, channelUtilization: Float?, airTime: Float?, subscribed: Bool, peripheral: CBPeripheral) {
init(id: String, num: Int64, name: String, shortName: String, longName: String, firmwareVersion: String, rssi: Int, channelUtilization: Float?, airTime: Float?, lastUpdate: Date, subscribed: Bool, peripheral: CBPeripheral) {
self.id = id
self.num = num
self.name = name
@ -24,6 +25,7 @@ struct Peripheral: Identifiable {
self.rssi = rssi
self.channelUtilization = channelUtilization
self.airTime = airTime
self.lastUpdate = lastUpdate
self.subscribed = subscribed
self.peripheral = peripheral
}

View file

@ -1,44 +0,0 @@
//import Foundation
//import SwiftUI
//import CoreBluetooth
//
//struct Channels: View {
//
// @State private var isShowingDetailView = true
//
// var body: some View {
//
// NavigationView {
//
// NavigationLink(destination: Messages(), isActive: $isShowingDetailView) {
//
// List {
//
// HStack {
//
// Image(systemName: "megaphone.fill")
// .font(.largeTitle)
// .symbolRenderingMode(.hierarchical)
// .padding(.trailing)
// .foregroundColor(.accentColor)
//
// Text("All - Broadcast")
// .font(.largeTitle)
//
// }.padding()
// }
// }
// .navigationTitle("Contacts")
// }
// .navigationViewStyle(DoubleColumnNavigationViewStyle())
// }
//}
//
//struct MessageList_Previews: PreviewProvider {
//
// static var previews: some View {
// Group {
// Channels()
// }
// }
//}

View file

@ -1,204 +0,0 @@
//import SwiftUI
//import MapKit
//import Foundation
//import CoreLocation
//
//struct Messages: View {
//
// enum Field: Hashable {
// case messageText
// }
//
// // CoreData
// @Environment(\.managedObjectContext) var context
// @EnvironmentObject var bleManager: BLEManager
//
// @FetchRequest(
// sortDescriptors: [NSSortDescriptor(keyPath: \MessageEntity.messageTimestamp, ascending: true)],
// animation: .default)
// var messages: FetchedResults<MessageEntity>
//
// // Keyboard State
// @State var typingMessage: String = ""
// @State private var totalBytes = 0
// private var maxbytes = 228
// @State private var lastTypingMessage = ""
// @FocusState private var focusedField: Field?
//
// @State var showDeleteMessageAlert = false
// @State private var deleteMessageId: Int64 = 0
//
// public var broadcastNodeId: UInt32 = 4294967295
//
// var body: some View {
//
// Text("\(messages.count) Messages").font(.caption)
// GeometryReader { bounds in
//
// VStack {
//
// ScrollViewReader { scrollView in
//
// if self.messages.count > 0 {
//
// ScrollView {
//
// ForEach(messages) { message in
//
// HStack(alignment: .top) {
// let currentUser: Bool = (bleManager.connectedPeripheral == nil) ? false : ((bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.num == message.fromUser?.num) ? true : false )
//
// CircleText(text: (message.fromUser?.shortName ?? "???"), color: currentUser ? .accentColor : Color(.darkGray)).padding(.all, 5)
// .gesture(LongPressGesture(minimumDuration: 2)
// .onEnded {_ in
// print(messages)
// print("I want to delete message: \(message.messageId)")
// self.showDeleteMessageAlert = true
// self.deleteMessageId = message.messageId
//
// print(deleteMessageId)
// })
//
// VStack(alignment: .leading) {
// Text(message.messagePayload ?? "EMPTY MESSAGE")
// .textSelection(.enabled)
// .padding(10)
// .foregroundColor(.white)
// .background(currentUser ? Color.blue : Color(.darkGray))
// .cornerRadius(10)
// HStack(spacing: 4) {
//
// let time = Int32(message.messageTimestamp)
// let messageDate = Date(timeIntervalSince1970: TimeInterval(time))
//
// if time != 0 {
// Text(messageDate, style: .date).font(.caption2).foregroundColor(.gray)
// Text(messageDate, style: .time).font(.caption2).foregroundColor(.gray)
// } else {
// Text("Unknown").font(.caption2).foregroundColor(.gray)
// }
// }
// .padding(.bottom, 10)
// }
// Spacer()
// }
// .alert(isPresented: $showDeleteMessageAlert) {
// Alert(title: Text("Are you sure you want to delete this message?"), message: Text("This action is permanent."),
// primaryButton: .destructive(Text("Delete")) {
// print("OK button tapped")
// if deleteMessageId > 0 {
//
// let message = messages.first(where: { $0.messageId == deleteMessageId })
//
// context.delete(message!)
// do {
// try context.save()
//
// deleteMessageId = 0
//
// } catch {
// print("Failed to delete message \(deleteMessageId)")
// }
//
// }
// },
// secondaryButton: .cancel()
// )
// }
// }
// .onChange(of: messages.count, perform: { newValue in
//
// if messages.count > 0 {
//
// scrollView.scrollTo(messages[messages.count-1].id, anchor: .bottom)
// }
// }
// )
// .onAppear(perform: {
//
// self.bleManager.context = context
// if messages.count > 0 {
//
// scrollView.scrollTo(messages[messages.count-1].id, anchor: .bottom)
// }
// })
// }
// .padding(.horizontal)
// }
// }
//
// HStack(alignment: .top) {
//
// ZStack {
//
// let kbType = UIKeyboardType(rawValue: UserDefaults.standard.object(forKey: "keyboardType") as? Int ?? 0)
// TextEditor(text: $typingMessage)
// .onChange(of: typingMessage, perform: { value in
//
// let size = value.utf8.count
// totalBytes = size
// if totalBytes <= maxbytes {
// // Allow the user to type
// lastTypingMessage = typingMessage
// } else {
// // Set the message back and remove the bytes over the count
// self.typingMessage = lastTypingMessage
// }
// })
// .keyboardType(kbType!)
// .toolbar {
// ToolbarItemGroup(placement: .keyboard) {
//
// Button("Dismiss Keyboard") {
// focusedField = nil
// }
// .font(.subheadline)
//
// Spacer()
//
// ProgressView("Bytes: \(totalBytes) / \(maxbytes)", value: Double(totalBytes), total: Double(maxbytes))
// .frame(width: 130)
// .padding(5)
// .font(.subheadline)
// .accentColor(.accentColor)
// }
// }
// .padding(.horizontal, 8)
// .focused($focusedField, equals: .messageText)
// .multilineTextAlignment(.leading)
// .frame(minHeight: bounds.size.height / 4, maxHeight: bounds.size.height / 4)
//
// Text(typingMessage).opacity(0).padding(.all, 0)
//
// }
// .overlay(RoundedRectangle(cornerRadius: 20).stroke(.tertiary, lineWidth: 1))
// .padding(.bottom, 15)
//
// Button(action: {
// if self.bleManager.sendMessage(message: typingMessage, toUserNum: Int64(self.bleManager.broadcastNodeNum)) {
// typingMessage = ""
// focusedField = nil
// }
//
// }) {
// Image(systemName: "arrow.up.circle.fill").font(.largeTitle).foregroundColor(.blue)
// }
//
// }
// .padding(.all, 15)
// }
// }
// .navigationTitle("All - Broadcast")
// .navigationBarTitleDisplayMode(.inline)
// .navigationBarItems(trailing:
//
// ZStack {
//
// ConnectedDevice(
// bluetoothOn: self.bleManager.isSwitchedOn,
// deviceConnected: self.bleManager.connectedPeripheral != nil,
// name: (self.bleManager.connectedPeripheral != nil) ? self.bleManager.connectedPeripheral.shortName : "???")
// }
// )
// }
//}

View file

@ -335,20 +335,17 @@ struct UserMessageList: View {
self.bleManager.context = context
self.bleManager.userSettings = userSettings
if allMessages.count > 2 {
if allMessages.count > 0 {
scrollView.scrollTo(allMessages.firstIndex(of: allMessages.last! ), anchor: .bottom)
withAnimation(Animation.spring().delay(0.5)) {
scrollView.scrollTo(allMessages.firstIndex(of: allMessages.last! ), anchor: .bottom)
}
}
})
.onChange(of: allMessages.count, perform: { count in
//self.context.refresh(user, mergeChanges: true)
let index = count - 1
if index > 3 {
scrollView.scrollTo(index, anchor: .bottom)
withAnimation(Animation.spring().delay(0.5)) {
scrollView.scrollTo(allMessages.firstIndex(of: allMessages.last! ), anchor: .bottom)
}
})
}

View file

@ -53,6 +53,31 @@ enum MeshMapType: String, CaseIterable, Identifiable {
}
}
enum LocationUpdateInterval: Int, CaseIterable, Identifiable {
case oneMinute = 60
case fiveMinutes = 300
case tenMinutes = 600
case fifteenMinutes = 900
var id: Int { self.rawValue }
var description: String {
get {
switch self {
case .oneMinute:
return "One Minute"
case .fiveMinutes:
return "Five Minutes"
case .tenMinutes:
return "Ten Minutes"
case .fifteenMinutes:
return "Fifteen Minutes"
}
}
}
}
class UserSettings: ObservableObject {
@Published var meshtasticUsername: String {
didSet {
@ -74,6 +99,11 @@ class UserSettings: ObservableObject {
UserDefaults.standard.set(provideLocation, forKey: "provideLocation")
}
}
@Published var provideLocationInterval: Int {
didSet {
UserDefaults.standard.set(provideLocationInterval, forKey: "provideLocationInterval")
}
}
@Published var keyboardType: Int {
didSet {
UserDefaults.standard.set(keyboardType, forKey: "keyboardType")
@ -90,7 +120,6 @@ class UserSettings: ObservableObject {
UserDefaults.standard.set(meshMapType, forKey: "meshMapType")
}
}
@Published var meshMapCustomTileServer: String {
didSet {
UserDefaults.standard.set(meshMapCustomTileServer, forKey: "meshMapCustomTileServer")
@ -103,6 +132,7 @@ class UserSettings: ObservableObject {
self.preferredPeripheralName = UserDefaults.standard.object(forKey: "preferredPeripheralName") as? String ?? ""
self.preferredPeripheralId = UserDefaults.standard.object(forKey: "preferredPeripheralId") as? String ?? ""
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
self.meshActivityLog = UserDefaults.standard.object(forKey: "meshActivityLog") as? Bool ?? false
self.meshMapType = UserDefaults.standard.string(forKey: "meshMapType") ?? "hybrid"
@ -139,23 +169,42 @@ struct AppSettings: View {
.keyboardType(.asciiCapable)
.disableAutocorrection(true)
.listRowSeparator(.visible)
HStack {
Label("Radio", systemImage: "flipphone")
Text(userSettings.preferredPeripheralName)
.foregroundColor(.gray)
}
Text("This option is set via the preferred radio toggle for the connected device on the bluetooth tab.")
.font(.caption)
.listRowSeparator(.hidden)
Text("The preferred radio will automatically reconnect if it becomes disconnected and is still within range.")
.font(.caption2)
.foregroundColor(.gray)
}
Section(header: Text("LOCATION OPTIONS")) {
Toggle(isOn: $userSettings.provideLocation) {
Label("Provide location to mesh", systemImage: "location.circle.fill")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
.listRowSeparator(.visible)
Label("Preferred Radio", systemImage: "flipphone")
.listRowSeparator(.hidden)
Text(userSettings.preferredPeripheralName)
.foregroundColor(.gray)
Text("This option is set via the preferred radio toggle for the connected device on the bluetooth tab.")
.font(.caption)
.listRowSeparator(.hidden)
Text("The preferred radio will automatically reconnect if it becomes disconnected and is still within range. This device is assumed to be the primary radio used for messaging.")
.font(.caption2)
.foregroundColor(.gray)
if userSettings.provideLocation {
Picker(" Update Interval", selection: $userSettings.provideLocationInterval) {
ForEach(LocationUpdateInterval.allCases) { lu in
Text(lu.description)
}
}
.pickerStyle(DefaultPickerStyle())
Text("How frequently your phone will send your location to the device, location updates to the mesh are managed by the device.")
.font(.caption)
.listRowSeparator(.visible)
}
}
Section(header: Text("MESSAGING OPTIONS")) {
@ -181,10 +230,10 @@ struct AppSettings: View {
Label("Log all Mesh activity", systemImage: "network")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
if userSettings.meshActivityLog {
NavigationLink(destination: MeshLog()) {
Text("View Mesh Log")
}
if userSettings.meshActivityLog {
NavigationLink(destination: MeshLog()) {
Text("View Mesh Log")
}
.listRowSeparator(.visible)
}
}