From 2f9351c6535a2dde0d053cd8099389471c73880d Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Sun, 14 Jan 2024 19:54:00 -0800 Subject: [PATCH] Bump version, get firmware list from the json api --- Meshtastic.xcodeproj/project.pbxproj | 8 +- Meshtastic/Views/Settings/Firmware.swift | 135 +++++--------------- Meshtastic/Views/Settings/FirmwareApi.swift | 60 +++++---- Meshtastic/Views/Settings/Settings.swift | 39 +++--- 4 files changed, 89 insertions(+), 153 deletions(-) diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index 5ad009b7..bb725735 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -1491,7 +1491,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.2.18; + MARKETING_VERSION = 2.2.19; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = YES; @@ -1525,7 +1525,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.2.18; + MARKETING_VERSION = 2.2.19; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = YES; @@ -1647,7 +1647,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.2.18; + MARKETING_VERSION = 2.2.19; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1680,7 +1680,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.2.18; + MARKETING_VERSION = 2.2.19; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/Meshtastic/Views/Settings/Firmware.swift b/Meshtastic/Views/Settings/Firmware.swift index 8878b0d9..0e929dca 100644 --- a/Meshtastic/Views/Settings/Firmware.swift +++ b/Meshtastic/Views/Settings/Firmware.swift @@ -17,23 +17,42 @@ struct Firmware: View { @State private var currentDevice: DeviceHardware? var body: some View { + + let supportedVersion = bleManager.connectedVersion == "0.0.0" || self.minimumVersion.compare(bleManager.connectedVersion, options: .numeric) == .orderedAscending || minimumVersion.compare(bleManager.connectedVersion, options: .numeric) == .orderedSame VStack { VStack(alignment: .leading) { let deviceString = currentDevice?.hwModelSlug.replacingOccurrences(of: "_", with: "") - Text("Your Device Model: \(currentDevice?.displayName ?? "Unknown")") - .font(.largeTitle) - + HStack { + VStack { + Image(systemName: currentDevice?.activelySupported ?? false ? "checkmark.seal.fill" : "x.circle") + .font(.largeTitle) + .foregroundStyle(currentDevice?.activelySupported ?? false ? .green : .red) + Text( currentDevice?.activelySupported ?? false ? "Supported" : "Unsupported") + .foregroundStyle(.gray) + .font(.caption2) + } + Text("Device Model: \(currentDevice?.displayName ?? "Unknown")") + .font(.largeTitle) + } VStack { Image(deviceString ?? "UNSET") .resizable() .aspectRatio(contentMode: .fit) - .frame(width: 200, height: 200) + .frame(width: 300, height: 300) .cornerRadius(5) } - Text("Current Firmware Version: \(bleManager.connectedVersion)") - .font(.title) - + if supportedVersion { + Text("Your Firmware is up to date") + .font(.title) + Text("Current Firmware Version: \(bleManager.connectedVersion)") + .font(.title2) + } else { + Text("Your Firmware is out of date") + .font(.title) + Text("Current Firmware Version: \(bleManager.connectedVersion), Minimium Firmware Version: \(minimumVersion)") + .font(.title2) + } if currentDevice?.architecture == Meshtastic.Architecture.nrf52840 { VStack(alignment: .leading) { /// RAK 4631 @@ -141,115 +160,19 @@ struct Firmware: View { .onAppear() { Api().loadDeviceHardwareData { (hw) in for device in hw { - print(device) let currentHardware = node?.user?.hwModel ?? "UNSET" let deviceString = device.hwModelSlug.replacingOccurrences(of: "_", with: "") if deviceString == currentHardware { - print("Selected: \(device)") currentDevice = device } } } -// Api().loadFirmwareReleaseData { (bks) in -// //sel = bks -// } + Api().loadFirmwareReleaseData { (bks) in + //sel = bks + } } .navigationTitle("Firmware Updates") .navigationBarTitleDisplayMode(.inline) } } } - -//struct FirmwareRelease: Codable { -// var releases: Releases? = Releases() -// var pullRequests: [PullRequests]? = [] -// enum CodingKeys: String, CodingKey { -// case releases = "Releases" -// case pullRequests = "Pull Requests" -// } -// init(from decoder: Decoder) throws { -// let values = try decoder.container(keyedBy: CodingKeys.self) -// releases = try values.decodeIfPresent(Releases.self, forKey: .releases ) -// pullRequests = try values.decodeIfPresent([PullRequests].self, forKey: .pullRequests ) -// } -// init() { -// } -//} -// -//struct Releases: Codable { -// var stable: [Stable]? = [] -// var alpha: [Alpha]? = [] -// enum CodingKeys: String, CodingKey { -// case stable = "Stable" -// case alpha = "Alpha" -// } -// init(from decoder: Decoder) throws { -// let values = try decoder.container(keyedBy: CodingKeys.self) -// stable = try values.decodeIfPresent([Stable].self, forKey: .stable ) -// alpha = try values.decodeIfPresent([Alpha].self, forKey: .alpha ) -// } -// init() {} -//} -// -//struct Alpha: Codable { -// var id: String? -// var title: String? -// var pageUrl: String? -// var zipUrl: String? -// enum CodingKeys: String, CodingKey { -// case id = "id" -// case title = "title" -// case pageUrl = "page_url" -// case zipUrl = "zip_url" -// } -// init(from decoder: Decoder) throws { -// let values = try decoder.container(keyedBy: CodingKeys.self) -// id = try values.decodeIfPresent(String.self, forKey: .id ) -// title = try values.decodeIfPresent(String.self, forKey: .title ) -// pageUrl = try values.decodeIfPresent(String.self, forKey: .pageUrl ) -// zipUrl = try values.decodeIfPresent(String.self, forKey: .zipUrl ) -// } -// init() {} -//} -// -//struct Stable: Codable { -// var id: String? -// var title: String? -// var pageUrl: String? -// var zipUrl: String? -// enum CodingKeys: String, CodingKey { -// case id = "id" -// case title = "title" -// case pageUrl = "page_url" -// case zipUrl = "zip_url" -// } -// init(from decoder: Decoder) throws { -// let values = try decoder.container(keyedBy: CodingKeys.self) -// id = try values.decodeIfPresent(String.self, forKey: .id ) -// title = try values.decodeIfPresent(String.self, forKey: .title ) -// pageUrl = try values.decodeIfPresent(String.self, forKey: .pageUrl ) -// zipUrl = try values.decodeIfPresent(String.self, forKey: .zipUrl ) -// } -// init() {} -//} -// -//struct PullRequests: Codable { -// var id: String? -// var title: String? -// var pageUrl: String? -// var zipUrl: String? -// enum CodingKeys: String, CodingKey { -// case id = "id" -// case title = "title" -// case pageUrl = "page_url" -// case zipUrl = "zip_url" -// } -// init(from decoder: Decoder) throws { -// let values = try decoder.container(keyedBy: CodingKeys.self) -// id = try values.decodeIfPresent(String.self, forKey: .id ) -// title = try values.decodeIfPresent(String.self, forKey: .title ) -// pageUrl = try values.decodeIfPresent(String.self, forKey: .pageUrl ) -// zipUrl = try values.decodeIfPresent(String.self, forKey: .zipUrl ) -// } -// init() {} -//} diff --git a/Meshtastic/Views/Settings/FirmwareApi.swift b/Meshtastic/Views/Settings/FirmwareApi.swift index 5eb2f488..ab480849 100644 --- a/Meshtastic/Views/Settings/FirmwareApi.swift +++ b/Meshtastic/Views/Settings/FirmwareApi.swift @@ -7,14 +7,6 @@ import Foundation -//struct DeviceHardware: Codable { -// var hwModel: Int -// var hwModelSlug: String -// var platformioTarget: String -// var activelySupported: Bool -// var displayName: String -//} - struct DeviceHardware: Codable { let hwModel: Int let hwModelSlug, platformioTarget: String @@ -31,9 +23,30 @@ enum Architecture: String, Codable { case rp2040 = "rp2040" } +struct FirmwareReleases: Codable { + let releases: Releases + let pullRequests: [PullRequest] +} + +struct PullRequest: Codable { + let id, title: String + let pageURL: String + let zipURL: String + + enum CodingKeys: String, CodingKey { + case id, title + case pageURL = "page_url" + case zipURL = "zip_url" + } +} + +// MARK: - Releases +struct Releases: Codable { + let stable, alpha: [PullRequest] +} + class Api : ObservableObject{ -// @Published var devices = [DeviceHardware]() - + func loadDeviceHardwareData(completion:@escaping ([DeviceHardware]) -> ()) { guard let url = URL(string: "https://api.meshtastic.org/resource/deviceHardware") else { print("Invalid url...") @@ -47,17 +60,18 @@ class Api : ObservableObject{ } }.resume() } -// func loadFirmwareReleaseData(completion:@escaping ([FirmwareRelease]) -> ()) { -// guard let url = URL(string: "https://api.meshtastic.org/github/firmware/list") else { -// print("Invalid url...") -// return -// } -// URLSession.shared.dataTask(with: url) { data, response, error in -// let deviceHardware = try! JSONDecoder().decode([FirmwareRelease].self, from: data!) -// print(deviceHardware) -// DispatchQueue.main.async { -// completion(deviceHardware) -// } -// }.resume() -// } + + func loadFirmwareReleaseData(completion:@escaping (FirmwareReleases) -> ()) { + guard let url = URL(string: "https://api.meshtastic.org/github/firmware/list") else { + print("Invalid url...") + return + } + URLSession.shared.dataTask(with: url) { data, response, error in + let firmwareReleases = try! JSONDecoder().decode(FirmwareReleases.self, from: data!) + print(firmwareReleases) + DispatchQueue.main.async { + completion(firmwareReleases) + } + }.resume() + } } diff --git a/Meshtastic/Views/Settings/Settings.swift b/Meshtastic/Views/Settings/Settings.swift index a7baadf0..886acf8c 100644 --- a/Meshtastic/Views/Settings/Settings.swift +++ b/Meshtastic/Views/Settings/Settings.swift @@ -69,15 +69,14 @@ struct Settings: View { Text("routes") } .tag(SettingsSidebar.routes) - -// NavigationLink { -// RouteRecorder() -// } label: { -// Image(systemName: "record.circle") -// .symbolRenderingMode(.hierarchical) -// Text("route.recorder") -// } -// .tag(SettingsSidebar.routeRecorder) + NavigationLink { + RouteRecorder() + } label: { + Image(systemName: "record.circle") + .symbolRenderingMode(.hierarchical) + Text("route.recorder") + } + .tag(SettingsSidebar.routeRecorder) } let node = nodes.first(where: { $0.num == preferredNodeNum }) @@ -299,17 +298,17 @@ struct Settings: View { } .tag(SettingsSidebar.adminMessageLog) } -// Section(header: Text("Firmware")) { -// NavigationLink { -// Firmware(node: nodes.first(where: { $0.num == preferredNodeNum })) -// } label: { -// Image(systemName: "arrow.up.arrow.down.square") -// .symbolRenderingMode(.hierarchical) -// Text("Firmware Updates") -// } -// .tag(SettingsSidebar.about) -// .disabled(selectedNode > 0 && selectedNode != preferredNodeNum) -// } + Section(header: Text("Firmware")) { + NavigationLink { + Firmware(node: nodes.first(where: { $0.num == preferredNodeNum })) + } label: { + Image(systemName: "arrow.up.arrow.down.square") + .symbolRenderingMode(.hierarchical) + Text("Firmware Updates") + } + .tag(SettingsSidebar.about) + .disabled(selectedNode > 0 && selectedNode != preferredNodeNum) + } } } .onAppear {