diff --git a/Localizable.xcstrings b/Localizable.xcstrings index d0857465a..f5642a53a 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -5052,9 +5052,6 @@ }, "Debug Log" : { - }, - "Debug Logs" : { - }, "Debug Logs%@" : { @@ -10852,6 +10849,9 @@ }, "Line Series" : { + }, + "Loading Logs. . ." : { + }, "Location: %@" : { @@ -15304,9 +15304,6 @@ }, "No Environment Metrics" : { - }, - "No Logs Available" : { - }, "No Positions" : { diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index 5ee37673e..0d6f59176 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -670,7 +670,7 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage telemetry.voltage = telemetryMessage.deviceMetrics.voltage telemetry.uptimeSeconds = Int32(telemetryMessage.deviceMetrics.uptimeSeconds) telemetry.metricsType = 0 - Logger.statistics.info("📈 [Mesh Statistics] Channel Utilization: \(telemetryMessage.deviceMetrics.channelUtilization, privacy: .public) Airtime: \(telemetryMessage.deviceMetrics.airUtilTx, privacy: .public) for Node: \(packet.from.toHex(), privacy: .public))") + Logger.statistics.info("📈 [Mesh Statistics] Channel Utilization: \(telemetryMessage.deviceMetrics.channelUtilization, privacy: .public) Airtime: \(telemetryMessage.deviceMetrics.airUtilTx, privacy: .public) for Node: \(packet.from.toHex(), privacy: .public)") } else if telemetryMessage.variant == Telemetry.OneOf_Variant.environmentMetrics(telemetryMessage.environmentMetrics) { // Environment Metrics telemetry.barometricPressure = telemetryMessage.environmentMetrics.barometricPressure diff --git a/Meshtastic/Views/Settings/AppLog.swift b/Meshtastic/Views/Settings/AppLog.swift index 2ed2b081c..fd3db8106 100644 --- a/Meshtastic/Views/Settings/AppLog.swift +++ b/Meshtastic/Views/Settings/AppLog.swift @@ -9,7 +9,7 @@ import SwiftUI import OSLog /// Needed for TableColumnForEach -@available(iOS 17.4, macOS 14.4, *) +@available(iOS 17.0, macOS 14.0, *) struct AppLog: View { @State private var logs: [OSLogEntryLog] = [] @@ -33,61 +33,101 @@ struct AppLog: View { .secondFraction(.fractional(3)) var body: some View { + HStack { - Table(logs, selection: $selection, sortOrder: $sortOrder) { - if idiom != .phone { - TableColumn("log.time") { value in - Text(value.date.formatted(dateFormatStyle)) + if idiom == .phone { + Table(logs, selection: $selection, sortOrder: $sortOrder) { + TableColumn("log.message", value: \.composedMessage) { value in + Text(value.composedMessage) + .foregroundStyle(value.level.color) + .font(.caption) + } + .width(ideal: 200, max: .infinity) } - .width(min: 125, max: 150) - TableColumn("log.level") { value in - Text(value.level.description) - .foregroundStyle(value.level.color) + .monospaced() + .safeAreaInset(edge: .bottom, alignment: .trailing) { + HStack { + Button(action: { + withAnimation { + isEditingFilters = !isEditingFilters + } + }) { + Image(systemName: !isEditingFilters ? "line.3.horizontal.decrease.circle" : "line.3.horizontal.decrease.circle.fill") + .padding(.vertical, 5) + } + .tint(Color(UIColor.secondarySystemBackground)) + .foregroundColor(.accentColor) + .buttonStyle(.borderedProminent) + } + .controlSize(.regular) + .padding(5) } - .width(min: 85, max: 110) - TableColumn("log.category", value: \.category) - .width(min: 80, max: 130) - } - TableColumn("log.message", value: \.composedMessage) { value in - Text(value.composedMessage) - .foregroundStyle(value.level.color) - .font(idiom == .phone ? .caption : .body) - } - .width(ideal: 200, max: .infinity) - } - .monospaced() - - .safeAreaInset(edge: .bottom, alignment: .trailing) { - HStack { - Button(action: { - withAnimation { - isEditingFilters = !isEditingFilters + .padding(.bottom, 5) + .padding(.trailing, 5) + .searchable(text: $searchText, placement: .navigationBarDrawer, prompt: "Search") + .disabled(selection != nil) + .overlay { + if logs.isEmpty { + ContentUnavailableView("Loading Logs. . .", systemImage: "scroll") } - }) { - Image(systemName: !isEditingFilters ? "line.3.horizontal.decrease.circle" : "line.3.horizontal.decrease.circle.fill") - .padding(.vertical, 5) } - .tint(Color(UIColor.secondarySystemBackground)) - .foregroundColor(.accentColor) - .buttonStyle(.borderedProminent) - - } - .controlSize(.regular) - .padding(5) - } - .padding(.bottom, 5) - .padding(.trailing, 5) - .searchable(text: $searchText, placement: .navigationBarDrawer, prompt: "Search") - .disabled(selection != nil) - .overlay { - if logs.isEmpty { - ContentUnavailableView("No Logs Available", systemImage: "scroll") + .refreshable { + await logs = searchAppLogs() + logs.sort(using: sortOrder) + } + } else { + Table(logs, selection: $selection, sortOrder: $sortOrder) { + TableColumn("log.time") { value in + Text(value.date.formatted(dateFormatStyle)) + } + .width(min: 125, max: 150) + TableColumn("log.level") { value in + Text(value.level.description) + .foregroundStyle(value.level.color) + } + .width(min: 85, max: 110) + TableColumn("log.category", value: \.category) + .width(min: 80, max: 130) + TableColumn("log.message", value: \.composedMessage) { value in + Text(value.composedMessage) + .foregroundStyle(value.level.color) + .font(.body) + } + .width(ideal: 200, max: .infinity) + } + .monospaced() + .safeAreaInset(edge: .bottom, alignment: .trailing) { + HStack { + Button(action: { + withAnimation { + isEditingFilters = !isEditingFilters + } + }) { + Image(systemName: !isEditingFilters ? "line.3.horizontal.decrease.circle" : "line.3.horizontal.decrease.circle.fill") + .padding(.vertical, 5) + } + .tint(Color(UIColor.secondarySystemBackground)) + .foregroundColor(.accentColor) + .buttonStyle(.borderedProminent) + } + .controlSize(.regular) + .padding(5) + } + .padding(.bottom, 5) + .padding(.trailing, 5) + .searchable(text: $searchText, placement: .navigationBarDrawer, prompt: "Search") + .disabled(selection != nil) + .overlay { + if logs.isEmpty { + ContentUnavailableView("Loading Logs. . .", systemImage: "scroll") + } + } + .refreshable { + await logs = searchAppLogs() + logs.sort(using: sortOrder) + } } } - .refreshable { - await logs = searchAppLogs() - logs.sort(using: sortOrder) - } .onChange(of: sortOrder) { _, sortOrder in withAnimation { logs.sort(using: sortOrder) @@ -176,7 +216,7 @@ struct AppLog: View { } } -@available(iOS 17.4, macOS 14.4, *) +@available(iOS 17.0, macOS 14.0, *) extension AppLog { @MainActor private func searchAppLogs() async -> [OSLogEntryLog] { diff --git a/Meshtastic/Views/Settings/MeshLog.swift b/Meshtastic/Views/Settings/MeshLog.swift index da2b5014a..e63c2f34b 100644 --- a/Meshtastic/Views/Settings/MeshLog.swift +++ b/Meshtastic/Views/Settings/MeshLog.swift @@ -18,7 +18,7 @@ struct MeshLog: View { let url = logFile! logs.removeAll() var lineCount = 0 - let lineLimit = 1000 + let lineLimit = 10000 // Get the number of lines for try await _ in url.lines { lineCount += 1 diff --git a/Meshtastic/Views/Settings/Settings.swift b/Meshtastic/Views/Settings/Settings.swift index faad71ad8..b141f9977 100644 --- a/Meshtastic/Views/Settings/Settings.swift +++ b/Meshtastic/Views/Settings/Settings.swift @@ -243,20 +243,12 @@ struct Settings: View { var loggingSection: some View { Section(header: Text("logging")) { - NavigationLink(value: SettingsNavigationState.meshLog) { - Label { - Text("mesh.log") - } icon: { - Image(systemName: "list.bullet.rectangle") - } - } - - if #available (iOS 17.4, *) { + if #available (iOS 17.0, *) { NavigationLink(value: SettingsNavigationState.debugLogs) { Label { - Text("Debug Logs") + Text("Logs") } icon: { - Image(systemName: "stethoscope") + Image(systemName: "scroll") } } } @@ -265,6 +257,13 @@ struct Settings: View { var developersSection: some View { Section(header: Text("Developers")) { + NavigationLink(value: SettingsNavigationState.meshLog) { + Label { + Text("mesh.log") + } icon: { + Image(systemName: "list.bullet.rectangle") + } + } NavigationLink(value: SettingsNavigationState.appFiles) { Label { Text("App Files") @@ -445,7 +444,7 @@ struct Settings: View { case .power: PowerConfig(node: node) case .ambientLighting: - if #available(iOS 17.0, *) { + if #available(iOS 17.0, macOS 14.0, *) { AmbientLightingConfig(node: node) } case .cannedMessages: @@ -471,7 +470,7 @@ struct Settings: View { case .meshLog: MeshLog() case .debugLogs: - if #available(iOS 17.4, *) { + if #available(iOS 17.0, macOS 14.0, *) { AppLog() } case .appFiles: