diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index 59a1dd10..25d6cac0 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -1522,7 +1522,7 @@ CODE_SIGN_ENTITLEMENTS = Meshtastic/Meshtastic.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 959; DEVELOPMENT_ASSET_PATHS = "\"Meshtastic/Preview Content\""; DEVELOPMENT_TEAM = GCH7VS5Y9R; ENABLE_PREVIEWS = YES; @@ -1556,7 +1556,7 @@ CODE_SIGN_ENTITLEMENTS = Meshtastic/Meshtastic.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 959; DEVELOPMENT_ASSET_PATHS = "\"Meshtastic/Preview Content\""; DEVELOPMENT_TEAM = GCH7VS5Y9R; ENABLE_PREVIEWS = YES; diff --git a/Meshtastic/Export/WriteCsvFile.swift b/Meshtastic/Export/WriteCsvFile.swift index 521dc937..56776554 100644 --- a/Meshtastic/Export/WriteCsvFile.swift +++ b/Meshtastic/Export/WriteCsvFile.swift @@ -6,6 +6,7 @@ // import SwiftUI +import OSLog func telemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> String { var csvString: String = "" @@ -64,6 +65,27 @@ func detectionsToCsv(detections: [MessageEntity]) -> String { return csvString } +func logToCsvFile(log: [OSLogEntryLog]) -> String { + var csvString: String = "" + let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmma", options: 0, locale: Locale.current) + let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mma").replacingOccurrences(of: ",", with: "") + // Create PAX Header + csvString = "Process, Category, Level, Message, \("timestamp".localized)" + for l in log { + csvString += "\n" + csvString += String(l.process) + csvString += ", " + csvString += String(l.category) + csvString += ", " + csvString += String(l.level.description) + csvString += ", " + csvString += String(l.composedMessage) + csvString += ", " + csvString += l.date.formattedDate(format: dateFormatString) + } + return csvString +} + func paxToCsvFile(pax: [PaxCounterEntity]) -> String { var csvString: String = "" let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmma", options: 0, locale: Locale.current) diff --git a/Meshtastic/Views/Settings/AppLog.swift b/Meshtastic/Views/Settings/AppLog.swift index de925061..7203b0ba 100644 --- a/Meshtastic/Views/Settings/AppLog.swift +++ b/Meshtastic/Views/Settings/AppLog.swift @@ -16,6 +16,8 @@ struct AppLog: View { @State private var selection: OSLogEntry.ID? @State private var selectedLog: OSLogEntryLog? @State private var presentingErrorDetails: Bool = false + @State var isExporting = false + @State var exportString = "" private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom } private let dateFormatStyle = Date.FormatStyle() .hour(.twoDigits(amPM: .omitted)) @@ -61,7 +63,32 @@ struct AppLog: View { .task { logs = await fetchLogs() } + .fileExporter( + isPresented: $isExporting, + document: CsvDocument(emptyCsv: exportString), + contentType: .commaSeparatedText, + defaultFilename: String("Meshtastic Application Logs"), + onCompletion: { result in + switch result { + case .success: + self.isExporting = false + Logger.services.info("Application log download succeeded.") + case .failure(let error): + Logger.services.error("Application log download failed: \(error.localizedDescription)") + } + } + ) .navigationBarTitle("Debug Logs", displayMode: .inline) + .toolbar { + ToolbarItem(placement: .navigationBarTrailing) { + Button(action: { + exportString = logToCsvFile(log: logs) + isExporting = true + }) { + Image(systemName: "square.and.arrow.down") + } + } + } } } diff --git a/Meshtastic/Views/Settings/Settings.swift b/Meshtastic/Views/Settings/Settings.swift index 77ca47ad..55a77b65 100644 --- a/Meshtastic/Views/Settings/Settings.swift +++ b/Meshtastic/Views/Settings/Settings.swift @@ -424,7 +424,6 @@ struct Settings: View { } } .tag(SettingsSidebar.adminMessageLog) -#if DEBUG if #available (iOS 17.4, *) { NavigationLink { AppLog() @@ -437,7 +436,6 @@ struct Settings: View { } .tag(SettingsSidebar.appLog) } -#endif } Section(header: Text("Firmware")) { NavigationLink {