mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Merge pull request #61 from meshtastic/feature/project_cleanup
Assorted Project Cleanup
This commit is contained in:
commit
d1dbe80ab4
7 changed files with 105 additions and 322 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
@ -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 : "???")
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
//}
|
||||
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue