Merge pull request #259 from meshtastic/2.0.7_Working_Changes

2.0.7 Working Changes
This commit is contained in:
Garth Vander Houwen 2022-12-09 19:16:22 -08:00 committed by GitHub
commit 7cab56f8da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 150 additions and 102 deletions

View file

@ -979,7 +979,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 2.0.6;
MARKETING_VERSION = 2.0.7;
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_MACCATALYST = YES;
@ -1012,7 +1012,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 2.0.6;
MARKETING_VERSION = 2.0.7;
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_MACCATALYST = YES;

View file

@ -198,6 +198,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject {
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
self.connectedPeripheral = nil
self.isConnecting = false
self.isConnected = false
self.isSubscribed = false
if let e = error {
// https://developer.apple.com/documentation/corebluetooth/cberror/code
@ -501,11 +502,12 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject {
MeshLogger.log(" MESH PACKET received for Simulator App UNHANDLED \(try! decodedInfo.packet.jsonString())")
case .audioApp:
MeshLogger.log(" MESH PACKET received for Audio App UNHANDLED \(try! decodedInfo.packet.jsonString())")
case .tracerouteApp:
MeshLogger.log(" MESH PACKET received for Trace Route App UNHANDLED \(try! decodedInfo.packet.jsonString())")
case .UNRECOGNIZED(_):
MeshLogger.log(" MESH PACKET received for Other App UNHANDLED \(try! decodedInfo.packet.jsonString())")
case .max:
print("MAX PORT NUM OF 511")
}
// MARK: Check for an All / Broadcast User and delete it as a transition to multi channel

View file

@ -815,6 +815,12 @@ struct Config {
/// NUM_CHANNELS (Where num channels depends on the regulatory region).
var channelNum: UInt32 = 0
///
/// If true, duty cycle limits will be exceeded and thus you're possibly not following
/// the local regulations if you're not a HAM.
/// Has no effect if the duty cycle of the used region is 100%.
var overrideDutyCycle: Bool = false
///
/// For testing it is useful sometimes to force a node to never listen to
/// particular other nodes (simulating radio out of range). All nodenums listed
@ -1830,6 +1836,7 @@ extension Config.LoRaConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
9: .standard(proto: "tx_enabled"),
10: .standard(proto: "tx_power"),
11: .standard(proto: "channel_num"),
12: .standard(proto: "override_duty_cycle"),
103: .standard(proto: "ignore_incoming"),
]
@ -1850,6 +1857,7 @@ extension Config.LoRaConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
case 9: try { try decoder.decodeSingularBoolField(value: &self.txEnabled) }()
case 10: try { try decoder.decodeSingularInt32Field(value: &self.txPower) }()
case 11: try { try decoder.decodeSingularUInt32Field(value: &self.channelNum) }()
case 12: try { try decoder.decodeSingularBoolField(value: &self.overrideDutyCycle) }()
case 103: try { try decoder.decodeRepeatedUInt32Field(value: &self.ignoreIncoming) }()
default: break
}
@ -1890,6 +1898,9 @@ extension Config.LoRaConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
if self.channelNum != 0 {
try visitor.visitSingularUInt32Field(value: self.channelNum, fieldNumber: 11)
}
if self.overrideDutyCycle != false {
try visitor.visitSingularBoolField(value: self.overrideDutyCycle, fieldNumber: 12)
}
if !self.ignoreIncoming.isEmpty {
try visitor.visitPackedUInt32Field(value: self.ignoreIncoming, fieldNumber: 103)
}
@ -1908,6 +1919,7 @@ extension Config.LoRaConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
if lhs.txEnabled != rhs.txEnabled {return false}
if lhs.txPower != rhs.txPower {return false}
if lhs.channelNum != rhs.channelNum {return false}
if lhs.overrideDutyCycle != rhs.overrideDutyCycle {return false}
if lhs.ignoreIncoming != rhs.ignoreIncoming {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true

View file

@ -968,6 +968,10 @@ struct Routing {
/// (possibly due to bad channel permissions)
case noResponse // = 8
///
/// Cannot send currently because duty cycle regulations will be violated.
case dutyCycleLimit // = 9
///
/// The application layer service on the remote node received your request, but considered your request somehow invalid
case badRequest // = 32
@ -993,6 +997,7 @@ struct Routing {
case 6: self = .noChannel
case 7: self = .tooLarge
case 8: self = .noResponse
case 9: self = .dutyCycleLimit
case 32: self = .badRequest
case 33: self = .notAuthorized
default: self = .UNRECOGNIZED(rawValue)
@ -1010,6 +1015,7 @@ struct Routing {
case .noChannel: return 6
case .tooLarge: return 7
case .noResponse: return 8
case .dutyCycleLimit: return 9
case .badRequest: return 32
case .notAuthorized: return 33
case .UNRECOGNIZED(let i): return i
@ -1035,6 +1041,7 @@ extension Routing.Error: CaseIterable {
.noChannel,
.tooLarge,
.noResponse,
.dutyCycleLimit,
.badRequest,
.notAuthorized,
]
@ -2627,6 +2634,7 @@ extension Routing.Error: SwiftProtobuf._ProtoNameProviding {
6: .same(proto: "NO_CHANNEL"),
7: .same(proto: "TOO_LARGE"),
8: .same(proto: "NO_RESPONSE"),
9: .same(proto: "DUTY_CYCLE_LIMIT"),
32: .same(proto: "BAD_REQUEST"),
33: .same(proto: "NOT_AUTHORIZED"),
]

View file

@ -241,14 +241,6 @@ struct ModuleConfig {
/// Whether Audio is enabled
var codec2Enabled: Bool = false
///
/// ADC where Microphone is connected
var micChan: UInt32 = 0
///
/// DAC where Speaker is connected
var ampPin: UInt32 = 0
///
/// PTT Pin
var pttPin: UInt32 = 0
@ -257,6 +249,22 @@ struct ModuleConfig {
/// The audio sample rate to use for codec2
var bitrate: ModuleConfig.AudioConfig.Audio_Baud = .codec2Default
///
/// I2S Word Select
var i2SWs: UInt32 = 0
///
/// I2S Data IN
var i2SSd: UInt32 = 0
///
/// I2S Data OUT
var i2SDin: UInt32 = 0
///
/// I2S Clock
var i2SSck: UInt32 = 0
var unknownFields = SwiftProtobuf.UnknownStorage()
///
@ -1057,10 +1065,12 @@ extension ModuleConfig.AudioConfig: SwiftProtobuf.Message, SwiftProtobuf._Messag
static let protoMessageName: String = ModuleConfig.protoMessageName + ".AudioConfig"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "codec2_enabled"),
2: .standard(proto: "mic_chan"),
3: .standard(proto: "amp_pin"),
4: .standard(proto: "ptt_pin"),
5: .same(proto: "bitrate"),
2: .standard(proto: "ptt_pin"),
3: .same(proto: "bitrate"),
4: .standard(proto: "i2s_ws"),
5: .standard(proto: "i2s_sd"),
6: .standard(proto: "i2s_din"),
7: .standard(proto: "i2s_sck"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1070,10 +1080,12 @@ extension ModuleConfig.AudioConfig: SwiftProtobuf.Message, SwiftProtobuf._Messag
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularBoolField(value: &self.codec2Enabled) }()
case 2: try { try decoder.decodeSingularUInt32Field(value: &self.micChan) }()
case 3: try { try decoder.decodeSingularUInt32Field(value: &self.ampPin) }()
case 4: try { try decoder.decodeSingularUInt32Field(value: &self.pttPin) }()
case 5: try { try decoder.decodeSingularEnumField(value: &self.bitrate) }()
case 2: try { try decoder.decodeSingularUInt32Field(value: &self.pttPin) }()
case 3: try { try decoder.decodeSingularEnumField(value: &self.bitrate) }()
case 4: try { try decoder.decodeSingularUInt32Field(value: &self.i2SWs) }()
case 5: try { try decoder.decodeSingularUInt32Field(value: &self.i2SSd) }()
case 6: try { try decoder.decodeSingularUInt32Field(value: &self.i2SDin) }()
case 7: try { try decoder.decodeSingularUInt32Field(value: &self.i2SSck) }()
default: break
}
}
@ -1083,27 +1095,35 @@ extension ModuleConfig.AudioConfig: SwiftProtobuf.Message, SwiftProtobuf._Messag
if self.codec2Enabled != false {
try visitor.visitSingularBoolField(value: self.codec2Enabled, fieldNumber: 1)
}
if self.micChan != 0 {
try visitor.visitSingularUInt32Field(value: self.micChan, fieldNumber: 2)
}
if self.ampPin != 0 {
try visitor.visitSingularUInt32Field(value: self.ampPin, fieldNumber: 3)
}
if self.pttPin != 0 {
try visitor.visitSingularUInt32Field(value: self.pttPin, fieldNumber: 4)
try visitor.visitSingularUInt32Field(value: self.pttPin, fieldNumber: 2)
}
if self.bitrate != .codec2Default {
try visitor.visitSingularEnumField(value: self.bitrate, fieldNumber: 5)
try visitor.visitSingularEnumField(value: self.bitrate, fieldNumber: 3)
}
if self.i2SWs != 0 {
try visitor.visitSingularUInt32Field(value: self.i2SWs, fieldNumber: 4)
}
if self.i2SSd != 0 {
try visitor.visitSingularUInt32Field(value: self.i2SSd, fieldNumber: 5)
}
if self.i2SDin != 0 {
try visitor.visitSingularUInt32Field(value: self.i2SDin, fieldNumber: 6)
}
if self.i2SSck != 0 {
try visitor.visitSingularUInt32Field(value: self.i2SSck, fieldNumber: 7)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: ModuleConfig.AudioConfig, rhs: ModuleConfig.AudioConfig) -> Bool {
if lhs.codec2Enabled != rhs.codec2Enabled {return false}
if lhs.micChan != rhs.micChan {return false}
if lhs.ampPin != rhs.ampPin {return false}
if lhs.pttPin != rhs.pttPin {return false}
if lhs.bitrate != rhs.bitrate {return false}
if lhs.i2SWs != rhs.i2SWs {return false}
if lhs.i2SSd != rhs.i2SSd {return false}
if lhs.i2SDin != rhs.i2SDin {return false}
if lhs.i2SSck != rhs.i2SSck {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}

View file

@ -130,6 +130,11 @@ enum PortNum: SwiftProtobuf.Enum {
/// Project files at https://github.com/GUVWAF/Meshtasticator
case simulatorApp // = 69
///
/// Provides a traceroute functionality to show the route a packet towards
/// a certain destination would take on the mesh.
case tracerouteApp // = 70
///
/// Private applications should use portnums >= 256.
/// To simplify initial development and testing you can use "PRIVATE_APP"
@ -169,6 +174,7 @@ enum PortNum: SwiftProtobuf.Enum {
case 67: self = .telemetryApp
case 68: self = .zpsApp
case 69: self = .simulatorApp
case 70: self = .tracerouteApp
case 256: self = .privateApp
case 257: self = .atakForwarder
case 511: self = .max
@ -196,6 +202,7 @@ enum PortNum: SwiftProtobuf.Enum {
case .telemetryApp: return 67
case .zpsApp: return 68
case .simulatorApp: return 69
case .tracerouteApp: return 70
case .privateApp: return 256
case .atakForwarder: return 257
case .max: return 511
@ -228,6 +235,7 @@ extension PortNum: CaseIterable {
.telemetryApp,
.zpsApp,
.simulatorApp,
.tracerouteApp,
.privateApp,
.atakForwarder,
.max,
@ -262,6 +270,7 @@ extension PortNum: SwiftProtobuf._ProtoNameProviding {
67: .same(proto: "TELEMETRY_APP"),
68: .same(proto: "ZPS_APP"),
69: .same(proto: "SIMULATOR_APP"),
70: .same(proto: "TRACEROUTE_APP"),
256: .same(proto: "PRIVATE_APP"),
257: .same(proto: "ATAK_FORWARDER"),
511: .same(proto: "MAX"),

View file

@ -46,7 +46,15 @@ struct Contacts: View {
.padding(.trailing, 5)
VStack {
HStack {
Text(String(channel.name ?? "Channel \(channel.index)").camelCaseToWords()).font(.headline)
if channel.name?.isEmpty ?? false {
if channel.role == 1 {
Text(String("PrimaryChannel").camelCaseToWords()).font(.headline)
} else {
Text(String("Channel \(channel.index)").camelCaseToWords()).font(.headline)
}
} else {
Text(String(channel.name ?? "Channel \(channel.index)").camelCaseToWords()).font(.headline)
}
Spacer()
if channel.allPrivateMessages.count > 0 {
VStack (alignment: .trailing) {

View file

@ -34,7 +34,7 @@ struct AboutMeshtastic: View {
Link("GitHub Repository", destination: URL(string: "https://github.com/meshtastic/Meshtastic-Apple")!)
.font(.title2)
}
if locale.region?.identifier == "US" {
if locale.region?.identifier ?? "no locale" == "US" {
Section(header: Text("Get Devices")) {
Link("Buy Complete Radios", destination: URL(string: "https://www.etsy.com/shop/GarthVH")!)
.font(.title2)

View file

@ -11,6 +11,7 @@ struct BluetoothConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@ -19,6 +20,8 @@ struct BluetoothConfig: View {
@State var enabled = true
@State var mode = 0
@State var fixedPin = "123456"
@State var shortPin = false
var pinLength: Int = 6
let numberFormatter: NumberFormatter = {
@ -57,77 +60,66 @@ struct BluetoothConfig: View {
TextField("Fixed PIN", text: $fixedPin)
.foregroundColor(.gray)
.onChange(of: fixedPin, perform: { value in
let digitCount = fixedPin.utf8.count
// Only mess with the value if it is too big
if digitCount > 6 || digitCount < 6 {
fixedPin = "123456"
}
if digitCount < 6 {
fixedPin = "123456"
//Require that pin is no more than 6 numbers and no less than 6 numbers
if fixedPin.utf8.count == pinLength {
shortPin = false
} else if fixedPin.utf8.count > pinLength {
shortPin = false
fixedPin = String(fixedPin.prefix(pinLength))
} else if fixedPin.utf8.count < pinLength {
shortPin = true
}
})
.foregroundColor(.gray)
}
.keyboardType(.decimalPad)
if shortPin {
Text("BLE Pin must be 6 digits long.")
.font(.callout)
.foregroundColor(.red)
}
}
}
}
.disabled(bleManager.connectedPeripheral == nil)
Button {
isPresentingSaveConfirm = true
} label: {
Label("Save", systemImage: "square.and.arrow.down")
}
.disabled(bleManager.connectedPeripheral == nil || !hasChanges)
.disabled(bleManager.connectedPeripheral == nil || !hasChanges || shortPin)
.buttonStyle(.bordered)
.buttonBorderShape(.capsule)
.controlSize(.large)
.padding()
.confirmationDialog(
"Are you sure you want to save?",
isPresented: $isPresentingSaveConfirm,
titleVisibility: .visible
) {
Button("Save Config for \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")") {
var bc = Config.BluetoothConfig()
bc.enabled = enabled
bc.mode = BluetoothModes(rawValue: mode)?.protoEnumValue() ?? Config.BluetoothConfig.PairingMode.randomPin
bc.fixedPin = UInt32(fixedPin) ?? 123456
let adminMessageId = bleManager.saveBluetoothConfig(config: bc, fromUser: node!.user!, toUser: node!.user!)
if adminMessageId > 0 {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
hasChanges = false
} else {
goBack()
}
}
} message: {
Text("After bluetooth config saves the node will reboot.")
}
}
.navigationTitle("Bluetooth (BLE) Config")
.navigationBarItems(trailing:
ZStack {
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
})
.onAppear {
self.bleManager.context = context

View file

@ -10,6 +10,7 @@ struct DeviceConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@ -165,15 +166,11 @@ struct DeviceConfig: View {
dc.buzzerGpio = UInt32(buzzerGPIO)
let adminMessageId = bleManager.saveDeviceConfig(config: dc, fromUser: node!.user!, toUser: node!.user!)
if adminMessageId > 0 {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
hasChanges = false
} else {
goBack()
}
}
}

View file

@ -11,6 +11,7 @@ struct DisplayConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@ -115,9 +116,7 @@ struct DisplayConfig: View {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
hasChanges = false
} else {
goBack()
}
}
}

View file

@ -11,6 +11,7 @@ struct LoRaConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@ -83,16 +84,12 @@ struct LoRaConfig: View {
lc.txEnabled = true
let adminMessageId = bleManager.saveLoRaConfig(config: lc, fromUser: node!.user!, toUser: node!.user!)
if adminMessageId > 0 {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
hasChanges = false
} else {
goBack()
}
}
} message: {
Text("After LoRa config saves the node will reboot.")
}

View file

@ -10,6 +10,7 @@ struct CannedMessagesConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@ -251,6 +252,7 @@ struct CannedMessagesConfig: View {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
hasChanges = false
goBack()
}
}
if hasMessagesChanges {

View file

@ -50,6 +50,7 @@ struct ExternalNotificationConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@ -148,8 +149,7 @@ struct ExternalNotificationConfig: View {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
hasChanges = false
} else {
goBack()
}
}
}

View file

@ -10,6 +10,7 @@ struct MQTTConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@State private var isPresentingSaveConfirm: Bool = false
@State var hasChanges: Bool = false
@ -103,8 +104,6 @@ struct MQTTConfig: View {
}
.keyboardType(.default)
.scrollDismissesKeyboard(.interactively)
HStack {
Label("Password", systemImage: "wallet.pass")
TextField("Server Password", text: $password)
@ -153,13 +152,11 @@ struct MQTTConfig: View {
.controlSize(.large)
.padding()
.confirmationDialog(
"Are you sure?",
isPresented: $isPresentingSaveConfirm,
titleVisibility: .visible
) {
Button("Save MQTT Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") {
var mqtt = ModuleConfig.MQTTConfig()
mqtt.enabled = self.enabled
mqtt.address = self.address
@ -167,17 +164,12 @@ struct MQTTConfig: View {
mqtt.password = self.password
mqtt.encryptionEnabled = self.encryptionEnabled
mqtt.jsonEnabled = self.jsonEnabled
let adminMessageId = bleManager.saveMQTTConfig(config: mqtt, fromUser: node!.user!, toUser: node!.user!)
if adminMessageId > 0 {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
self.hasChanges = false
} else {
hasChanges = false
goBack()
}
}
}

View file

@ -48,6 +48,7 @@ struct RangeTestConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@ -89,7 +90,7 @@ struct RangeTestConfig: View {
} label: {
Label("Save", systemImage: "square.and.arrow.down")
}
.disabled(bleManager.connectedPeripheral == nil || !hasChanges || !(node!.myInfo?.hasWifi ?? false))
.disabled(bleManager.connectedPeripheral == nil || !hasChanges || !(node?.myInfo?.hasWifi ?? false))
.buttonStyle(.bordered)
.buttonBorderShape(.capsule)
.controlSize(.large)
@ -109,8 +110,7 @@ struct RangeTestConfig: View {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
hasChanges = false
} else {
goBack()
}
}
}

View file

@ -10,6 +10,7 @@ struct SerialConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@ -142,9 +143,7 @@ struct SerialConfig: View {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
hasChanges = false
} else {
goBack()
}
}
}

View file

@ -70,6 +70,7 @@ struct TelemetryConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@ -148,8 +149,7 @@ struct TelemetryConfig: View {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
hasChanges = false
} else {
goBack()
}
}
}

View file

@ -11,6 +11,7 @@ struct NetworkConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@ -119,10 +120,8 @@ struct NetworkConfig: View {
if adminMessageId > 0 {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
self.hasChanges = false
} else {
hasChanges = false
goBack()
}
}
} message: {

View file

@ -27,6 +27,7 @@ struct PositionConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@ -234,6 +235,7 @@ struct PositionConfig: View {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
hasChanges = false
goBack()
}
}
}

View file

@ -33,6 +33,7 @@ struct ShareChannels: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var dismiss
@State var channelSet: ChannelSet = ChannelSet()
@State var includeChannel0 = true
@State var includeChannel1 = true
@ -48,8 +49,6 @@ struct ShareChannels: View {
var qrCodeImage = QrCodeImage()
var body: some View {
// VStack {
GeometryReader { bounds in
let smallest = min(bounds.size.width, bounds.size.height)
ScrollView {
@ -218,8 +217,6 @@ struct ShareChannels: View {
}
}
}
//}
}
.sheet(isPresented: $isPresentingHelp) {
VStack {
@ -244,6 +241,18 @@ struct ShareChannels: View {
.padding()
.presentationDetents([.large])
.presentationDragIndicator(.automatic)
#if targetEnvironment(macCatalyst)
Button {
dismiss()
} label: {
Label("Close", systemImage: "xmark")
}
.buttonStyle(.bordered)
.buttonBorderShape(.capsule)
.controlSize(.large)
.padding()
#endif
}
.navigationTitle("Generate QR Code")
.navigationBarTitleDisplayMode(.inline)
@ -263,7 +272,6 @@ struct ShareChannels: View {
.onChange(of: includeChannel6) { includeCh6 in GenerateChannelSet() }
.onChange(of: includeChannel7) { includeCh7 in GenerateChannelSet() }
}
// }
}
func GenerateChannelSet() {
channelSet = ChannelSet()

View file

@ -10,6 +10,7 @@ struct UserConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@ -90,6 +91,7 @@ struct UserConfig: View {
let adminMessageId = bleManager.saveUser(config: u, fromUser: node!.user!, toUser: node!.user!)
if adminMessageId > 0 {
hasChanges = false
goBack()
}
}
} message: {