From 464b74a118e61354982fb23ec77f78aa6277bdb7 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Sat, 17 Dec 2022 19:14:53 -0800 Subject: [PATCH] Channel Grid --- Meshtastic.xcodeproj/project.pbxproj | 16 ++- Meshtastic/Views/Messages/Contacts.swift | 2 +- Meshtastic/Views/Settings/Channels.swift | 106 ++++++++++++++++++ Meshtastic/Views/Settings/Settings.swift | 11 ++ Meshtastic/Views/Settings/ShareChannels.swift | 2 +- de.lproj/Localizable.strings | 3 +- en.lproj/Localizable.strings | 3 +- 7 files changed, 133 insertions(+), 10 deletions(-) create mode 100644 Meshtastic/Views/Settings/Channels.swift diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index 1818b5e5..0d6c3898 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -69,6 +69,7 @@ DD913639270DFF4C00D7ACF3 /* LocalNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD913638270DFF4C00D7ACF3 /* LocalNotificationManager.swift */; }; DD97E96628EFD9820056DDA4 /* MeshtasticLogo.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD97E96528EFD9820056DDA4 /* MeshtasticLogo.swift */; }; DD97E96828EFE9A00056DDA4 /* About.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD97E96728EFE9A00056DDA4 /* About.swift */; }; + DDA0B6B2294CDC55001356EC /* Channels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA0B6B1294CDC55001356EC /* Channels.swift */; }; DDA1C48E28DB49D3009933EC /* ChannelRoles.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA1C48D28DB49D3009933EC /* ChannelRoles.swift */; }; DDA6B2E928419CF2003E8C16 /* MeshPackets.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6B2E828419CF2003E8C16 /* MeshPackets.swift */; }; DDA6B2EB28420A7B003E8C16 /* NodeAnnotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6B2EA28420A7B003E8C16 /* NodeAnnotation.swift */; }; @@ -187,6 +188,7 @@ DD913638270DFF4C00D7ACF3 /* LocalNotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalNotificationManager.swift; sourceTree = ""; }; DD97E96528EFD9820056DDA4 /* MeshtasticLogo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshtasticLogo.swift; sourceTree = ""; }; DD97E96728EFE9A00056DDA4 /* About.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = About.swift; sourceTree = ""; }; + DDA0B6B1294CDC55001356EC /* Channels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Channels.swift; sourceTree = ""; }; DDA1C48D28DB49D3009933EC /* ChannelRoles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelRoles.swift; sourceTree = ""; }; DDA6B2E828419CF2003E8C16 /* MeshPackets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshPackets.swift; sourceTree = ""; }; DDA6B2EA28420A7B003E8C16 /* NodeAnnotation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeAnnotation.swift; sourceTree = ""; }; @@ -305,13 +307,14 @@ isa = PBXGroup; children = ( DD97E96728EFE9A00056DDA4 /* About.swift */, - DD3501882852FC3B000FC853 /* Settings.swift */, - DD4A911D2708C65400501B7E /* AppSettings.swift */, - DD8169FA271F1F3A00F4AB02 /* MeshLog.swift */, - DD3CC6B428E33FD100FA9159 /* ShareChannels.swift */, - DD86D40B287F401000BAEB7A /* SaveChannelQRCode.swift */, - DDCE4E2B2869F92900BE9F8F /* UserConfig.swift */, DD0F791A28713C8A00A6FDAD /* AdminMessageList.swift */, + DD4A911D2708C65400501B7E /* AppSettings.swift */, + DDA0B6B1294CDC55001356EC /* Channels.swift */, + DD8169FA271F1F3A00F4AB02 /* MeshLog.swift */, + DD86D40B287F401000BAEB7A /* SaveChannelQRCode.swift */, + DD3501882852FC3B000FC853 /* Settings.swift */, + DD3CC6B428E33FD100FA9159 /* ShareChannels.swift */, + DDCE4E2B2869F92900BE9F8F /* UserConfig.swift */, DD61937A2863876A00E59241 /* Config */, ); path = Settings; @@ -737,6 +740,7 @@ DD90860E26F69BAE00DC5189 /* NodeMap.swift in Sources */, DD8169FF272476C700F4AB02 /* LogDocument.swift in Sources */, DD6193792863875F00E59241 /* SerialConfig.swift in Sources */, + DDA0B6B2294CDC55001356EC /* Channels.swift in Sources */, DDAF8C6926ED0D070058C060 /* deviceonly.pb.swift in Sources */, DD4A911E2708C65400501B7E /* AppSettings.swift in Sources */, DD35018B2852FC79000FC853 /* UserSettings.swift in Sources */, diff --git a/Meshtastic/Views/Messages/Contacts.swift b/Meshtastic/Views/Messages/Contacts.swift index 4e07be06..7d873cee 100644 --- a/Meshtastic/Views/Messages/Contacts.swift +++ b/Meshtastic/Views/Messages/Contacts.swift @@ -28,7 +28,7 @@ struct Contacts: View { NavigationSplitView { List { - Section(header: Text("Channels (groups)")) { + Section(header: Text("channels")) { // Display Contacts for the rest of the non admin channels if node != nil && node!.myInfo != nil && node!.myInfo!.channels != nil { ForEach(node!.myInfo!.channels!.array as! [ChannelEntity], id: \.self) { (channel: ChannelEntity) in diff --git a/Meshtastic/Views/Settings/Channels.swift b/Meshtastic/Views/Settings/Channels.swift new file mode 100644 index 00000000..cda0b2f1 --- /dev/null +++ b/Meshtastic/Views/Settings/Channels.swift @@ -0,0 +1,106 @@ +// +// ShareChannel.swift +// MeshtasticApple +// +// Copyright(c) Garth Vander Houwen 4/8/22. +// +import SwiftUI +import CoreData + +func generateChannelKey(size: Int) -> String { + var keyData = Data(count: size) + let result = keyData.withUnsafeMutableBytes { + SecRandomCopyBytes(kSecRandomDefault, size, $0.baseAddress!) + } + return keyData.base64EncodedString() +} + +struct Channels: View { + + @Environment(\.managedObjectContext) var context + @EnvironmentObject var bleManager: BLEManager + @Environment(\.dismiss) private var dismiss + @Environment(\.sizeCategory) var sizeCategory + + var node: NodeInfoEntity? + + @State private var isPresentingEditView = false + + var body: some View { + + ScrollView { + if node != nil && node?.myInfo != nil { + Grid() { + GridRow { + Text("Index") + .font(.caption2) + Text("name") + .font(.caption2) + if sizeCategory <= ContentSizeCategory.extraExtraLarge { + Text("Up/down link") + .font(.caption2) + } + Text("Edit") + .font(.caption2) + Text("Delete") + .font(.caption2) + } + ForEach(node!.myInfo!.channels?.array as! [ChannelEntity], id: \.self) { (channel: ChannelEntity) in + GridRow { + CircleText(text: String(channel.index), color: .accentColor, circleSize: 32) + Text(((channel.name!.isEmpty ? "Primary" : channel.name) ?? "Primary").camelCaseToWords()) + if sizeCategory <= ContentSizeCategory.extraExtraLarge { + HStack { + if channel.uplinkEnabled { + Image(systemName: "checkmark.square") + } else { + Image(systemName: "square") + } + if channel.downlinkEnabled { + Image(systemName: "checkmark.square") + } else { + Image(systemName: "square") + } + } + } + Button { + print("Edit Channel") + + } label: { + Label("", systemImage: "square.and.pencil") + } + Button(role: .destructive) { + print("Delete Channel") + + } label: { + Label("", systemImage: "trash") + } + .disabled(channel.role == 1) + } + } + } + if node!.myInfo!.channels?.array.count ?? 0 < 8 { + + Button { + print("Add Channel") + + } label: { + Label("Add Channel", systemImage: "plus.square") + } + .buttonStyle(.bordered) + .buttonBorderShape(.capsule) + .controlSize(.large) + .padding() + } + } + } + .navigationTitle("Channels") + .navigationBarItems(trailing: + ZStack { + ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") + }) + .onAppear { + bleManager.context = context + } + } +} diff --git a/Meshtastic/Views/Settings/Settings.swift b/Meshtastic/Views/Settings/Settings.swift index 7b6ad0d6..528aacc5 100644 --- a/Meshtastic/Views/Settings/Settings.swift +++ b/Meshtastic/Views/Settings/Settings.swift @@ -59,6 +59,17 @@ struct Settings: View { Text("lora") } + NavigationLink() { + + Channels(node: nodes.first(where: { $0.num == connectedNodeNum })) + } label: { + + Image(systemName: "fibrechannel") + .symbolRenderingMode(.hierarchical) + + Text("channels") + } + NavigationLink() { BluetoothConfig(node: nodes.first(where: { $0.num == connectedNodeNum })) diff --git a/Meshtastic/Views/Settings/ShareChannels.swift b/Meshtastic/Views/Settings/ShareChannels.swift index 75240770..5810b5cf 100644 --- a/Meshtastic/Views/Settings/ShareChannels.swift +++ b/Meshtastic/Views/Settings/ShareChannels.swift @@ -76,7 +76,7 @@ struct ShareChannels: View { .toggleStyle(.switch) .labelsHidden() .disabled(channel.role == 1) - Text(((channel.name!.isEmpty ? "Primary" : channel.name) ?? "Primary").camelCaseToWords()).fixedSize() + Text(((channel.name!.isEmpty ? "Primary" : channel.name) ?? "Primary").camelCaseToWords()) if channel.psk?.hexDescription.count ?? 0 < 3 { Image(systemName: "lock.slash") .foregroundColor(.red) diff --git a/de.lproj/Localizable.strings b/de.lproj/Localizable.strings index 7ec05091..bde184d0 100644 --- a/de.lproj/Localizable.strings +++ b/de.lproj/Localizable.strings @@ -33,7 +33,7 @@ "channel.role.disabled"="Deaktiviert"; "channel.role.primary"="Primär"; "channel.role.secondary"="Sekundär"; -"channels"="Kanäle (Gruppen)"; +"channels"="Kanäle"; "clear.app.data"="App Daten löschen"; "connected.radio"="Verbundenes Gerät"; "communicating"="Verbinde mit Gerät..."; @@ -111,6 +111,7 @@ "mqtt"="MQTT"; "mqtt.config"="MQTT Config"; "mqtt.username"="Benutzername"; +"name"="Name"; "network"="Netzwerk"; "network.config"="Netzwerkeinstellungen"; "nodes"="Nodes"; diff --git a/en.lproj/Localizable.strings b/en.lproj/Localizable.strings index b97f5f37..dbe62ed9 100644 --- a/en.lproj/Localizable.strings +++ b/en.lproj/Localizable.strings @@ -33,7 +33,7 @@ "channel.role.disabled"="Disabled"; "channel.role.primary"="Primary"; "channel.role.secondary"="Secondary"; -"channels"="Channels (groups)"; +"channels"="Channels"; "clear.app.data"="Clear App Data"; "connected.radio"="Connected Radio"; "communicating"="Communicating with device. ."; @@ -111,6 +111,7 @@ "mqtt"="MQTT"; "mqtt.config"="MQTT Config"; "mqtt.username"="Username"; +"name"="Name"; "network"="Network"; "network.config"="Network Config"; "nodes"="Nodes";