mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Moved some things around
Co-authored-by: garthvh <1795163+garthvh@users.noreply.github.com>
This commit is contained in:
parent
d3d5980cca
commit
3f9348e36f
6 changed files with 318 additions and 242 deletions
|
|
@ -55318,7 +55318,6 @@
|
|||
}
|
||||
},
|
||||
"This node does not support any configurable modules." : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"da" : {
|
||||
"stringUnit" : {
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@
|
|||
8EED425B7820DA4FEB40C375 /* CoTXMLParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 748E4806582595DE80D455CD /* CoTXMLParser.swift */; };
|
||||
9604373EEB96801AA89DF48C /* EXICodec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D0A8ABAEF1E587683970927 /* EXICodec.swift */; };
|
||||
A5339E2F74E83F8FC41EEE33 /* TAKServerConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0618E6D0DF90B74EE32E6C06 /* TAKServerConfig.swift */; };
|
||||
AA0001032F07A4B000600001 /* TAKModuleConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA0001042F07A4B000600001 /* TAKModuleConfig.swift */; };
|
||||
AA0001012E2730EC00600001 /* ConnectViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA00010022E2730EC0060000 /* ConnectViewTests.swift */; };
|
||||
ABA8E6402E2F2A2300E27791 /* AppIconButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABA8E63F2E2F2A2300E27791 /* AppIconButton.swift */; };
|
||||
ABB99DEB2E2EA1C500CFBD05 /* AppIconPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABB99DEA2E2EA1C500CFBD05 /* AppIconPicker.swift */; };
|
||||
|
|
@ -351,6 +352,7 @@
|
|||
01028778B8BFD81F7A039593 /* TAKConnection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TAKConnection.swift; sourceTree = "<group>"; };
|
||||
0618E6D0DF90B74EE32E6C06 /* TAKServerConfig.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TAKServerConfig.swift; sourceTree = "<group>"; };
|
||||
09936BEBD6D82479B2360FDC /* TAKCertificateManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TAKCertificateManager.swift; sourceTree = "<group>"; };
|
||||
AA0001042F07A4B000600001 /* TAKModuleConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TAKModuleConfig.swift; sourceTree = "<group>"; };
|
||||
108FFECA2DD3F43C00BFAA81 /* ShareContactQRDialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareContactQRDialog.swift; sourceTree = "<group>"; };
|
||||
108FFECC2DD4005600BFAA81 /* NodeInfoEntityToNodeInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeInfoEntityToNodeInfo.swift; sourceTree = "<group>"; };
|
||||
1D5AD8037A0D583C614B0597 /* Tools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tools.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -1085,6 +1087,7 @@
|
|||
DD15E4F22B8BA56E00654F61 /* PaxCounterConfig.swift */,
|
||||
DD6193782863875F00E59241 /* SerialConfig.swift */,
|
||||
DDF6B2472A9AEBF500BA6931 /* StoreForwardConfig.swift */,
|
||||
AA0001042F07A4B000600001 /* TAKModuleConfig.swift */,
|
||||
DD415827285859C4009B0E59 /* TelemetryConfig.swift */,
|
||||
);
|
||||
path = Module;
|
||||
|
|
@ -1946,6 +1949,7 @@
|
|||
E3ED80145D0E873011982556 /* TAKServerManager.swift in Sources */,
|
||||
FE508F9AF5AD5DA20AA64DBF /* AccessoryManager+TAK.swift in Sources */,
|
||||
A5339E2F74E83F8FC41EEE33 /* TAKServerConfig.swift in Sources */,
|
||||
AA0001032F07A4B000600001 /* TAKModuleConfig.swift in Sources */,
|
||||
DCC919C6B47C15BB0795456C /* Tools.swift in Sources */,
|
||||
8398407DBA32EE7CFC16A385 /* TAKDataPackageGenerator.swift in Sources */,
|
||||
655AF7816E76D5F310DF87A6 /* FountainCodec.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -1824,7 +1824,9 @@ extension AccessoryManager {
|
|||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.getModuleConfigRequest = AdminMessage.ModuleConfigType.takConfig
|
||||
adminPacket.sessionPasskey = toUser.userNode?.sessionPasskey ?? Data()
|
||||
if fromUser != toUser {
|
||||
adminPacket.sessionPasskey = toUser.userNode?.sessionPasskey ?? Data()
|
||||
}
|
||||
var meshPacket: MeshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(toUser.num)
|
||||
meshPacket.from = UInt32(fromUser.num)
|
||||
|
|
|
|||
264
Meshtastic/Views/Settings/Config/Module/TAKModuleConfig.swift
Normal file
264
Meshtastic/Views/Settings/Config/Module/TAKModuleConfig.swift
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
//
|
||||
// TAKModuleConfig.swift
|
||||
// Meshtastic
|
||||
import SwiftUI
|
||||
import CoreData
|
||||
import OSLog
|
||||
import MeshtasticProtobufs
|
||||
|
||||
struct TAKModuleConfig: View {
|
||||
@Environment(\.managedObjectContext) private var context
|
||||
@EnvironmentObject private var accessoryManager: AccessoryManager
|
||||
@Environment(\.dismiss) private var goBack
|
||||
|
||||
let node: NodeInfoEntity?
|
||||
|
||||
@State private var hasChanges = false
|
||||
@State private var team = Team.unspecifedColor.rawValue
|
||||
@State private var role = MemberRole.unspecifed.rawValue
|
||||
|
||||
private var selectedTeam: Team {
|
||||
Team(rawValue: team) ?? .unspecifedColor
|
||||
}
|
||||
|
||||
private var selectedRole: MemberRole {
|
||||
MemberRole(rawValue: role) ?? .unspecifed
|
||||
}
|
||||
|
||||
private var deviceRole: DeviceRoles? {
|
||||
guard let role = node?.deviceConfig?.role ?? node?.user?.role else { return nil }
|
||||
return DeviceRoles(rawValue: Int(role))
|
||||
}
|
||||
|
||||
private var isConnectedNode: Bool {
|
||||
guard let node else { return false }
|
||||
return node.num == accessoryManager.activeDeviceNum
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
ConfigHeader(title: "TAK", config: \.takConfig, node: node, onAppear: setTAKValues)
|
||||
|
||||
if let deviceRole, deviceRole != .tak && deviceRole != .takTracker {
|
||||
Section {
|
||||
Text("These settings only apply when the device role is TAK or TAK Tracker.")
|
||||
.font(.callout)
|
||||
.foregroundColor(.orange)
|
||||
}
|
||||
}
|
||||
|
||||
Section(header: Text("Identity")) {
|
||||
VStack(alignment: .leading) {
|
||||
Picker("Team", selection: $team) {
|
||||
ForEach(Team.allCases, id: \.rawValue) { teamOption in
|
||||
Text(teamTitle(teamOption)).tag(teamOption.rawValue)
|
||||
}
|
||||
}
|
||||
.pickerStyle(DefaultPickerStyle())
|
||||
Text(teamHelpText(selectedTeam))
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Picker("Role", selection: $role) {
|
||||
ForEach(MemberRole.allCases, id: \.rawValue) { roleOption in
|
||||
Text(roleTitle(roleOption)).tag(roleOption.rawValue)
|
||||
}
|
||||
}
|
||||
.pickerStyle(DefaultPickerStyle())
|
||||
Text(roleHelpText(selectedRole))
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
}
|
||||
}
|
||||
|
||||
Section {
|
||||
Text("These values are included in TAK position reports. Leave either setting at Default to let firmware use Cyan and Team Member.")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
}
|
||||
}
|
||||
.disabled(!accessoryManager.isConnected || (!isConnectedNode && node?.takConfig == nil))
|
||||
.safeAreaInset(edge: .bottom, alignment: .center) {
|
||||
HStack(spacing: 0) {
|
||||
SaveConfigButton(node: node, hasChanges: $hasChanges) {
|
||||
guard let connectedNode = getNodeInfo(id: accessoryManager.activeDeviceNum ?? -1, context: context),
|
||||
let fromUser = connectedNode.user,
|
||||
let toUser = node?.user else {
|
||||
return
|
||||
}
|
||||
|
||||
var config = ModuleConfig.TAKConfig()
|
||||
config.team = selectedTeam
|
||||
config.role = selectedRole
|
||||
|
||||
Task {
|
||||
_ = try await accessoryManager.saveTAKModuleConfig(config: config, fromUser: fromUser, toUser: toUser)
|
||||
Task { @MainActor in
|
||||
hasChanges = false
|
||||
goBack()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("TAK Config")
|
||||
.navigationBarItems(
|
||||
trailing: ZStack {
|
||||
ConnectedDevice(
|
||||
deviceConnected: accessoryManager.isConnected,
|
||||
name: accessoryManager.activeConnection?.device.shortName ?? "?"
|
||||
)
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
// Need to request a TAKModuleConfig from the connected node before allowing changes.
|
||||
if let deviceNum = accessoryManager.activeDeviceNum,
|
||||
let node,
|
||||
node.num == deviceNum,
|
||||
node.takConfig == nil {
|
||||
let connectedNode = getNodeInfo(id: deviceNum, context: context)
|
||||
if let connectedNode {
|
||||
Task {
|
||||
do {
|
||||
Logger.mesh.info("⚙️ Empty TAK module config requesting from connected node")
|
||||
try await accessoryManager.requestTAKModuleConfig(fromUser: connectedNode.user!, toUser: node.user!)
|
||||
} catch {
|
||||
Logger.mesh.error("🚨 TAK module config request failed: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.onFirstAppear {
|
||||
if let deviceNum = accessoryManager.activeDeviceNum, let node {
|
||||
let connectedNode = getNodeInfo(id: deviceNum, context: context)
|
||||
if let connectedNode, node.num != deviceNum {
|
||||
if UserDefaults.enableAdministration {
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.takConfig == nil {
|
||||
Task {
|
||||
do {
|
||||
Logger.mesh.info("⚙️ Empty or expired TAK module config requesting via PKI admin")
|
||||
try await accessoryManager.requestTAKModuleConfig(fromUser: connectedNode.user!, toUser: node.user!)
|
||||
} catch {
|
||||
Logger.mesh.info("🚨 TAK module config request failed: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Logger.mesh.info("☠️ Using insecure legacy admin that is no longer supported, please upgrade your firmware.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: team) { _, newTeam in
|
||||
if newTeam != Int(node?.takConfig?.team ?? Int32(Team.unspecifedColor.rawValue)) {
|
||||
hasChanges = true
|
||||
}
|
||||
}
|
||||
.onChange(of: role) { _, newRole in
|
||||
if newRole != Int(node?.takConfig?.role ?? Int32(MemberRole.unspecifed.rawValue)) {
|
||||
hasChanges = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func setTAKValues() {
|
||||
team = Int(node?.takConfig?.team ?? Int32(Team.unspecifedColor.rawValue))
|
||||
role = Int(node?.takConfig?.role ?? Int32(MemberRole.unspecifed.rawValue))
|
||||
hasChanges = false
|
||||
}
|
||||
|
||||
private func teamTitle(_ team: Team) -> String {
|
||||
switch team {
|
||||
case .unspecifedColor:
|
||||
return "Default (Cyan)"
|
||||
case .white:
|
||||
return "White"
|
||||
case .yellow:
|
||||
return "Yellow"
|
||||
case .orange:
|
||||
return "Orange"
|
||||
case .magenta:
|
||||
return "Magenta"
|
||||
case .red:
|
||||
return "Red"
|
||||
case .maroon:
|
||||
return "Maroon"
|
||||
case .purple:
|
||||
return "Purple"
|
||||
case .darkBlue:
|
||||
return "Dark Blue"
|
||||
case .blue:
|
||||
return "Blue"
|
||||
case .cyan:
|
||||
return "Cyan"
|
||||
case .teal:
|
||||
return "Teal"
|
||||
case .green:
|
||||
return "Green"
|
||||
case .darkGreen:
|
||||
return "Dark Green"
|
||||
case .brown:
|
||||
return "Brown"
|
||||
case .UNRECOGNIZED:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
private func roleTitle(_ role: MemberRole) -> String {
|
||||
switch role {
|
||||
case .unspecifed:
|
||||
return "Default (Team Member)"
|
||||
case .teamMember:
|
||||
return "Team Member"
|
||||
case .teamLead:
|
||||
return "Team Lead"
|
||||
case .hq:
|
||||
return "HQ"
|
||||
case .sniper:
|
||||
return "Sniper"
|
||||
case .medic:
|
||||
return "Medic"
|
||||
case .forwardObserver:
|
||||
return "Forward Observer"
|
||||
case .rto:
|
||||
return "RTO"
|
||||
case .k9:
|
||||
return "K9"
|
||||
case .UNRECOGNIZED:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
private func teamHelpText(_ team: Team) -> String {
|
||||
switch team {
|
||||
case .unspecifedColor:
|
||||
return "Default uses Cyan."
|
||||
case .UNRECOGNIZED:
|
||||
return "Unknown team color."
|
||||
default:
|
||||
return "Shown to TAK clients as the \(teamTitle(team)) team color."
|
||||
}
|
||||
}
|
||||
|
||||
private func roleHelpText(_ role: MemberRole) -> String {
|
||||
switch role {
|
||||
case .unspecifed:
|
||||
return "Default uses Team Member."
|
||||
case .UNRECOGNIZED:
|
||||
return "Unknown TAK role."
|
||||
default:
|
||||
return "Shown to TAK clients as the \(roleTitle(role)) role."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return TAKModuleConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
@ -33,14 +33,48 @@ struct Settings: View {
|
|||
|
||||
// MARK: Helper
|
||||
|
||||
private var moduleConfigurationNode: NodeInfoEntity? {
|
||||
let nodeNum = selectedNode > 0 ? selectedNode : preferredNodeNum
|
||||
return nodes.first(where: { $0.num == nodeNum })
|
||||
}
|
||||
|
||||
private var showsAnyModuleConfiguration: Bool {
|
||||
isAnySupported([
|
||||
.ambientlightingConfig,
|
||||
.cannedmsgConfig,
|
||||
.detectionsensorConfig,
|
||||
.extnotifConfig,
|
||||
.mqttConfig,
|
||||
.rangetestConfig,
|
||||
.paxcounterConfig,
|
||||
.serialConfig,
|
||||
.storeforwardConfig,
|
||||
.telemetryConfig
|
||||
]) || isTAKModuleSupported()
|
||||
}
|
||||
|
||||
private func isModuleSupported(_ module: ExcludedModules) -> Bool {
|
||||
return Int(nodes.first(where: { $0.num == preferredNodeNum })?.metadata?.excludedModules ?? Int32.zero) & module.rawValue == 0
|
||||
return Int(moduleConfigurationNode?.metadata?.excludedModules ?? Int32.zero) & module.rawValue == 0
|
||||
}
|
||||
|
||||
private func isAnySupported(_ modules: [ExcludedModules]) -> Bool {
|
||||
return modules.map(isModuleSupported).contains(true)
|
||||
}
|
||||
|
||||
private func isTAKModuleSupported() -> Bool {
|
||||
guard let node = moduleConfigurationNode else { return false }
|
||||
if node.takConfig != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
guard let roleValue = node.deviceConfig?.role ?? node.user?.role,
|
||||
let deviceRole = DeviceRoles(rawValue: Int(roleValue)) else {
|
||||
return false
|
||||
}
|
||||
|
||||
return deviceRole == .tak || deviceRole == .takTracker
|
||||
}
|
||||
|
||||
// MARK: Views
|
||||
|
||||
var radioConfigurationSection: some View {
|
||||
|
|
@ -276,13 +310,20 @@ struct Settings: View {
|
|||
}
|
||||
}
|
||||
|
||||
NavigationLink(value: SettingsNavigationState.takConfig) {
|
||||
Label {
|
||||
Text("TAK")
|
||||
} icon: {
|
||||
Image(systemName: "shield.checkered")
|
||||
if isTAKModuleSupported() {
|
||||
NavigationLink(value: SettingsNavigationState.takConfig) {
|
||||
Label {
|
||||
Text("TAK")
|
||||
} icon: {
|
||||
Image(systemName: "shield.checkered")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !showsAnyModuleConfiguration {
|
||||
Text("This node does not support any configurable modules.")
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
} header: {
|
||||
Text("Module Configuration")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import SwiftUI
|
|||
import UniformTypeIdentifiers
|
||||
import OSLog
|
||||
import CoreData
|
||||
import MeshtasticProtobufs
|
||||
|
||||
enum CertificateImportType {
|
||||
case p12
|
||||
|
|
@ -564,236 +563,3 @@ struct ZipDocument: FileDocument {
|
|||
FileWrapper(regularFileWithContents: data)
|
||||
}
|
||||
}
|
||||
|
||||
struct TAKModuleConfig: View {
|
||||
@Environment(\.managedObjectContext) private var context
|
||||
@EnvironmentObject private var accessoryManager: AccessoryManager
|
||||
@Environment(\.dismiss) private var goBack
|
||||
|
||||
let node: NodeInfoEntity?
|
||||
|
||||
@State private var hasChanges = false
|
||||
@State private var team = Team.unspecifedColor.rawValue
|
||||
@State private var role = MemberRole.unspecifed.rawValue
|
||||
|
||||
private var selectedTeam: Team {
|
||||
Team(rawValue: team) ?? .unspecifedColor
|
||||
}
|
||||
|
||||
private var selectedRole: MemberRole {
|
||||
MemberRole(rawValue: role) ?? .unspecifed
|
||||
}
|
||||
|
||||
private var deviceRole: DeviceRoles? {
|
||||
guard let role = node?.deviceConfig?.role else { return nil }
|
||||
return DeviceRoles(rawValue: Int(role))
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
ConfigHeader(title: "TAK", config: \.takConfig, node: node, onAppear: setTAKValues)
|
||||
|
||||
if let deviceRole, deviceRole != .tak && deviceRole != .takTracker {
|
||||
Section {
|
||||
Text("These settings only apply when the device role is TAK or TAK Tracker.")
|
||||
.font(.callout)
|
||||
.foregroundColor(.orange)
|
||||
}
|
||||
}
|
||||
|
||||
Section(header: Text("Identity")) {
|
||||
VStack(alignment: .leading) {
|
||||
Picker("Team", selection: $team) {
|
||||
ForEach(Team.allCases, id: \.rawValue) { teamOption in
|
||||
Text(teamTitle(teamOption)).tag(teamOption.rawValue)
|
||||
}
|
||||
}
|
||||
.pickerStyle(DefaultPickerStyle())
|
||||
Text(teamHelpText(selectedTeam))
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Picker("Role", selection: $role) {
|
||||
ForEach(MemberRole.allCases, id: \.rawValue) { roleOption in
|
||||
Text(roleTitle(roleOption)).tag(roleOption.rawValue)
|
||||
}
|
||||
}
|
||||
.pickerStyle(DefaultPickerStyle())
|
||||
Text(roleHelpText(selectedRole))
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
}
|
||||
}
|
||||
|
||||
Section {
|
||||
Text("These values are included in TAK position reports. Leave either setting at Default to let firmware use Cyan and Team Member.")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
}
|
||||
}
|
||||
.disabled(!accessoryManager.isConnected || node?.takConfig == nil)
|
||||
.safeAreaInset(edge: .bottom, alignment: .center) {
|
||||
HStack(spacing: 0) {
|
||||
SaveConfigButton(node: node, hasChanges: $hasChanges) {
|
||||
guard let connectedNode = getNodeInfo(id: accessoryManager.activeDeviceNum ?? -1, context: context),
|
||||
let fromUser = connectedNode.user,
|
||||
let toUser = node?.user else {
|
||||
return
|
||||
}
|
||||
|
||||
var config = ModuleConfig.TAKConfig()
|
||||
config.team = selectedTeam
|
||||
config.role = selectedRole
|
||||
|
||||
Task {
|
||||
_ = try await accessoryManager.saveTAKModuleConfig(config: config, fromUser: fromUser, toUser: toUser)
|
||||
Task { @MainActor in
|
||||
hasChanges = false
|
||||
goBack()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("TAK Config")
|
||||
.navigationBarItems(
|
||||
trailing: ZStack {
|
||||
ConnectedDevice(
|
||||
deviceConnected: accessoryManager.isConnected,
|
||||
name: accessoryManager.activeConnection?.device.shortName ?? "?"
|
||||
)
|
||||
}
|
||||
)
|
||||
.onFirstAppear {
|
||||
if let deviceNum = accessoryManager.activeDeviceNum, let node {
|
||||
let connectedNode = getNodeInfo(id: deviceNum, context: context)
|
||||
if let connectedNode, node.num != deviceNum {
|
||||
if UserDefaults.enableAdministration {
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.takConfig == nil {
|
||||
Task {
|
||||
do {
|
||||
Logger.mesh.info("⚙️ Empty or expired TAK module config requesting via PKI admin")
|
||||
try await accessoryManager.requestTAKModuleConfig(fromUser: connectedNode.user!, toUser: node.user!)
|
||||
} catch {
|
||||
Logger.mesh.info("🚨 TAK module config request failed: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Logger.mesh.info("☠️ Using insecure legacy admin that is no longer supported, please upgrade your firmware.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: team) { _, newTeam in
|
||||
if newTeam != Int(node?.takConfig?.team ?? Int32(Team.unspecifedColor.rawValue)) {
|
||||
hasChanges = true
|
||||
}
|
||||
}
|
||||
.onChange(of: role) { _, newRole in
|
||||
if newRole != Int(node?.takConfig?.role ?? Int32(MemberRole.unspecifed.rawValue)) {
|
||||
hasChanges = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func setTAKValues() {
|
||||
team = Int(node?.takConfig?.team ?? Int32(Team.unspecifedColor.rawValue))
|
||||
role = Int(node?.takConfig?.role ?? Int32(MemberRole.unspecifed.rawValue))
|
||||
hasChanges = false
|
||||
}
|
||||
|
||||
private func teamTitle(_ team: Team) -> String {
|
||||
switch team {
|
||||
case .unspecifedColor:
|
||||
return "Default (Cyan)"
|
||||
case .white:
|
||||
return "White"
|
||||
case .yellow:
|
||||
return "Yellow"
|
||||
case .orange:
|
||||
return "Orange"
|
||||
case .magenta:
|
||||
return "Magenta"
|
||||
case .red:
|
||||
return "Red"
|
||||
case .maroon:
|
||||
return "Maroon"
|
||||
case .purple:
|
||||
return "Purple"
|
||||
case .darkBlue:
|
||||
return "Dark Blue"
|
||||
case .blue:
|
||||
return "Blue"
|
||||
case .cyan:
|
||||
return "Cyan"
|
||||
case .teal:
|
||||
return "Teal"
|
||||
case .green:
|
||||
return "Green"
|
||||
case .darkGreen:
|
||||
return "Dark Green"
|
||||
case .brown:
|
||||
return "Brown"
|
||||
case .UNRECOGNIZED:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
private func roleTitle(_ role: MemberRole) -> String {
|
||||
switch role {
|
||||
case .unspecifed:
|
||||
return "Default (Team Member)"
|
||||
case .teamMember:
|
||||
return "Team Member"
|
||||
case .teamLead:
|
||||
return "Team Lead"
|
||||
case .hq:
|
||||
return "HQ"
|
||||
case .sniper:
|
||||
return "Sniper"
|
||||
case .medic:
|
||||
return "Medic"
|
||||
case .forwardObserver:
|
||||
return "Forward Observer"
|
||||
case .rto:
|
||||
return "RTO"
|
||||
case .k9:
|
||||
return "K9"
|
||||
case .UNRECOGNIZED:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
private func teamHelpText(_ team: Team) -> String {
|
||||
switch team {
|
||||
case .unspecifedColor:
|
||||
return "Default uses Cyan."
|
||||
case .UNRECOGNIZED:
|
||||
return "Unknown team color."
|
||||
default:
|
||||
return "Shown to TAK clients as the \(teamTitle(team)) team color."
|
||||
}
|
||||
}
|
||||
|
||||
private func roleHelpText(_ role: MemberRole) -> String {
|
||||
switch role {
|
||||
case .unspecifed:
|
||||
return "Default uses Team Member."
|
||||
case .UNRECOGNIZED:
|
||||
return "Unknown TAK role."
|
||||
default:
|
||||
return "Shown to TAK clients as the \(roleTitle(role)) role."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return TAKModuleConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue