mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Stop clearing channels on each connect
This commit is contained in:
parent
15ee57f23b
commit
79d5aab240
3 changed files with 238 additions and 236 deletions
|
|
@ -532,7 +532,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
connectedPeripheral.name = myInfo?.bleName ?? "unknown".localized
|
||||
connectedPeripheral.longName = myInfo?.bleName ?? "unknown".localized
|
||||
}
|
||||
tryClearExistingChannels()
|
||||
//tryClearExistingChannels()
|
||||
}
|
||||
// NodeInfo
|
||||
if decodedInfo.nodeInfo.num > 0 {// && !invalidVersion {
|
||||
|
|
|
|||
|
|
@ -154,7 +154,10 @@ func channelPacket (channel: Channel, fromNum: Int64, context: NSManagedObjectCo
|
|||
return
|
||||
}
|
||||
if mutableChannels.contains(newChannel) {
|
||||
mutableChannels.replaceObject(at: Int(newChannel.index), with: newChannel)
|
||||
let oldChannel = mutableChannels.first(where: {($0 as AnyObject).index == newChannel.index }) as! ChannelEntity
|
||||
newChannel.mute = oldChannel.mute
|
||||
let index = mutableChannels.index(of: oldChannel as Any)
|
||||
mutableChannels.replaceObject(at: index, with: newChannel)
|
||||
} else {
|
||||
mutableChannels.add(newChannel)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@ struct Channels: View {
|
|||
channelName = channel.name ?? ""
|
||||
uplink = channel.uplinkEnabled
|
||||
downlink = channel.downlinkEnabled
|
||||
isPresentingEditView = true
|
||||
hasChanges = false
|
||||
isPresentingEditView = true
|
||||
}) {
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
|
|
@ -94,6 +94,238 @@ struct Channels: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $isPresentingEditView) {
|
||||
#if targetEnvironment(macCatalyst)
|
||||
Text("channel")
|
||||
.font(.largeTitle)
|
||||
.padding()
|
||||
#endif
|
||||
Form {
|
||||
HStack {
|
||||
Text("name")
|
||||
Spacer()
|
||||
TextField(
|
||||
"Channel Name",
|
||||
text: $channelName
|
||||
)
|
||||
.disableAutocorrection(true)
|
||||
.keyboardType(.alphabet)
|
||||
.foregroundColor(Color.gray)
|
||||
.onChange(of: channelName, perform: { _ in
|
||||
channelName = channelName.replacing(" ", with: "")
|
||||
let totalBytes = channelName.utf8.count
|
||||
// Only mess with the value if it is too big
|
||||
if totalBytes > 11 {
|
||||
let firstNBytes = Data(channelName.utf8.prefix(11))
|
||||
if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) {
|
||||
// Set the channelName back to the last place where it was the right size
|
||||
channelName = maxBytesString
|
||||
}
|
||||
}
|
||||
hasChanges = true
|
||||
})
|
||||
}
|
||||
HStack {
|
||||
Picker("Key Size", selection: $channelKeySize) {
|
||||
Text("Empty").tag(0)
|
||||
Text("Default").tag(-1)
|
||||
Text("1 byte").tag(1)
|
||||
Text("128 bit").tag(16)
|
||||
Text("192 bit").tag(24)
|
||||
Text("256 bit").tag(32)
|
||||
}
|
||||
.pickerStyle(DefaultPickerStyle())
|
||||
Spacer()
|
||||
Button {
|
||||
if channelKeySize == -1 {
|
||||
channelKey = "AQ=="
|
||||
} else {
|
||||
let key = generateChannelKey(size: channelKeySize)
|
||||
channelKey = key
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "lock.rotation")
|
||||
.font(.title)
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.small)
|
||||
}
|
||||
HStack(alignment: .center) {
|
||||
Text("Key")
|
||||
Spacer()
|
||||
TextField(
|
||||
"Key",
|
||||
text: $channelKey,
|
||||
axis: .vertical
|
||||
)
|
||||
.padding(6)
|
||||
.disableAutocorrection(true)
|
||||
.keyboardType(.alphabet)
|
||||
.foregroundColor(Color.gray)
|
||||
.textSelection(.enabled)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 10.0)
|
||||
.stroke(
|
||||
hasValidKey ?
|
||||
Color.clear :
|
||||
Color.red
|
||||
, lineWidth: 2.0)
|
||||
|
||||
)
|
||||
.onChange(of: channelKey, perform: { _ in
|
||||
let tempKey = Data(base64Encoded: channelKey) ?? Data()
|
||||
if tempKey.count == channelKeySize || channelKeySize == -1{
|
||||
hasValidKey = true
|
||||
}
|
||||
else {
|
||||
hasValidKey = false
|
||||
}
|
||||
hasChanges = true
|
||||
})
|
||||
.disabled(channelKeySize <= 0)
|
||||
}
|
||||
HStack {
|
||||
if channelRole == 1 {
|
||||
Picker("Channel Role", selection: $channelRole) {
|
||||
Text("Primary").tag(1)
|
||||
}
|
||||
.pickerStyle(.automatic)
|
||||
.disabled(true)
|
||||
} else {
|
||||
Text("Channel Role")
|
||||
Spacer()
|
||||
Picker("Channel Role", selection: $channelRole) {
|
||||
Text("Disabled").tag(0)
|
||||
Text("Secondary").tag(2)
|
||||
}
|
||||
.pickerStyle(.segmented)
|
||||
}
|
||||
}
|
||||
Toggle("Uplink Enabled", isOn: $uplink)
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
Toggle("Downlink Enabled", isOn: $downlink)
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
}
|
||||
.onAppear {
|
||||
let tempKey = Data(base64Encoded: channelKey) ?? Data()
|
||||
if tempKey.count == channelKeySize || channelKeySize == -1{
|
||||
hasValidKey = true
|
||||
}
|
||||
else {
|
||||
hasValidKey = false
|
||||
}
|
||||
}
|
||||
.onChange(of: channelName) { _ in
|
||||
hasChanges = true
|
||||
}
|
||||
.onChange(of: channelKeySize) { _ in
|
||||
if channelKeySize == -1 {
|
||||
channelKey = "AQ=="
|
||||
} else {
|
||||
let key = generateChannelKey(size: channelKeySize)
|
||||
channelKey = key
|
||||
}
|
||||
hasChanges = true
|
||||
}
|
||||
.onChange(of: channelKey) { _ in
|
||||
hasChanges = true
|
||||
}
|
||||
.onChange(of: channelRole) { _ in
|
||||
hasChanges = true
|
||||
}
|
||||
.onChange(of: uplink) { _ in
|
||||
hasChanges = true
|
||||
}
|
||||
.onChange(of: downlink) { _ in
|
||||
hasChanges = true
|
||||
}
|
||||
HStack {
|
||||
Button {
|
||||
var channel = Channel()
|
||||
channel.index = channelIndex
|
||||
channel.role = ChannelRoles(rawValue: channelRole)?.protoEnumValue() ?? .secondary
|
||||
if channel.role != Channel.Role.disabled {
|
||||
channel.index = channelIndex
|
||||
channel.settings.name = channelName
|
||||
channel.settings.psk = Data(base64Encoded: channelKey) ?? Data()
|
||||
channel.settings.uplinkEnabled = uplink
|
||||
channel.settings.downlinkEnabled = downlink
|
||||
|
||||
let newChannel = ChannelEntity(context: context)
|
||||
newChannel.id = Int32(channel.index)
|
||||
newChannel.index = Int32(channel.index)
|
||||
newChannel.uplinkEnabled = channel.settings.uplinkEnabled
|
||||
newChannel.downlinkEnabled = channel.settings.downlinkEnabled
|
||||
newChannel.name = channel.settings.name
|
||||
newChannel.role = Int32(channel.role.rawValue)
|
||||
newChannel.psk = channel.settings.psk
|
||||
guard let mutableChannels = node?.myInfo?.channels?.mutableCopy() as? NSMutableOrderedSet else {
|
||||
return
|
||||
}
|
||||
if mutableChannels.contains(newChannel) {
|
||||
mutableChannels.replaceObject(at: Int(newChannel.index), with: newChannel)
|
||||
} else {
|
||||
mutableChannels.add(newChannel)
|
||||
}
|
||||
node!.myInfo!.channels = mutableChannels.copy() as? NSOrderedSet
|
||||
context.refresh(newChannel, mergeChanges: true)
|
||||
do {
|
||||
try context.save()
|
||||
print("💾 Saved Channel: \(channel.settings.name)")
|
||||
} catch {
|
||||
context.rollback()
|
||||
let nsError = error as NSError
|
||||
print("💥 Unresolved Core Data error in the channel editor. Error: \(nsError)")
|
||||
}
|
||||
} else {
|
||||
if channelIndex <= node!.myInfo!.channels?.count ?? 0 {
|
||||
guard let channelEntity = node!.myInfo!.channels?[Int(channelIndex)] as? ChannelEntity else {
|
||||
return
|
||||
}
|
||||
context.delete(channelEntity)
|
||||
do {
|
||||
try context.save()
|
||||
print("💾 Deleted Channel: \(channel.settings.name)")
|
||||
} catch {
|
||||
context.rollback()
|
||||
let nsError = error as NSError
|
||||
print("💥 Unresolved Core Data error in the channel editor. Error: \(nsError)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let adminMessageId = bleManager.saveChannel(channel: channel, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
self.isPresentingEditView = false
|
||||
channelName = ""
|
||||
channelRole = 2
|
||||
hasChanges = false
|
||||
_ = bleManager.getChannel(channel: channel, fromUser: node!.user!, toUser: node!.user!)
|
||||
}
|
||||
} label: {
|
||||
Label("save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil || !hasChanges || !hasValidKey)
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding(.bottom)
|
||||
#if targetEnvironment(macCatalyst)
|
||||
Button {
|
||||
isPresentingEditView = false
|
||||
} label: {
|
||||
Label("close", systemImage: "xmark")
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding(.bottom)
|
||||
#endif
|
||||
}
|
||||
.presentationDetents([.medium, .large])
|
||||
}
|
||||
if node?.myInfo?.channels?.array.count ?? 0 < 8 && node != nil {
|
||||
|
||||
Button {
|
||||
|
|
@ -121,239 +353,6 @@ struct Channels: View {
|
|||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding()
|
||||
.sheet(isPresented: $isPresentingEditView) {
|
||||
|
||||
#if targetEnvironment(macCatalyst)
|
||||
Text("channel")
|
||||
.font(.largeTitle)
|
||||
.padding()
|
||||
#endif
|
||||
Form {
|
||||
HStack {
|
||||
Text("name")
|
||||
Spacer()
|
||||
TextField(
|
||||
"Channel Name",
|
||||
text: $channelName
|
||||
)
|
||||
.disableAutocorrection(true)
|
||||
.keyboardType(.alphabet)
|
||||
.foregroundColor(Color.gray)
|
||||
.onChange(of: channelName, perform: { _ in
|
||||
channelName = channelName.replacing(" ", with: "")
|
||||
let totalBytes = channelName.utf8.count
|
||||
// Only mess with the value if it is too big
|
||||
if totalBytes > 11 {
|
||||
let firstNBytes = Data(channelName.utf8.prefix(11))
|
||||
if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) {
|
||||
// Set the channelName back to the last place where it was the right size
|
||||
channelName = maxBytesString
|
||||
}
|
||||
}
|
||||
hasChanges = true
|
||||
})
|
||||
}
|
||||
HStack {
|
||||
Picker("Key Size", selection: $channelKeySize) {
|
||||
Text("Empty").tag(0)
|
||||
Text("Default").tag(-1)
|
||||
Text("1 byte").tag(1)
|
||||
Text("128 bit").tag(16)
|
||||
Text("192 bit").tag(24)
|
||||
Text("256 bit").tag(32)
|
||||
}
|
||||
.pickerStyle(DefaultPickerStyle())
|
||||
Spacer()
|
||||
Button {
|
||||
if channelKeySize == -1 {
|
||||
channelKey = "AQ=="
|
||||
} else {
|
||||
let key = generateChannelKey(size: channelKeySize)
|
||||
channelKey = key
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "lock.rotation")
|
||||
.font(.title)
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.small)
|
||||
}
|
||||
HStack(alignment: .center) {
|
||||
Text("Key")
|
||||
Spacer()
|
||||
TextField(
|
||||
"Key",
|
||||
text: $channelKey,
|
||||
axis: .vertical
|
||||
)
|
||||
.padding(6)
|
||||
.disableAutocorrection(true)
|
||||
.keyboardType(.alphabet)
|
||||
.foregroundColor(Color.gray)
|
||||
.textSelection(.enabled)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 10.0)
|
||||
.stroke(
|
||||
hasValidKey ?
|
||||
Color.clear :
|
||||
Color.red
|
||||
, lineWidth: 2.0)
|
||||
|
||||
)
|
||||
.onChange(of: channelKey, perform: { _ in
|
||||
let tempKey = Data(base64Encoded: channelKey) ?? Data()
|
||||
if tempKey.count == channelKeySize || channelKeySize == -1{
|
||||
hasValidKey = true
|
||||
}
|
||||
else {
|
||||
hasValidKey = false
|
||||
}
|
||||
hasChanges = true
|
||||
})
|
||||
.disabled(channelKeySize <= 0)
|
||||
}
|
||||
HStack {
|
||||
if channelRole == 1 {
|
||||
Picker("Channel Role", selection: $channelRole) {
|
||||
Text("Primary").tag(1)
|
||||
}
|
||||
.pickerStyle(.automatic)
|
||||
.disabled(true)
|
||||
} else {
|
||||
Text("Channel Role")
|
||||
Spacer()
|
||||
Picker("Channel Role", selection: $channelRole) {
|
||||
Text("Disabled").tag(0)
|
||||
Text("Secondary").tag(2)
|
||||
}
|
||||
.pickerStyle(.segmented)
|
||||
}
|
||||
}
|
||||
Toggle("Uplink Enabled", isOn: $uplink)
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
Toggle("Downlink Enabled", isOn: $downlink)
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
}
|
||||
.onAppear {
|
||||
let tempKey = Data(base64Encoded: channelKey) ?? Data()
|
||||
if tempKey.count == channelKeySize || channelKeySize == -1{
|
||||
hasValidKey = true
|
||||
}
|
||||
else {
|
||||
hasValidKey = false
|
||||
}
|
||||
}
|
||||
.onChange(of: channelName) { _ in
|
||||
hasChanges = true
|
||||
}
|
||||
.onChange(of: channelKeySize) { _ in
|
||||
if channelKeySize == -1 {
|
||||
channelKey = "AQ=="
|
||||
} else {
|
||||
let key = generateChannelKey(size: channelKeySize)
|
||||
channelKey = key
|
||||
}
|
||||
hasChanges = true
|
||||
}
|
||||
.onChange(of: channelKey) { _ in
|
||||
hasChanges = true
|
||||
}
|
||||
.onChange(of: channelRole) { _ in
|
||||
hasChanges = true
|
||||
}
|
||||
.onChange(of: uplink) { _ in
|
||||
hasChanges = true
|
||||
}
|
||||
.onChange(of: downlink) { _ in
|
||||
hasChanges = true
|
||||
}
|
||||
HStack {
|
||||
Button {
|
||||
var channel = Channel()
|
||||
channel.index = channelIndex
|
||||
channel.role = ChannelRoles(rawValue: channelRole)?.protoEnumValue() ?? .secondary
|
||||
if channel.role != Channel.Role.disabled {
|
||||
channel.index = channelIndex
|
||||
channel.settings.name = channelName
|
||||
channel.settings.psk = Data(base64Encoded: channelKey) ?? Data()
|
||||
channel.settings.uplinkEnabled = uplink
|
||||
channel.settings.downlinkEnabled = downlink
|
||||
|
||||
let newChannel = ChannelEntity(context: context)
|
||||
newChannel.id = Int32(channel.index)
|
||||
newChannel.index = Int32(channel.index)
|
||||
newChannel.uplinkEnabled = channel.settings.uplinkEnabled
|
||||
newChannel.downlinkEnabled = channel.settings.downlinkEnabled
|
||||
newChannel.name = channel.settings.name
|
||||
newChannel.role = Int32(channel.role.rawValue)
|
||||
newChannel.psk = channel.settings.psk
|
||||
guard let mutableChannels = node?.myInfo?.channels?.mutableCopy() as? NSMutableOrderedSet else {
|
||||
return
|
||||
}
|
||||
if mutableChannels.contains(newChannel) {
|
||||
mutableChannels.replaceObject(at: Int(newChannel.index), with: newChannel)
|
||||
} else {
|
||||
mutableChannels.add(newChannel)
|
||||
}
|
||||
node!.myInfo!.channels = mutableChannels.copy() as? NSOrderedSet
|
||||
context.refresh(newChannel, mergeChanges: true)
|
||||
do {
|
||||
try context.save()
|
||||
print("💾 Saved Channel: \(channel.settings.name)")
|
||||
} catch {
|
||||
context.rollback()
|
||||
let nsError = error as NSError
|
||||
print("💥 Unresolved Core Data error in the channel editor. Error: \(nsError)")
|
||||
}
|
||||
} else {
|
||||
if channelIndex <= node!.myInfo!.channels?.count ?? 0 {
|
||||
guard let channelEntity = node!.myInfo!.channels?[Int(channelIndex)] as? ChannelEntity else {
|
||||
return
|
||||
}
|
||||
context.delete(channelEntity)
|
||||
do {
|
||||
try context.save()
|
||||
print("💾 Deleted Channel: \(channel.settings.name)")
|
||||
} catch {
|
||||
context.rollback()
|
||||
let nsError = error as NSError
|
||||
print("💥 Unresolved Core Data error in the channel editor. Error: \(nsError)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let adminMessageId = bleManager.saveChannel(channel: channel, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
self.isPresentingEditView = false
|
||||
channelName = ""
|
||||
channelRole = 2
|
||||
hasChanges = false
|
||||
_ = bleManager.getChannel(channel: channel, fromUser: node!.user!, toUser: node!.user!)
|
||||
}
|
||||
} label: {
|
||||
Label("save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil || !hasChanges || !hasValidKey)
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding(.bottom)
|
||||
#if targetEnvironment(macCatalyst)
|
||||
Button {
|
||||
isPresentingEditView = false
|
||||
} label: {
|
||||
Label("close", systemImage: "xmark")
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding(.bottom)
|
||||
#endif
|
||||
}
|
||||
.presentationDetents([.medium, .large])
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("channels")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue