mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Merge branch meshtastic:main into main
This commit is contained in:
commit
4e7f5d5d83
9 changed files with 145 additions and 39 deletions
|
|
@ -2160,6 +2160,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"A yellow open lock lock means the channel is not securely encrypted but it not used for precise location data, it uses either no key at all or a 1 byte known key." : {
|
||||
|
||||
},
|
||||
"About" : {
|
||||
"localizations" : {
|
||||
|
|
@ -33512,6 +33515,7 @@
|
|||
}
|
||||
},
|
||||
"Shows information for the Lora radio connected via bluetooth. You can swipe left to disconnect the radio and long press start the live activity." : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"it" : {
|
||||
"stringUnit" : {
|
||||
|
|
@ -33532,6 +33536,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Shows information for the Lora radio connected via bluetooth. You can swipe left to disconnect the radio and long press to start the live activity." : {
|
||||
|
||||
},
|
||||
"Shut Down" : {
|
||||
"localizations" : {
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@
|
|||
DD1BEF4C2E030D310090CE24 /* KeyBackupStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1BEF4B2E030D240090CE24 /* KeyBackupStatus.swift */; };
|
||||
DD1BEF4E2E03916A0090CE24 /* ChannelsHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1BEF4D2E0391620090CE24 /* ChannelsHelp.swift */; };
|
||||
DD1BEF502E0528AA0090CE24 /* PersistantTips.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1BEF4F2E0528A80090CE24 /* PersistantTips.swift */; };
|
||||
DD1BEF522E08E9B80090CE24 /* ChannelLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1BEF512E08E9AE0090CE24 /* ChannelLock.swift */; };
|
||||
DD1BF2F92776FE2E008C8D2F /* UserMessageList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1BF2F82776FE2E008C8D2F /* UserMessageList.swift */; };
|
||||
DD2160AF28C5552500C17253 /* MQTTConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD2160AE28C5552500C17253 /* MQTTConfig.swift */; };
|
||||
DD23A50F26FD1B4400D9B90C /* PeripheralModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */; };
|
||||
|
|
@ -380,6 +381,7 @@
|
|||
DD1BEF4B2E030D240090CE24 /* KeyBackupStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupStatus.swift; sourceTree = "<group>"; };
|
||||
DD1BEF4D2E0391620090CE24 /* ChannelsHelp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelsHelp.swift; sourceTree = "<group>"; };
|
||||
DD1BEF4F2E0528A80090CE24 /* PersistantTips.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistantTips.swift; sourceTree = "<group>"; };
|
||||
DD1BEF512E08E9AE0090CE24 /* ChannelLock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelLock.swift; sourceTree = "<group>"; };
|
||||
DD1BF2F82776FE2E008C8D2F /* UserMessageList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserMessageList.swift; sourceTree = "<group>"; };
|
||||
DD2160AE28C5552500C17253 /* MQTTConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MQTTConfig.swift; sourceTree = "<group>"; };
|
||||
DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeripheralModel.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -1057,6 +1059,7 @@
|
|||
DD3CC6BD28E4CD9800FA9159 /* BatteryGauge.swift */,
|
||||
DD3CC24B2C498D6C001BD3A2 /* BatteryCompact.swift */,
|
||||
DD457187293C7E63000C49FB /* BLESignalStrengthIndicator.swift */,
|
||||
DD1BEF512E08E9AE0090CE24 /* ChannelLock.swift */,
|
||||
DD47E3D526F17ED900029299 /* CircleText.swift */,
|
||||
DDF924C926FBB953009FE055 /* ConnectedDevice.swift */,
|
||||
DDD94A4F2845C8F5004A87A0 /* DateTimeText.swift */,
|
||||
|
|
@ -1385,6 +1388,7 @@
|
|||
25F26B1E2C2F610D00C9CD9D /* Logger.swift in Sources */,
|
||||
259792252C2F114500AD1659 /* ChannelEntityExtension.swift in Sources */,
|
||||
BCE2D3C52C7AE369008E6199 /* RestartNodeIntent.swift in Sources */,
|
||||
DD1BEF522E08E9B80090CE24 /* ChannelLock.swift in Sources */,
|
||||
259792262C2F114500AD1659 /* PositionEntityExtension.swift in Sources */,
|
||||
259792272C2F114500AD1659 /* TraceRouteEntityExtension.swift in Sources */,
|
||||
DDDB444829F8A9C900EE2349 /* String.swift in Sources */,
|
||||
|
|
@ -1825,7 +1829,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.8;
|
||||
MARKETING_VERSION = 2.6.9;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
@ -1858,7 +1862,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.8;
|
||||
MARKETING_VERSION = 2.6.9;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
@ -1889,7 +1893,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.8;
|
||||
MARKETING_VERSION = 2.6.9;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
|
@ -1921,7 +1925,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.8;
|
||||
MARKETING_VERSION = 2.6.9;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
|
|
|||
|
|
@ -725,7 +725,6 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
let message = CocoaMQTTMessage(topic: decodedInfo.mqttClientProxyMessage.topic, payload: [UInt8](decodedInfo.mqttClientProxyMessage.data), retained: decodedInfo.mqttClientProxyMessage.retained)
|
||||
mqttManager.mqttClientProxy?.publish(message)
|
||||
} else if decodedInfo.payloadVariant == FromRadio.OneOf_PayloadVariant.clientNotification(decodedInfo.clientNotification) {
|
||||
|
||||
var path = "meshtastic:///settings/debugLogs"
|
||||
if decodedInfo.clientNotification.hasReplyID {
|
||||
/// Set Sent bool on TraceRouteEntity to false if we got rate limited
|
||||
|
|
@ -740,8 +739,9 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
let nsError = error as NSError
|
||||
Logger.data.error("💥 [TraceRouteEntity] Error Updating Core Data: \(nsError, privacy: .public)")
|
||||
}
|
||||
} else if decodedInfo.clientNotification.message.starts(with: "You Device is configured with a low entropy") || decodedInfo.clientNotification.message.starts(with: "Compromised keys detected")
|
||||
|| decodedInfo.clientNotification.message.starts(with: "Remote device"){
|
||||
}
|
||||
if decodedInfo.clientNotification.payloadVariant == ClientNotification.OneOf_PayloadVariant.lowEntropyKey(decodedInfo.clientNotification.lowEntropyKey) ||
|
||||
decodedInfo.clientNotification.payloadVariant == ClientNotification.OneOf_PayloadVariant.duplicatedPublicKey(decodedInfo.clientNotification.duplicatedPublicKey) {
|
||||
path = "meshtastic:///settings/security"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
35
Meshtastic/Views/Helpers/ChannelLock.swift
Normal file
35
Meshtastic/Views/Helpers/ChannelLock.swift
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// ChannelLock.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright(c) Garth Vander Houwen 6/22/25.
|
||||
//
|
||||
import SwiftUI
|
||||
|
||||
struct ChannelLock: View {
|
||||
|
||||
@ObservedObject var channel: ChannelEntity
|
||||
|
||||
var body: some View {
|
||||
/// Unencrypted - using no key at all or a known 1 byte key
|
||||
if channel.psk?.hexDescription.count ?? 0 < 3 {
|
||||
let preciseLoction = 17...32
|
||||
// Using precise location and have MQTT uplink enabled
|
||||
if channel.uplinkEnabled && preciseLoction ~= (Int(channel.positionPrecision)) {
|
||||
Image(systemName: "lock.open.trianglebadge.exclamationmark.fill")
|
||||
.foregroundColor(.red)
|
||||
// Using precise location
|
||||
} else if preciseLoction ~= (Int(channel.positionPrecision)) {
|
||||
Image(systemName: "lock.open.fill")
|
||||
.foregroundColor(.red)
|
||||
// Just unencrypted without any location or MQTT
|
||||
} else {
|
||||
Image(systemName: "lock.open.fill")
|
||||
.foregroundColor(.yellow)
|
||||
}
|
||||
} else {
|
||||
Image(systemName: "lock.fill")
|
||||
.foregroundColor(.green)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,25 +21,46 @@ struct ChannelsHelp: View {
|
|||
CircleText(text: String(0), color: .accentColor)
|
||||
.brightness(0.2)
|
||||
.offset(y: -10)
|
||||
Text("A channel index of 0 indicates the primary channel where all broadcast packets are sent from.")
|
||||
Text("A channel index of 0 indicates the primary channel where broadcast packets are sent from. Location data is broadcast from the first channel where it is enabled with firmware 2.7 forward.")
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding(.bottom)
|
||||
.padding(.leading, 7)
|
||||
}
|
||||
HStack {
|
||||
Image(systemName: "lock.fill")
|
||||
.padding(.bottom)
|
||||
.padding(.leading)
|
||||
.padding(.trailing, 7)
|
||||
.foregroundColor(Color.green)
|
||||
.font(.largeTitle)
|
||||
.font(.title)
|
||||
Text("A green lock means the channel is securely encrypted with either a 128 or 256 bit AES key.")
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding(.bottom)
|
||||
}
|
||||
HStack {
|
||||
Image(systemName: "lock.slash.fill")
|
||||
Image(systemName: "lock.open.fill")
|
||||
.padding(.leading)
|
||||
.foregroundColor(Color.yellow)
|
||||
.font(.title)
|
||||
Text("A yellow open lock lock means the channel is not securely encrypted but it not used for precise location data, it uses either no key at all or a 1 byte known key.")
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding(.bottom)
|
||||
}
|
||||
HStack {
|
||||
Image(systemName: "lock.open.fill")
|
||||
.padding(.leading)
|
||||
.foregroundColor(Color.red)
|
||||
.font(.largeTitle)
|
||||
Text("A red lock with a slash means the channel is not securely encrypted, it uses either no key at all or a 1 byte known key. Traffic on this channel is easily intercepted.")
|
||||
.font(.title)
|
||||
Text("A red open lock means the channel is not securely encrypted and is used for precise location data, it uses either no key at all or a 1 byte known key.")
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding(.bottom)
|
||||
}
|
||||
HStack {
|
||||
Image(systemName: "lock.open.trianglebadge.exclamationmark.fill")
|
||||
.padding(.leading)
|
||||
.symbolRenderingMode(.multicolor)
|
||||
.foregroundColor(Color.red)
|
||||
.font(.title)
|
||||
Text("A red open lock with a warning means the channel is not securely encrypted and is used for precise location data which is being uplinked to the internet via MQTT, it uses either no key at all or a 1 byte known key.")
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding(.bottom)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,13 +58,7 @@ struct ChannelList: View {
|
|||
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
if channel.psk?.hexDescription.count ?? 0 < 3 {
|
||||
Image(systemName: "lock.slash.fill")
|
||||
.foregroundColor(.red)
|
||||
} else {
|
||||
Image(systemName: "lock.fill")
|
||||
.foregroundColor(.green)
|
||||
}
|
||||
ChannelLock(channel: channel)
|
||||
if channel.name?.isEmpty ?? false {
|
||||
if channel.role == 1 {
|
||||
Text(String("PrimaryChannel").camelCaseToWords())
|
||||
|
|
@ -173,7 +167,7 @@ struct ChannelList: View {
|
|||
}
|
||||
.sheet(isPresented: $showingHelp) {
|
||||
ChannelsHelp()
|
||||
.presentationDetents([.medium, .large])
|
||||
.presentationDetents([.large])
|
||||
.presentationDragIndicator(.visible)
|
||||
}
|
||||
.safeAreaInset(edge: .bottom, alignment: .leading) {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ struct Channels: View {
|
|||
|
||||
/// Minimum Version for granular position configuration
|
||||
@State var minimumVersion = "2.2.24"
|
||||
@State private var showingHelp = false
|
||||
|
||||
@FetchRequest(
|
||||
sortDescriptors: [NSSortDescriptor(key: "favorite", ascending: false),
|
||||
|
|
@ -124,13 +125,7 @@ struct Channels: View {
|
|||
.brightness(0.1)
|
||||
VStack {
|
||||
HStack {
|
||||
if channel.psk?.hexDescription.count ?? 0 < 3 {
|
||||
Image(systemName: "lock.slash.fill")
|
||||
.foregroundColor(.red)
|
||||
} else {
|
||||
Image(systemName: "lock.fill")
|
||||
.foregroundColor(.green)
|
||||
}
|
||||
ChannelLock(channel: channel)
|
||||
if channel.name?.isEmpty ?? false {
|
||||
if channel.role == 1 {
|
||||
Text(String("PrimaryChannel").camelCaseToWords()).font(.headline)
|
||||
|
|
@ -246,6 +241,7 @@ struct Channels: View {
|
|||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if node?.myInfo?.channels?.array.count ?? 0 < 8 && node != nil {
|
||||
|
||||
Button {
|
||||
|
|
@ -286,6 +282,29 @@ struct Channels: View {
|
|||
.padding()
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showingHelp) {
|
||||
ChannelsHelp()
|
||||
.presentationDetents([.large])
|
||||
.presentationDragIndicator(.visible)
|
||||
}
|
||||
.safeAreaInset(edge: .bottom, alignment: .leading) {
|
||||
HStack {
|
||||
Button(action: {
|
||||
withAnimation {
|
||||
showingHelp = !showingHelp
|
||||
}
|
||||
}) {
|
||||
Image(systemName: !showingHelp ? "questionmark.circle" : "questionmark.circle.fill")
|
||||
.padding(.vertical, 5)
|
||||
}
|
||||
.tint(Color(UIColor.secondarySystemBackground))
|
||||
.foregroundColor(.accentColor)
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
.controlSize(.regular)
|
||||
.padding(5)
|
||||
}
|
||||
.padding(.bottom, 5)
|
||||
.navigationTitle("Channels")
|
||||
.navigationBarItems(trailing:
|
||||
ZStack {
|
||||
|
|
|
|||
|
|
@ -349,6 +349,14 @@ struct SecurityConfig: View {
|
|||
}
|
||||
}
|
||||
hasChanges = false
|
||||
if keyUpdated {
|
||||
if !bleManager.sendReboot(
|
||||
fromUser: fromUser,
|
||||
toUser: toUser
|
||||
) {
|
||||
Logger.mesh.warning("Reboot Failed")
|
||||
}
|
||||
}
|
||||
goBack()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ struct ShareChannels: View {
|
|||
var node: NodeInfoEntity?
|
||||
@State private var channelsUrl = "https://www.meshtastic.org/e/#"
|
||||
var qrCodeImage = QrCodeImage()
|
||||
@State private var showingHelp = false
|
||||
|
||||
var body: some View {
|
||||
|
||||
|
|
@ -82,13 +83,7 @@ struct ShareChannels: View {
|
|||
.toggleStyle(.switch)
|
||||
.labelsHidden()
|
||||
Text(((channel.name!.isEmpty ? "Primary" : channel.name) ?? "Primary").camelCaseToWords())
|
||||
if channel.psk?.hexDescription.count ?? 0 < 3 {
|
||||
Image(systemName: "lock.slash.fill")
|
||||
.foregroundColor(.red)
|
||||
} else {
|
||||
Image(systemName: "lock.fill")
|
||||
.foregroundColor(.green)
|
||||
}
|
||||
ChannelLock(channel: channel)
|
||||
} else if channel.index == 1 && channel.role > 0 {
|
||||
Toggle("Channel 1 Included", isOn: $includeChannel1)
|
||||
.toggleStyle(.switch)
|
||||
|
|
@ -216,16 +211,39 @@ struct ShareChannels: View {
|
|||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(
|
||||
minWidth: smallest * (UIDevice.current.userInterfaceIdiom == .phone ? 0.8 : 0.6),
|
||||
maxWidth: smallest * (UIDevice.current.userInterfaceIdiom == .phone ? 0.8 : 0.6),
|
||||
minHeight: smallest * (UIDevice.current.userInterfaceIdiom == .phone ? 0.8 : 0.6),
|
||||
maxHeight: smallest * (UIDevice.current.userInterfaceIdiom == .phone ? 0.8 : 0.6),
|
||||
minWidth: smallest * (UIDevice.current.userInterfaceIdiom == .phone ? 0.75 : 0.6),
|
||||
maxWidth: smallest * (UIDevice.current.userInterfaceIdiom == .phone ? 0.75 : 0.6),
|
||||
minHeight: smallest * (UIDevice.current.userInterfaceIdiom == .phone ? 0.75 : 0.6),
|
||||
maxHeight: smallest * (UIDevice.current.userInterfaceIdiom == .phone ? 0.75 : 0.6),
|
||||
alignment: .top
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showingHelp) {
|
||||
ChannelsHelp()
|
||||
.presentationDetents([.large])
|
||||
.presentationDragIndicator(.visible)
|
||||
}
|
||||
.safeAreaInset(edge: .bottom, alignment: .leading) {
|
||||
HStack {
|
||||
Button(action: {
|
||||
withAnimation {
|
||||
showingHelp = !showingHelp
|
||||
}
|
||||
}) {
|
||||
Image(systemName: !showingHelp ? "questionmark.circle" : "questionmark.circle.fill")
|
||||
.padding(.vertical, 5)
|
||||
}
|
||||
.tint(Color(UIColor.secondarySystemBackground))
|
||||
.foregroundColor(.accentColor)
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
.controlSize(.regular)
|
||||
.padding(5)
|
||||
}
|
||||
.padding(.bottom, 5)
|
||||
.navigationTitle("Generate QR Code")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.navigationBarItems(trailing:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue