From 86b2bb621cc078e6bea926eb9b590cb009efc0bd Mon Sep 17 00:00:00 2001 From: neoarz Date: Sat, 29 Mar 2025 03:24:05 -0400 Subject: [PATCH 01/17] build logger ui --- StikJIT/Views/ConsoleLogsView.swift | 196 ++++++++++++++++++++++++++++ StikJIT/Views/SettingsView.swift | 43 +++++- 2 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 StikJIT/Views/ConsoleLogsView.swift diff --git a/StikJIT/Views/ConsoleLogsView.swift b/StikJIT/Views/ConsoleLogsView.swift new file mode 100644 index 0000000..618c37a --- /dev/null +++ b/StikJIT/Views/ConsoleLogsView.swift @@ -0,0 +1,196 @@ +// +// ConsoleLogsView.swift +// StikJIT +// +// Created by neoarz on 3/29/25. +// + +import SwiftUI +import UIKit + +struct ConsoleLogsView: View { + @Environment(\.dismiss) private var dismiss + @State private var dummyLogs: [String] = [ + "Initializing StikJIT environment...", + "Checking device compatibility...", + "Loading system configuration...", + "Verifying device permissions...", + "Initializing JIT compiler...", + "Loading pairing credentials...", + "Configuration loaded successfully", + "System check completed", + "Ready for operation" + ] + + var body: some View { + NavigationView { + ZStack { + Color(UIColor.systemBackground) + .edgesIgnoringSafeArea(.all) + + VStack(spacing: 0) { + // Terminal-style logs area + ScrollView { + VStack(spacing: 2) { + // Device Information + ForEach(["Version: \(UIDevice.current.systemVersion)", + "Name: \(UIDevice.current.name)", + "Model: \(UIDevice.current.model)", + "StikJIT: 1.0"], id: \.self) { info in + HStack { + Text("[\(timeString())]") + .foregroundColor(.blue) + .font(.system(size: 12, design: .monospaced)) + + Image(systemName: "checkmark.seal.fill") + .foregroundColor(.blue) + .font(.system(size: 10)) + + Text(info) + .font(.system(size: 12, design: .monospaced)) + .foregroundColor(.primary) + .frame(maxWidth: .infinity, alignment: .leading) + } + .padding(.vertical, 1) + .padding(.horizontal, 8) + } + + Divider() + .padding(.vertical, 4) + + // Log entries + ForEach(dummyLogs.indices, id: \.self) { index in + HStack(alignment: .top, spacing: 8) { + Text("[\(timeString(minutesAgo: dummyLogs.count - index))]") + .foregroundColor(.gray) + .font(.system(size: 11, design: .monospaced)) + + Text("[INFO]") + .foregroundColor(.green) + .font(.system(size: 11, design: .monospaced)) + + Text(dummyLogs[index]) + .font(.system(size: 11, design: .monospaced)) + .foregroundColor(.primary) + .frame(maxWidth: .infinity, alignment: .leading) + } + .padding(.vertical, 1) + .padding(.horizontal, 8) + } + } + .padding(.vertical, 8) + .background(Color(UIColor.secondarySystemBackground)) + .cornerRadius(8) + .padding(.horizontal, 8) + .padding(.top, 8) + } + + Spacer() + + // Bottom section with error count and action buttons + VStack(spacing: 16) { + // Error count + HStack { + Text("0 Critical Errors.") + .font(.headline) + .foregroundColor(.white) + .padding(.vertical, 10) + .padding(.horizontal, 20) + .frame(maxWidth: .infinity) + .background(Color.red) + .cornerRadius(8) + } + .padding(.horizontal) + + // Action buttons + VStack(spacing: 1) { + // Share button + Button(action: { + let logs = dummyLogs.map { "[\(timeString())] [INFO] \($0)" }.joined(separator: "\n") + let activityVC = UIActivityViewController(activityItems: [logs], applicationActivities: nil) + + guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, + let rootVC = windowScene.windows.first?.rootViewController else { return } + rootVC.present(activityVC, animated: true) + }) { + HStack { + Text("Share Logs") + .foregroundColor(.blue) + .padding(.leading, 2) + Spacer() + Image(systemName: "square.and.arrow.up") + .foregroundColor(.secondary) + } + .padding(.vertical, 14) + .padding(.horizontal, 20) + .contentShape(Rectangle()) + } + .background(Color.black.opacity(0.05)) + + Divider() + .background(Color.gray.opacity(0.3)) + + // Copy button + Button(action: { + let logs = dummyLogs.map { "[\(timeString())] [INFO] \($0)" }.joined(separator: "\n") + UIPasteboard.general.string = logs + }) { + HStack { + Text("Copy Logs") + .foregroundColor(.blue) + .padding(.leading, 2) + Spacer() + Image(systemName: "arrow.right") + .foregroundColor(.secondary) + } + .padding(.vertical, 14) + .padding(.horizontal, 20) + .contentShape(Rectangle()) + } + .background(Color.black.opacity(0.05)) + } + .cornerRadius(8) + .padding(.horizontal) + .padding(.bottom, 16) + } + } + } + .navigationTitle("Console Logs") + .navigationBarItems( + leading: Button(action: { + dismiss() + }) { + HStack(spacing: 2) { + Image(systemName: "chevron.left") + .font(.system(size: 16, weight: .semibold)) + Text("Settings") + .fontWeight(.regular) + } + .foregroundColor(.blue) + } + ) + } + } + + // Helper to display current time + private func timeString() -> String { + let formatter = DateFormatter() + formatter.dateFormat = "HH:mm:ss" + return formatter.string(from: Date()) + } + + // Helper to display time with offset for log display + private func timeString(minutesAgo: Int) -> String { + let formatter = DateFormatter() + formatter.dateFormat = "HH:mm:ss" + let date = Calendar.current.date(byAdding: .minute, value: -minutesAgo, to: Date()) ?? Date() + return formatter.string(from: date) + } +} + +// Preview provider +struct ConsoleLogsView_Previews: PreviewProvider { + static var previews: some View { + ConsoleLogsView() + } +} \ No newline at end of file diff --git a/StikJIT/Views/SettingsView.swift b/StikJIT/Views/SettingsView.swift index e39eb52..bcbc9bb 100644 --- a/StikJIT/Views/SettingsView.swift +++ b/StikJIT/Views/SettingsView.swift @@ -6,6 +6,9 @@ import SwiftUI import UniformTypeIdentifiers +// Add this if ConsoleLogsView is in a different module (unlikely but just in case) +// import ConsoleLogsModule + struct SettingsView: View { @AppStorage("username") private var username = "User" @AppStorage("customBackgroundColor") private var customBackgroundColorHex: String = Color.primaryBackground.toHex() ?? "#000000" @@ -23,6 +26,8 @@ struct SettingsView: View { @State private var mounted = false + @State private var showingConsoleLogsView = false + // Developer profile image URLs private let developerProfiles: [String: String] = [ "Blu": "https://github.com/0-Blu.png", @@ -361,8 +366,32 @@ struct SettingsView: View { .padding(.vertical, 20) .padding(.horizontal, 16) } + .padding(.bottom, 16) - // Version text - now outside of any card, as standalone text at the bottom + // Move System Logs section here (right after About card, before version) + SettingsCard { + Button(action: { + showingConsoleLogsView = true + }) { + HStack { + Text("System Logs") + .font(.headline) + .foregroundColor(.primary) + + Spacer() + + Image(systemName: "chevron.right") + .foregroundColor(.secondary) + } + .contentShape(Rectangle()) + .padding(.vertical, 16) + .padding(.horizontal, 16) + } + .buttonStyle(PlainButtonStyle()) + } + .padding(.bottom, 16) + + // Version info should now come after System Logs HStack { Spacer() Text("Version 1.0 • iOS \(UIDevice.current.systemVersion)") @@ -376,6 +405,11 @@ struct SettingsView: View { .padding(.horizontal, 16) .padding(.vertical, 20) } + + // Add this sheet at the end of the ZStack, before the final closing bracket + .sheet(isPresented: $showingConsoleLogsView) { + ConsoleLogsView() + } } .fileImporter( isPresented: $isShowingPairingFilePicker, @@ -655,3 +689,10 @@ struct CollaboratorRow: View { } } } + +// Define these in a separate file if they conflict +struct ConsoleLogsView_Preview: PreviewProvider { + static var previews: some View { + ConsoleLogsView() + } +} From d20eb43d06a574894785b9687c9c346d5d1ad267 Mon Sep 17 00:00:00 2001 From: neoarz Date: Sat, 29 Mar 2025 03:50:53 -0400 Subject: [PATCH 02/17] get some logs --- StikJIT.xcodeproj/project.pbxproj | 18 ++- StikJIT/Utilities/LogManager.swift | 73 +++++++++++ StikJIT/Utilities/LogManagerBridge.swift | 32 +++++ StikJIT/Views/ConsoleLogsView.swift | 158 ++++++++++++++--------- StikJIT/Views/HomeView.swift | 14 +- StikJIT/idevice/JITEnableContext.m | 12 ++ 6 files changed, 235 insertions(+), 72 deletions(-) create mode 100644 StikJIT/Utilities/LogManager.swift create mode 100644 StikJIT/Utilities/LogManagerBridge.swift diff --git a/StikJIT.xcodeproj/project.pbxproj b/StikJIT.xcodeproj/project.pbxproj index d4d4a9b..6b326e2 100644 --- a/StikJIT.xcodeproj/project.pbxproj +++ b/StikJIT.xcodeproj/project.pbxproj @@ -435,10 +435,11 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = StikJIT/StikJIT.entitlements; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"StikJIT/Preview Content\""; - DEVELOPMENT_TEAM = SZ977XLF24; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5W322N3S53; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -463,8 +464,10 @@ ); MACOSX_DEPLOYMENT_TARGET = 15.1; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.stik.StikJIT; + PRODUCT_BUNDLE_IDENTIFIER = com.stikjit.neosign; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = StikJIT; SDKROOT = auto; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -483,10 +486,11 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = StikJIT/StikJIT.entitlements; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"StikJIT/Preview Content\""; - DEVELOPMENT_TEAM = SZ977XLF24; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5W322N3S53; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -511,8 +515,10 @@ ); MACOSX_DEPLOYMENT_TARGET = 15.1; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.stik.StikJIT; + PRODUCT_BUNDLE_IDENTIFIER = com.stikjit.neosign; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = StikJIT; SDKROOT = auto; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; SWIFT_EMIT_LOC_STRINGS = YES; diff --git a/StikJIT/Utilities/LogManager.swift b/StikJIT/Utilities/LogManager.swift new file mode 100644 index 0000000..eacd36f --- /dev/null +++ b/StikJIT/Utilities/LogManager.swift @@ -0,0 +1,73 @@ +// +// LogManager.swift +// StikJIT +// +// Created by neoarz on 3/29/25. +// + +import Foundation + +class LogManager: ObservableObject { + static let shared = LogManager() + + @Published var logs: [LogEntry] = [] + @Published var errorCount: Int = 0 + + struct LogEntry: Identifiable { + let id = UUID() + let timestamp: Date + let type: LogType + let message: String + + enum LogType: String { + case info = "INFO" + case error = "ERROR" + case debug = "DEBUG" + case warning = "WARNING" + } + } + + private init() { + // Add initial system info logs + addInfoLog("StikJIT starting up") + addInfoLog("Initializing environment") + } + + func addLog(message: String, type: LogEntry.LogType) { + DispatchQueue.main.async { + self.logs.append(LogEntry(timestamp: Date(), type: type, message: message)) + + if type == .error { + self.errorCount += 1 + } + + // Keep log size manageable + if self.logs.count > 1000 { + self.logs.removeFirst(100) + } + } + } + + func addInfoLog(_ message: String) { + addLog(message: message, type: .info) + } + + func addErrorLog(_ message: String) { + addLog(message: message, type: .error) + } + + func addDebugLog(_ message: String) { + addLog(message: message, type: .debug) + } + + func addWarningLog(_ message: String) { + addLog(message: message, type: .warning) + } + + func clearLogs() { + DispatchQueue.main.async { + self.logs.removeAll() + self.errorCount = 0 + } + } +} \ No newline at end of file diff --git a/StikJIT/Utilities/LogManagerBridge.swift b/StikJIT/Utilities/LogManagerBridge.swift new file mode 100644 index 0000000..f5a2bb8 --- /dev/null +++ b/StikJIT/Utilities/LogManagerBridge.swift @@ -0,0 +1,32 @@ +// +// LogManagerBridge.swift +// StikJIT +// +// Created by neoarz on 3/29/25. +// + +import Foundation + +@objc class LogManagerBridge: NSObject { + @objc static let shared = LogManagerBridge() + + private override init() { + super.init() + } + + @objc func addInfoLog(_ message: String) { + LogManager.shared.addInfoLog(message) + } + + @objc func addErrorLog(_ message: String) { + LogManager.shared.addErrorLog(message) + } + + @objc func addDebugLog(_ message: String) { + LogManager.shared.addDebugLog(message) + } + + @objc func addWarningLog(_ message: String) { + LogManager.shared.addWarningLog(message) + } +} \ No newline at end of file diff --git a/StikJIT/Views/ConsoleLogsView.swift b/StikJIT/Views/ConsoleLogsView.swift index 618c37a..43a2f5e 100644 --- a/StikJIT/Views/ConsoleLogsView.swift +++ b/StikJIT/Views/ConsoleLogsView.swift @@ -10,17 +10,9 @@ import UIKit struct ConsoleLogsView: View { @Environment(\.dismiss) private var dismiss - @State private var dummyLogs: [String] = [ - "Initializing StikJIT environment...", - "Checking device compatibility...", - "Loading system configuration...", - "Verifying device permissions...", - "Initializing JIT compiler...", - "Loading pairing credentials...", - "Configuration loaded successfully", - "System check completed", - "Ready for operation" - ] + @StateObject private var logManager = LogManager.shared + @State private var autoScroll = true + @State private var scrollView: ScrollViewProxy? = nil var body: some View { NavigationView { @@ -30,59 +22,70 @@ struct ConsoleLogsView: View { VStack(spacing: 0) { // Terminal-style logs area - ScrollView { - VStack(spacing: 2) { - // Device Information - ForEach(["Version: \(UIDevice.current.systemVersion)", - "Name: \(UIDevice.current.name)", - "Model: \(UIDevice.current.model)", - "StikJIT: 1.0"], id: \.self) { info in - HStack { - Text("[\(timeString())]") - .foregroundColor(.blue) - .font(.system(size: 12, design: .monospaced)) - - Image(systemName: "checkmark.seal.fill") - .foregroundColor(.blue) - .font(.system(size: 10)) - - Text(info) - .font(.system(size: 12, design: .monospaced)) - .foregroundColor(.primary) - .frame(maxWidth: .infinity, alignment: .leading) + ScrollViewReader { proxy in + ScrollView { + VStack(spacing: 2) { + // Device Information + ForEach(["Version: \(UIDevice.current.systemVersion)", + "Name: \(UIDevice.current.name)", + "Model: \(UIDevice.current.model)", + "StikJIT: 1.0"], id: \.self) { info in + HStack { + Text("[\(timeString())]") + .foregroundColor(.blue) + .font(.system(size: 12, design: .monospaced)) + + Image(systemName: "checkmark.seal.fill") + .foregroundColor(.blue) + .font(.system(size: 10)) + + Text(info) + .font(.system(size: 12, design: .monospaced)) + .foregroundColor(.primary) + .frame(maxWidth: .infinity, alignment: .leading) + } + .padding(.vertical, 1) + .padding(.horizontal, 8) + } + + Divider() + .padding(.vertical, 4) + + // Real log entries + ForEach(logManager.logs) { logEntry in + HStack(alignment: .top, spacing: 8) { + Text("[\(formatTime(date: logEntry.timestamp))]") + .foregroundColor(.gray) + .font(.system(size: 11, design: .monospaced)) + + Text("[\(logEntry.type.rawValue)]") + .foregroundColor(colorForLogType(logEntry.type)) + .font(.system(size: 11, design: .monospaced)) + + Text(logEntry.message) + .font(.system(size: 11, design: .monospaced)) + .foregroundColor(.primary) + .frame(maxWidth: .infinity, alignment: .leading) + } + .padding(.vertical, 1) + .padding(.horizontal, 8) + .id(logEntry.id) } - .padding(.vertical, 1) - .padding(.horizontal, 8) } - - Divider() - .padding(.vertical, 4) - - // Log entries - ForEach(dummyLogs.indices, id: \.self) { index in - HStack(alignment: .top, spacing: 8) { - Text("[\(timeString(minutesAgo: dummyLogs.count - index))]") - .foregroundColor(.gray) - .font(.system(size: 11, design: .monospaced)) - - Text("[INFO]") - .foregroundColor(.green) - .font(.system(size: 11, design: .monospaced)) - - Text(dummyLogs[index]) - .font(.system(size: 11, design: .monospaced)) - .foregroundColor(.primary) - .frame(maxWidth: .infinity, alignment: .leading) - } - .padding(.vertical, 1) - .padding(.horizontal, 8) + .padding(.vertical, 8) + .background(Color(UIColor.secondarySystemBackground)) + .cornerRadius(8) + .padding(.horizontal, 8) + .padding(.top, 8) + } + .onAppear { + scrollView = proxy + } + .onChange(of: logManager.logs.count) { + if autoScroll, let lastLog = logManager.logs.last { + proxy.scrollTo(lastLog.id, anchor: .bottom) } } - .padding(.vertical, 8) - .background(Color(UIColor.secondarySystemBackground)) - .cornerRadius(8) - .padding(.horizontal, 8) - .padding(.top, 8) } Spacer() @@ -91,13 +94,13 @@ struct ConsoleLogsView: View { VStack(spacing: 16) { // Error count HStack { - Text("0 Critical Errors.") + Text("\(logManager.errorCount) Critical Errors.") .font(.headline) .foregroundColor(.white) .padding(.vertical, 10) .padding(.horizontal, 20) .frame(maxWidth: .infinity) - .background(Color.red) + .background(logManager.errorCount > 0 ? Color.red : Color.green) .cornerRadius(8) } .padding(.horizontal) @@ -106,7 +109,7 @@ struct ConsoleLogsView: View { VStack(spacing: 1) { // Share button Button(action: { - let logs = dummyLogs.map { "[\(timeString())] [INFO] \($0)" }.joined(separator: "\n") + let logs = logManager.logs.map { "[\(formatTime(date: $0.timestamp))] [\($0.type.rawValue)] \($0.message)" }.joined(separator: "\n") let activityVC = UIActivityViewController(activityItems: [logs], applicationActivities: nil) guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, @@ -132,7 +135,7 @@ struct ConsoleLogsView: View { // Copy button Button(action: { - let logs = dummyLogs.map { "[\(timeString())] [INFO] \($0)" }.joined(separator: "\n") + let logs = logManager.logs.map { "[\(formatTime(date: $0.timestamp))] [\($0.type.rawValue)] \($0.message)" }.joined(separator: "\n") UIPasteboard.general.string = logs }) { HStack { @@ -167,6 +170,12 @@ struct ConsoleLogsView: View { .fontWeight(.regular) } .foregroundColor(.blue) + }, + trailing: Button(action: { + logManager.clearLogs() + }) { + Text("Clear") + .foregroundColor(.blue) } ) } @@ -179,6 +188,13 @@ struct ConsoleLogsView: View { return formatter.string(from: Date()) } + // Helper to format Date objects to time strings + private func formatTime(date: Date) -> String { + let formatter = DateFormatter() + formatter.dateFormat = "HH:mm:ss" + return formatter.string(from: date) + } + // Helper to display time with offset for log display private func timeString(minutesAgo: Int) -> String { let formatter = DateFormatter() @@ -186,6 +202,20 @@ struct ConsoleLogsView: View { let date = Calendar.current.date(byAdding: .minute, value: -minutesAgo, to: Date()) ?? Date() return formatter.string(from: date) } + + // Return color based on log type + private func colorForLogType(_ type: LogManager.LogEntry.LogType) -> Color { + switch type { + case .info: + return .green + case .error: + return .red + case .debug: + return .blue + case .warning: + return .orange + } + } } // Preview provider diff --git a/StikJIT/Views/HomeView.swift b/StikJIT/Views/HomeView.swift index 13ef8c4..7ec0695 100644 --- a/StikJIT/Views/HomeView.swift +++ b/StikJIT/Views/HomeView.swift @@ -259,11 +259,21 @@ struct HomeView: View { private func startJITInBackground(with bundleID: String) { isProcessing = true + + // Add log message + LogManager.shared.addInfoLog("Starting JIT for \(bundleID)") + DispatchQueue.global(qos: .background).async { - - JITEnableContext.shared().debugApp(withBundleID: bundleID, logger: nil) + JITEnableContext.shared().debugApp(withBundleID: bundleID, logger: { message in + // Safely unwrap the optional message + if let message = message { + // Log messages from the JIT process + LogManager.shared.addInfoLog(message) + } + }) DispatchQueue.main.async { + LogManager.shared.addInfoLog("JIT process completed for \(bundleID)") isProcessing = false } } diff --git a/StikJIT/idevice/JITEnableContext.m b/StikJIT/idevice/JITEnableContext.m index 83e985f..c20ac94 100644 --- a/StikJIT/idevice/JITEnableContext.m +++ b/StikJIT/idevice/JITEnableContext.m @@ -13,6 +13,7 @@ #include "applist.h" #include "JITEnableContext.h" +#import "StikJIT-Swift.h" // This imports the Swift files into Objective-C JITEnableContext* sharedJITContext = nil; @@ -41,6 +42,17 @@ JITEnableContext* sharedJITContext = nil; NSString *message = [[NSString alloc] initWithFormat:formatStr arguments:args]; NSLog(@"%@", message); + // Add to log manager + if ([message containsString:@"ERROR"] || [message containsString:@"Error"]) { + [[LogManagerBridge shared] addErrorLog:message]; + } else if ([message containsString:@"WARNING"] || [message containsString:@"Warning"]) { + [[LogManagerBridge shared] addWarningLog:message]; + } else if ([message containsString:@"DEBUG"]) { + [[LogManagerBridge shared] addDebugLog:message]; + } else { + [[LogManagerBridge shared] addInfoLog:message]; + } + if(logger) { logger(message); } From 503a96601d01088a02d99e93691c263b2766a1b3 Mon Sep 17 00:00:00 2001 From: neoarz Date: Sat, 29 Mar 2025 04:02:54 -0400 Subject: [PATCH 03/17] Fix ui again --- StikJIT/Views/ConsoleLogsView.swift | 101 +++++++++++++++------------- 1 file changed, 54 insertions(+), 47 deletions(-) diff --git a/StikJIT/Views/ConsoleLogsView.swift b/StikJIT/Views/ConsoleLogsView.swift index 43a2f5e..a608ba0 100644 --- a/StikJIT/Views/ConsoleLogsView.swift +++ b/StikJIT/Views/ConsoleLogsView.swift @@ -17,43 +17,42 @@ struct ConsoleLogsView: View { var body: some View { NavigationView { ZStack { - Color(UIColor.systemBackground) + Color.black .edgesIgnoringSafeArea(.all) VStack(spacing: 0) { // Terminal-style logs area ScrollViewReader { proxy in ScrollView { - VStack(spacing: 2) { + VStack(spacing: 0) { // Device Information ForEach(["Version: \(UIDevice.current.systemVersion)", "Name: \(UIDevice.current.name)", "Model: \(UIDevice.current.model)", - "StikJIT: 1.0"], id: \.self) { info in + "StikJIT Version: App Version: 1.0"], id: \.self) { info in HStack { Text("[\(timeString())]") .foregroundColor(.blue) - .font(.system(size: 12, design: .monospaced)) + .font(.system(size: 11, design: .monospaced)) Image(systemName: "checkmark.seal.fill") .foregroundColor(.blue) .font(.system(size: 10)) Text(info) - .font(.system(size: 12, design: .monospaced)) - .foregroundColor(.primary) - .frame(maxWidth: .infinity, alignment: .leading) + .font(.system(size: 11, design: .monospaced)) + .foregroundColor(.white) } - .padding(.vertical, 1) - .padding(.horizontal, 8) + .padding(.vertical, 2) + .padding(.horizontal, 10) + .frame(maxWidth: .infinity, alignment: .leading) } - Divider() - .padding(.vertical, 4) + Spacer() - // Real log entries + // Log entries would appear here ForEach(logManager.logs) { logEntry in - HStack(alignment: .top, spacing: 8) { + HStack(alignment: .top, spacing: 4) { Text("[\(formatTime(date: logEntry.timestamp))]") .foregroundColor(.gray) .font(.system(size: 11, design: .monospaced)) @@ -64,19 +63,16 @@ struct ConsoleLogsView: View { Text(logEntry.message) .font(.system(size: 11, design: .monospaced)) - .foregroundColor(.primary) - .frame(maxWidth: .infinity, alignment: .leading) + .foregroundColor(.white) + .fixedSize(horizontal: false, vertical: true) + .lineLimit(nil) } .padding(.vertical, 1) - .padding(.horizontal, 8) + .padding(.horizontal, 10) + .frame(maxWidth: .infinity, alignment: .leading) .id(logEntry.id) } } - .padding(.vertical, 8) - .background(Color(UIColor.secondarySystemBackground)) - .cornerRadius(8) - .padding(.horizontal, 8) - .padding(.top, 8) } .onAppear { scrollView = proxy @@ -92,43 +88,63 @@ struct ConsoleLogsView: View { // Bottom section with error count and action buttons VStack(spacing: 16) { - // Error count + // Error count with blue theme HStack { Text("\(logManager.errorCount) Critical Errors.") .font(.headline) .foregroundColor(.white) - .padding(.vertical, 10) - .padding(.horizontal, 20) + .padding(.vertical, 12) .frame(maxWidth: .infinity) - .background(logManager.errorCount > 0 ? Color.red : Color.green) - .cornerRadius(8) + .background(Color.blue) + .cornerRadius(10) } .padding(.horizontal) - // Action buttons + // Action buttons with dark background VStack(spacing: 1) { // Share button Button(action: { let logs = logManager.logs.map { "[\(formatTime(date: $0.timestamp))] [\($0.type.rawValue)] \($0.message)" }.joined(separator: "\n") - let activityVC = UIActivityViewController(activityItems: [logs], applicationActivities: nil) - guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, - let rootVC = windowScene.windows.first?.rootViewController else { return } - rootVC.present(activityVC, animated: true) + // Create a temporary file for the logs + let tempDirectoryURL = FileManager.default.temporaryDirectory + let tempFileURL = tempDirectoryURL.appendingPathComponent("StikJIT_Logs_\(Date().timeIntervalSince1970).txt") + + do { + try logs.write(to: tempFileURL, atomically: true, encoding: .utf8) + + // Share the file instead of just the text + let activityVC = UIActivityViewController(activityItems: [tempFileURL], applicationActivities: nil) + + // Present the view controller + if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, + let rootVC = windowScene.windows.first?.rootViewController { + + // For iPad, we need to specify the source view and source rect + if let popoverController = activityVC.popoverPresentationController { + popoverController.sourceView = rootVC.view + popoverController.sourceRect = CGRect(x: UIScreen.main.bounds.width / 2, y: UIScreen.main.bounds.height / 2, width: 0, height: 0) + popoverController.permittedArrowDirections = [] + } + + rootVC.present(activityVC, animated: true) + } + } catch { + print("Error writing logs to file: \(error)") + } }) { HStack { Text("Share Logs") .foregroundColor(.blue) - .padding(.leading, 2) Spacer() Image(systemName: "square.and.arrow.up") - .foregroundColor(.secondary) + .foregroundColor(.gray) } .padding(.vertical, 14) .padding(.horizontal, 20) .contentShape(Rectangle()) } - .background(Color.black.opacity(0.05)) + .background(Color(red: 0.1, green: 0.1, blue: 0.1)) Divider() .background(Color.gray.opacity(0.3)) @@ -141,20 +157,19 @@ struct ConsoleLogsView: View { HStack { Text("Copy Logs") .foregroundColor(.blue) - .padding(.leading, 2) Spacer() Image(systemName: "arrow.right") - .foregroundColor(.secondary) + .foregroundColor(.gray) } .padding(.vertical, 14) .padding(.horizontal, 20) .contentShape(Rectangle()) } - .background(Color.black.opacity(0.05)) + .background(Color(red: 0.1, green: 0.1, blue: 0.1)) } - .cornerRadius(8) + .cornerRadius(10) .padding(.horizontal) - .padding(.bottom, 16) + .padding(.bottom, 20) } } } @@ -195,14 +210,6 @@ struct ConsoleLogsView: View { return formatter.string(from: date) } - // Helper to display time with offset for log display - private func timeString(minutesAgo: Int) -> String { - let formatter = DateFormatter() - formatter.dateFormat = "HH:mm:ss" - let date = Calendar.current.date(byAdding: .minute, value: -minutesAgo, to: Date()) ?? Date() - return formatter.string(from: date) - } - // Return color based on log type private func colorForLogType(_ type: LogManager.LogEntry.LogType) -> Color { switch type { From 1425a3a2197a20629d5971929a4abebf5be51715 Mon Sep 17 00:00:00 2001 From: neoarz Date: Sat, 29 Mar 2025 05:03:47 -0400 Subject: [PATCH 04/17] pbx --- StikJIT.xcodeproj/project.pbxproj | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/StikJIT.xcodeproj/project.pbxproj b/StikJIT.xcodeproj/project.pbxproj index 6b326e2..c17ccb1 100644 --- a/StikJIT.xcodeproj/project.pbxproj +++ b/StikJIT.xcodeproj/project.pbxproj @@ -435,11 +435,10 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = StikJIT/StikJIT.entitlements; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"StikJIT/Preview Content\""; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5W322N3S53; + DEVELOPMENT_TEAM = SZ977XLF24; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -464,10 +463,8 @@ ); MACOSX_DEPLOYMENT_TARGET = 15.1; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.stikjit.neosign; + PRODUCT_BUNDLE_IDENTIFIER = com.stik.StikJIT; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = StikJIT; SDKROOT = auto; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -486,11 +483,10 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = StikJIT/StikJIT.entitlements; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"StikJIT/Preview Content\""; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5W322N3S53; + DEVELOPMENT_TEAM = SZ977XLF24; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -515,10 +511,8 @@ ); MACOSX_DEPLOYMENT_TARGET = 15.1; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.stikjit.neosign; + PRODUCT_BUNDLE_IDENTIFIER = com.stik.StikJIT; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = StikJIT; SDKROOT = auto; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -661,4 +655,4 @@ /* End XCConfigurationList section */ }; rootObject = DC6F1D2F2D94EADD0071B2B6 /* Project object */; -} +} \ No newline at end of file From 1539e1331e5ff883cc9a083c8108c6fa57400d2d Mon Sep 17 00:00:00 2001 From: neoarz Date: Sat, 29 Mar 2025 05:03:55 -0400 Subject: [PATCH 05/17] log manager --- StikJIT/Utilities/LogManager.swift | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/StikJIT/Utilities/LogManager.swift b/StikJIT/Utilities/LogManager.swift index eacd36f..160abca 100644 --- a/StikJIT/Utilities/LogManager.swift +++ b/StikJIT/Utilities/LogManager.swift @@ -34,8 +34,26 @@ class LogManager: ObservableObject { } func addLog(message: String, type: LogEntry.LogType) { + // Remove redundant prefixes from the message + var cleanMessage = message + + // Clean up common prefixes that match the log type + let prefixesToRemove = [ + "Info: ", "INFO: ", "Information: ", + "Error: ", "ERROR: ", "ERR: ", + "Debug: ", "DEBUG: ", "DBG: ", + "Warning: ", "WARN: ", "WARNING: " + ] + + for prefix in prefixesToRemove { + if cleanMessage.hasPrefix(prefix) { + cleanMessage = String(cleanMessage.dropFirst(prefix.count)) + break + } + } + DispatchQueue.main.async { - self.logs.append(LogEntry(timestamp: Date(), type: type, message: message)) + self.logs.append(LogEntry(timestamp: Date(), type: type, message: cleanMessage)) if type == .error { self.errorCount += 1 From 59221a2e16ea447bb25ab16a5bd02eb10a1334bf Mon Sep 17 00:00:00 2001 From: neoarz Date: Sat, 29 Mar 2025 05:08:24 -0400 Subject: [PATCH 06/17] ui finished --- StikJIT/Views/ConsoleLogsView.swift | 140 +++++++++++++++++----------- 1 file changed, 83 insertions(+), 57 deletions(-) diff --git a/StikJIT/Views/ConsoleLogsView.swift b/StikJIT/Views/ConsoleLogsView.swift index a608ba0..6fdd331 100644 --- a/StikJIT/Views/ConsoleLogsView.swift +++ b/StikJIT/Views/ConsoleLogsView.swift @@ -30,47 +30,27 @@ struct ConsoleLogsView: View { "Name: \(UIDevice.current.name)", "Model: \(UIDevice.current.model)", "StikJIT Version: App Version: 1.0"], id: \.self) { info in - HStack { - Text("[\(timeString())]") - .foregroundColor(.blue) - .font(.system(size: 11, design: .monospaced)) - - Image(systemName: "checkmark.seal.fill") - .foregroundColor(.blue) - .font(.system(size: 10)) - - Text(info) - .font(.system(size: 11, design: .monospaced)) - .foregroundColor(.white) - } - .padding(.vertical, 2) - .padding(.horizontal, 10) - .frame(maxWidth: .infinity, alignment: .leading) + Text("[\(timeString())] ℹ️ \(info)") + .font(.system(size: 11, design: .monospaced)) + .foregroundColor(.white) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.vertical, 2) + .padding(.horizontal, 4) } Spacer() - // Log entries would appear here + // Log entries with terminal-style alignment (no indentation on wrapped lines) ForEach(logManager.logs) { logEntry in - HStack(alignment: .top, spacing: 4) { - Text("[\(formatTime(date: logEntry.timestamp))]") - .foregroundColor(.gray) - .font(.system(size: 11, design: .monospaced)) - - Text("[\(logEntry.type.rawValue)]") - .foregroundColor(colorForLogType(logEntry.type)) - .font(.system(size: 11, design: .monospaced)) - - Text(logEntry.message) - .font(.system(size: 11, design: .monospaced)) - .foregroundColor(.white) - .fixedSize(horizontal: false, vertical: true) - .lineLimit(nil) - } - .padding(.vertical, 1) - .padding(.horizontal, 10) - .frame(maxWidth: .infinity, alignment: .leading) - .id(logEntry.id) + Text(AttributedString(createLogAttributedString(logEntry))) + .font(.system(size: 11, design: .monospaced)) + .textSelection(.enabled) + .lineLimit(nil) + .fixedSize(horizontal: false, vertical: true) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.vertical, 1) + .padding(.horizontal, 4) + .id(logEntry.id) } } } @@ -88,14 +68,14 @@ struct ConsoleLogsView: View { // Bottom section with error count and action buttons VStack(spacing: 16) { - // Error count with blue theme + // Error count with red theme HStack { Text("\(logManager.errorCount) Critical Errors.") .font(.headline) .foregroundColor(.white) .padding(.vertical, 12) .frame(maxWidth: .infinity) - .background(Color.blue) + .background(Color.red) .cornerRadius(10) } .padding(.horizontal) @@ -173,27 +153,73 @@ struct ConsoleLogsView: View { } } } - .navigationTitle("Console Logs") - .navigationBarItems( - leading: Button(action: { - dismiss() - }) { - HStack(spacing: 2) { - Image(systemName: "chevron.left") - .font(.system(size: 16, weight: .semibold)) - Text("Settings") - .fontWeight(.regular) - } - .foregroundColor(.blue) - }, - trailing: Button(action: { - logManager.clearLogs() - }) { - Text("Clear") - .foregroundColor(.blue) + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .principal) { + Text("Console Logs") + .font(.headline) + .foregroundColor(.white) } - ) + + ToolbarItem(placement: .navigationBarLeading) { + Button(action: { + dismiss() + }) { + HStack(spacing: 2) { + Image(systemName: "chevron.left") + .font(.system(size: 16, weight: .semibold)) + Text("Settings") + .fontWeight(.regular) + } + .foregroundColor(.blue) + } + } + + ToolbarItem(placement: .navigationBarTrailing) { + Button(action: { + logManager.clearLogs() + }) { + Text("Clear") + .foregroundColor(.blue) + } + } + } } + .navigationViewStyle(StackNavigationViewStyle()) + } + + // Creates an NSAttributedString that combines timestamp, type, and message + // with proper styling for each component + private func createLogAttributedString(_ logEntry: LogManager.LogEntry) -> NSAttributedString { + let fullString = NSMutableAttributedString() + + // Timestamp part + let timestampString = "[\(formatTime(date: logEntry.timestamp))]" + let timestampAttr = NSAttributedString( + string: timestampString, + attributes: [.foregroundColor: UIColor.gray] + ) + fullString.append(timestampAttr) + fullString.append(NSAttributedString(string: " ")) + + // Log type part + let typeString = "[\(logEntry.type.rawValue)]" + let typeColor = UIColor(colorForLogType(logEntry.type)) + let typeAttr = NSAttributedString( + string: typeString, + attributes: [.foregroundColor: typeColor] + ) + fullString.append(typeAttr) + fullString.append(NSAttributedString(string: " ")) + + // Message part + let messageAttr = NSAttributedString( + string: logEntry.message, + attributes: [.foregroundColor: UIColor.white] + ) + fullString.append(messageAttr) + + return fullString } // Helper to display current time From ef7593748299d2c7600a25d7cd761196e7c0eac3 Mon Sep 17 00:00:00 2001 From: neoarz <164915254+neoarz@users.noreply.github.com> Date: Sat, 29 Mar 2025 11:13:50 -0400 Subject: [PATCH 07/17] Update LogManager.swift --- StikJIT/Utilities/LogManager.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/StikJIT/Utilities/LogManager.swift b/StikJIT/Utilities/LogManager.swift index 160abca..6b72983 100644 --- a/StikJIT/Utilities/LogManager.swift +++ b/StikJIT/Utilities/LogManager.swift @@ -34,7 +34,7 @@ class LogManager: ObservableObject { } func addLog(message: String, type: LogEntry.LogType) { - // Remove redundant prefixes from the message + //clean dumb stuff var cleanMessage = message // Clean up common prefixes that match the log type @@ -88,4 +88,4 @@ class LogManager: ObservableObject { self.errorCount = 0 } } -} \ No newline at end of file +} From 5f3af47f96c51fc3212e1217ffc14b1a2e173c07 Mon Sep 17 00:00:00 2001 From: neoarz <164915254+neoarz@users.noreply.github.com> Date: Sat, 29 Mar 2025 11:14:54 -0400 Subject: [PATCH 08/17] Update LogManagerBridge.swift --- StikJIT/Utilities/LogManagerBridge.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/StikJIT/Utilities/LogManagerBridge.swift b/StikJIT/Utilities/LogManagerBridge.swift index f5a2bb8..9a8528e 100644 --- a/StikJIT/Utilities/LogManagerBridge.swift +++ b/StikJIT/Utilities/LogManagerBridge.swift @@ -6,7 +6,7 @@ // import Foundation - +//objc bridge for logs @objc class LogManagerBridge: NSObject { @objc static let shared = LogManagerBridge() @@ -29,4 +29,4 @@ import Foundation @objc func addWarningLog(_ message: String) { LogManager.shared.addWarningLog(message) } -} \ No newline at end of file +} From 5f99c5cc32d6998e71795a662819b50521620e29 Mon Sep 17 00:00:00 2001 From: neoarz <164915254+neoarz@users.noreply.github.com> Date: Sat, 29 Mar 2025 11:16:19 -0400 Subject: [PATCH 09/17] Update ConsoleLogsView.swift --- StikJIT/Views/ConsoleLogsView.swift | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/StikJIT/Views/ConsoleLogsView.swift b/StikJIT/Views/ConsoleLogsView.swift index 6fdd331..fe7d123 100644 --- a/StikJIT/Views/ConsoleLogsView.swift +++ b/StikJIT/Views/ConsoleLogsView.swift @@ -21,11 +21,11 @@ struct ConsoleLogsView: View { .edgesIgnoringSafeArea(.all) VStack(spacing: 0) { - // Terminal-style logs area + // Terminal logs area (made it look somewhat like feathers implementation) ScrollViewReader { proxy in ScrollView { VStack(spacing: 0) { - // Device Information + // Device Information (all thw way on top) ForEach(["Version: \(UIDevice.current.systemVersion)", "Name: \(UIDevice.current.name)", "Model: \(UIDevice.current.model)", @@ -40,7 +40,7 @@ struct ConsoleLogsView: View { Spacer() - // Log entries with terminal-style alignment (no indentation on wrapped lines) + // Log entries ForEach(logManager.logs) { logEntry in Text(AttributedString(createLogAttributedString(logEntry))) .font(.system(size: 11, design: .monospaced)) @@ -66,7 +66,7 @@ struct ConsoleLogsView: View { Spacer() - // Bottom section with error count and action buttons + VStack(spacing: 16) { // Error count with red theme HStack { @@ -82,7 +82,7 @@ struct ConsoleLogsView: View { // Action buttons with dark background VStack(spacing: 1) { - // Share button + Button(action: { let logs = logManager.logs.map { "[\(formatTime(date: $0.timestamp))] [\($0.type.rawValue)] \($0.message)" }.joined(separator: "\n") @@ -188,8 +188,7 @@ struct ConsoleLogsView: View { .navigationViewStyle(StackNavigationViewStyle()) } - // Creates an NSAttributedString that combines timestamp, type, and message - // with proper styling for each component + private func createLogAttributedString(_ logEntry: LogManager.LogEntry) -> NSAttributedString { let fullString = NSMutableAttributedString() @@ -251,9 +250,9 @@ struct ConsoleLogsView: View { } } -// Preview provider + struct ConsoleLogsView_Previews: PreviewProvider { static var previews: some View { ConsoleLogsView() } -} \ No newline at end of file +} From 3c8cb48b858410e2addf335fb23a2b97149089b5 Mon Sep 17 00:00:00 2001 From: neoarz Date: Sat, 29 Mar 2025 11:40:35 -0400 Subject: [PATCH 10/17] fix sharing logs errors --- StikJIT/Views/ConsoleLogsView.swift | 105 ++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 30 deletions(-) diff --git a/StikJIT/Views/ConsoleLogsView.swift b/StikJIT/Views/ConsoleLogsView.swift index fe7d123..0659fc2 100644 --- a/StikJIT/Views/ConsoleLogsView.swift +++ b/StikJIT/Views/ConsoleLogsView.swift @@ -14,6 +14,13 @@ struct ConsoleLogsView: View { @State private var autoScroll = true @State private var scrollView: ScrollViewProxy? = nil + // Add these state variables for alert handling + @State private var showingExportAlert = false + @State private var showingCopyAlert = false + @State private var alertMessage = "" + @State private var alertTitle = "" + @State private var isError = false + var body: some View { NavigationView { ZStack { @@ -82,42 +89,50 @@ struct ConsoleLogsView: View { // Action buttons with dark background VStack(spacing: 1) { - + // Export button Button(action: { - let logs = logManager.logs.map { "[\(formatTime(date: $0.timestamp))] [\($0.type.rawValue)] \($0.message)" }.joined(separator: "\n") + // Create logs content with device information + var logsContent = "=== DEVICE INFORMATION ===\n" + logsContent += "Version: \(UIDevice.current.systemVersion)\n" + logsContent += "Name: \(UIDevice.current.name)\n" + logsContent += "Model: \(UIDevice.current.model)\n" + logsContent += "StikJIT Version: App Version: 1.0\n\n" + logsContent += "=== LOG ENTRIES ===\n" - // Create a temporary file for the logs - let tempDirectoryURL = FileManager.default.temporaryDirectory - let tempFileURL = tempDirectoryURL.appendingPathComponent("StikJIT_Logs_\(Date().timeIntervalSince1970).txt") + // Add all log entries with proper formatting + logsContent += logManager.logs.map { + "[\(formatTime(date: $0.timestamp))] [\($0.type.rawValue)] \($0.message)" + }.joined(separator: "\n") + + // Save to document directory (accessible in Files app) + let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd_HH-mm-ss" + let timestamp = dateFormatter.string(from: Date()) + let fileURL = documentsDirectory.appendingPathComponent("StikJIT_Logs_\(timestamp).txt") do { - try logs.write(to: tempFileURL, atomically: true, encoding: .utf8) + // Write the logs to the file + try logsContent.write(to: fileURL, atomically: true, encoding: .utf8) - // Share the file instead of just the text - let activityVC = UIActivityViewController(activityItems: [tempFileURL], applicationActivities: nil) - - // Present the view controller - if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, - let rootVC = windowScene.windows.first?.rootViewController { - - // For iPad, we need to specify the source view and source rect - if let popoverController = activityVC.popoverPresentationController { - popoverController.sourceView = rootVC.view - popoverController.sourceRect = CGRect(x: UIScreen.main.bounds.width / 2, y: UIScreen.main.bounds.height / 2, width: 0, height: 0) - popoverController.permittedArrowDirections = [] - } - - rootVC.present(activityVC, animated: true) - } + // Set alert variables and show the alert + alertTitle = "Logs Exported" + alertMessage = "Logs have been saved to Files app in StikJIT folder." + isError = false + showingExportAlert = true } catch { - print("Error writing logs to file: \(error)") + // Set error alert variables and show the alert + alertTitle = "Export Failed" + alertMessage = "Failed to save logs: \(error.localizedDescription)" + isError = true + showingExportAlert = true } }) { HStack { - Text("Share Logs") + Text("Export Logs") .foregroundColor(.blue) Spacer() - Image(systemName: "square.and.arrow.up") + Image(systemName: "square.and.arrow.down") .foregroundColor(.gray) } .padding(.vertical, 14) @@ -127,18 +142,37 @@ struct ConsoleLogsView: View { .background(Color(red: 0.1, green: 0.1, blue: 0.1)) Divider() - .background(Color.gray.opacity(0.3)) + .background(Color(red: 0.15, green: 0.15, blue: 0.15)) // Copy button Button(action: { - let logs = logManager.logs.map { "[\(formatTime(date: $0.timestamp))] [\($0.type.rawValue)] \($0.message)" }.joined(separator: "\n") - UIPasteboard.general.string = logs + // Create logs content with device information + var logsContent = "=== DEVICE INFORMATION ===\n" + logsContent += "Version: \(UIDevice.current.systemVersion)\n" + logsContent += "Name: \(UIDevice.current.name)\n" + logsContent += "Model: \(UIDevice.current.model)\n" + logsContent += "StikJIT Version: App Version: 1.0\n\n" + logsContent += "=== LOG ENTRIES ===\n" + + // Add all log entries with proper formatting + logsContent += logManager.logs.map { + "[\(formatTime(date: $0.timestamp))] [\($0.type.rawValue)] \($0.message)" + }.joined(separator: "\n") + + // Copy to clipboard + UIPasteboard.general.string = logsContent + + // Show success alert using SwiftUI alert + alertTitle = "Logs Copied" + alertMessage = "Logs have been copied to clipboard." + isError = false + showingCopyAlert = true }) { HStack { Text("Copy Logs") .foregroundColor(.blue) Spacer() - Image(systemName: "arrow.right") + Image(systemName: "doc.on.doc") .foregroundColor(.gray) } .padding(.vertical, 14) @@ -186,9 +220,20 @@ struct ConsoleLogsView: View { } } .navigationViewStyle(StackNavigationViewStyle()) + .alert(alertTitle, isPresented: $showingExportAlert) { + Button("OK", role: .cancel) { } + } message: { + Text(alertMessage) + } + .alert(alertTitle, isPresented: $showingCopyAlert) { + Button("OK", role: .cancel) { } + } message: { + Text(alertMessage) + } } - + // Creates an NSAttributedString that combines timestamp, type, and message + // with proper styling for each component private func createLogAttributedString(_ logEntry: LogManager.LogEntry) -> NSAttributedString { let fullString = NSMutableAttributedString() From d6a9e190c20776df5c2b90a62492bba8469dac24 Mon Sep 17 00:00:00 2001 From: neoarz Date: Sat, 29 Mar 2025 11:50:47 -0400 Subject: [PATCH 11/17] Add rust logs --- StikJIT/Utilities/LogManager.swift | 157 ++++++++++++++++++++++++++++ StikJIT/Views/ConsoleLogsView.swift | 2 +- 2 files changed, 158 insertions(+), 1 deletion(-) diff --git a/StikJIT/Utilities/LogManager.swift b/StikJIT/Utilities/LogManager.swift index 6b72983..eeddc89 100644 --- a/StikJIT/Utilities/LogManager.swift +++ b/StikJIT/Utilities/LogManager.swift @@ -6,6 +6,7 @@ // import Foundation +import os.log class LogManager: ObservableObject { static let shared = LogManager() @@ -13,6 +14,13 @@ class LogManager: ObservableObject { @Published var logs: [LogEntry] = [] @Published var errorCount: Int = 0 + // Add properties to capture stdout/stderr + private var stdoutPipe: Pipe? + private var stderrPipe: Pipe? + private var originalStdout: Int32 = -1 + private var originalStderr: Int32 = -1 + private let logQueue = DispatchQueue(label: "com.stikjit.logQueue") + struct LogEntry: Identifiable { let id = UUID() let timestamp: Date @@ -31,6 +39,155 @@ class LogManager: ObservableObject { // Add initial system info logs addInfoLog("StikJIT starting up") addInfoLog("Initializing environment") + + // Set up stdout and stderr capture + captureStandardOutput() + + // Register for system log notifications + #if os(macOS) + // On macOS, also listen for system log messages + setupMacOSLogCapture() + #endif + } + + #if os(macOS) + private func setupMacOSLogCapture() { + // On macOS we can use the OSLog system + // This is a placeholder for macOS-specific log capture + // Start a background task to read system logs + DispatchQueue.global(qos: .background).async { + self.captureSystemLogs() + } + } + + private func captureSystemLogs() { + // This is a basic implementation to capture macOS logs + // A more comprehensive solution would use the OSLog framework + let task = Process() + let pipe = Pipe() + + task.executableURL = URL(fileURLWithPath: "/usr/bin/log") + task.arguments = ["stream", "--style", "compact"] + task.standardOutput = pipe + + pipe.fileHandleForReading.readabilityHandler = { [weak self] handle in + let data = handle.availableData + if let string = String(data: data, encoding: .utf8), !string.isEmpty { + self?.processStandardOutputLine(string, isError: false) + } + } + + do { + try task.run() + } catch { + self.addErrorLog("Failed to capture system logs: \(error.localizedDescription)") + } + } + #endif + + // Function to capture standard output and standard error + private func captureStandardOutput() { + #if DEBUG && targetEnvironment(simulator) + // Skip capturing in simulator debug builds to ensure logs appear in Xcode console + return + #endif + + // Save original file descriptors safely + if FileHandle.standardOutput.fileDescriptor >= 0 { + originalStdout = dup(FileHandle.standardOutput.fileDescriptor) + } + if FileHandle.standardError.fileDescriptor >= 0 { + originalStderr = dup(FileHandle.standardError.fileDescriptor) + } + + // Create pipes + stdoutPipe = Pipe() + stderrPipe = Pipe() + + // Redirect stdout and stderr to our pipes only if valid + if let stdoutPipe = stdoutPipe, FileHandle.standardOutput.fileDescriptor >= 0 { + dup2(stdoutPipe.fileHandleForWriting.fileDescriptor, FileHandle.standardOutput.fileDescriptor) + } + if let stderrPipe = stderrPipe, FileHandle.standardError.fileDescriptor >= 0 { + dup2(stderrPipe.fileHandleForWriting.fileDescriptor, FileHandle.standardError.fileDescriptor) + } + + // Start reading from the pipes on a background queue to avoid blocking + stdoutPipe?.fileHandleForReading.readabilityHandler = { [weak self] handle in + let data = handle.availableData + if !data.isEmpty, let string = String(data: data, encoding: .utf8) { + // Write back to original stdout for console viewing + if let strongSelf = self, strongSelf.originalStdout >= 0 { + write(strongSelf.originalStdout, string, string.utf8.count) + } + + self?.logQueue.async { + self?.processStandardOutputLine(string, isError: false) + } + } + } + + stderrPipe?.fileHandleForReading.readabilityHandler = { [weak self] handle in + let data = handle.availableData + if !data.isEmpty, let string = String(data: data, encoding: .utf8) { + // Write back to original stderr for console viewing + if let strongSelf = self, strongSelf.originalStderr >= 0 { + write(strongSelf.originalStderr, string, string.utf8.count) + } + + self?.logQueue.async { + self?.processStandardOutputLine(string, isError: true) + } + } + } + + // Also set up a timer to periodically flush stdout/stderr + Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] _ in + self?.flushPipes() + } + } + + private func flushPipes() { + // Force flush the pipes to ensure all output is captured + fflush(stdout) + fflush(stderr) + } + + // Process standard output/error lines and add to logs + private func processStandardOutputLine(_ line: String, isError: Bool) { + // Split multi-line output + let lines = line.components(separatedBy: .newlines) + + for line in lines where !line.isEmpty { + // Determine log type based on content + let type: LogEntry.LogType + + // Check for error indicators + if line.contains("[ERROR]") || line.contains("Error:") || line.contains("error:") || + line.contains("ERROR:") || line.contains("Failed") || (isError && !line.contains("DEBUG")) { + type = .error + } + // Check for warning indicators + else if line.contains("[WARNING]") || line.contains("Warning:") || line.contains("warning:") || + line.contains("WARN:") || line.contains("WARNING:") { + type = .warning + } + // Check for debug indicators + else if line.contains("[DEBUG]") || line.contains("DEBUG:") || line.contains("debug:") { + type = .debug + } + // Check for info indicators + else if line.contains("[INFO]") || line.contains("INFO:") || line.contains("info:") { + type = .info + } + // Default to info for anything else + else { + type = isError ? .error : .info + } + + // Add to logs + addLog(message: line, type: type) + } } func addLog(message: String, type: LogEntry.LogType) { diff --git a/StikJIT/Views/ConsoleLogsView.swift b/StikJIT/Views/ConsoleLogsView.swift index 0659fc2..ee8329b 100644 --- a/StikJIT/Views/ConsoleLogsView.swift +++ b/StikJIT/Views/ConsoleLogsView.swift @@ -77,7 +77,7 @@ struct ConsoleLogsView: View { VStack(spacing: 16) { // Error count with red theme HStack { - Text("\(logManager.errorCount) Critical Errors.") + Text("\(logManager.errorCount) Errors") .font(.headline) .foregroundColor(.white) .padding(.vertical, 12) From f85a99f3f590646f6cbffec05e1e7d57d065a560 Mon Sep 17 00:00:00 2001 From: neoarz Date: Sat, 29 Mar 2025 12:11:00 -0400 Subject: [PATCH 12/17] Revert "Add rust logs" This reverts commit d6a9e190c20776df5c2b90a62492bba8469dac24. --- StikJIT/Utilities/LogManager.swift | 157 ---------------------------- StikJIT/Views/ConsoleLogsView.swift | 2 +- 2 files changed, 1 insertion(+), 158 deletions(-) diff --git a/StikJIT/Utilities/LogManager.swift b/StikJIT/Utilities/LogManager.swift index eeddc89..6b72983 100644 --- a/StikJIT/Utilities/LogManager.swift +++ b/StikJIT/Utilities/LogManager.swift @@ -6,7 +6,6 @@ // import Foundation -import os.log class LogManager: ObservableObject { static let shared = LogManager() @@ -14,13 +13,6 @@ class LogManager: ObservableObject { @Published var logs: [LogEntry] = [] @Published var errorCount: Int = 0 - // Add properties to capture stdout/stderr - private var stdoutPipe: Pipe? - private var stderrPipe: Pipe? - private var originalStdout: Int32 = -1 - private var originalStderr: Int32 = -1 - private let logQueue = DispatchQueue(label: "com.stikjit.logQueue") - struct LogEntry: Identifiable { let id = UUID() let timestamp: Date @@ -39,155 +31,6 @@ class LogManager: ObservableObject { // Add initial system info logs addInfoLog("StikJIT starting up") addInfoLog("Initializing environment") - - // Set up stdout and stderr capture - captureStandardOutput() - - // Register for system log notifications - #if os(macOS) - // On macOS, also listen for system log messages - setupMacOSLogCapture() - #endif - } - - #if os(macOS) - private func setupMacOSLogCapture() { - // On macOS we can use the OSLog system - // This is a placeholder for macOS-specific log capture - // Start a background task to read system logs - DispatchQueue.global(qos: .background).async { - self.captureSystemLogs() - } - } - - private func captureSystemLogs() { - // This is a basic implementation to capture macOS logs - // A more comprehensive solution would use the OSLog framework - let task = Process() - let pipe = Pipe() - - task.executableURL = URL(fileURLWithPath: "/usr/bin/log") - task.arguments = ["stream", "--style", "compact"] - task.standardOutput = pipe - - pipe.fileHandleForReading.readabilityHandler = { [weak self] handle in - let data = handle.availableData - if let string = String(data: data, encoding: .utf8), !string.isEmpty { - self?.processStandardOutputLine(string, isError: false) - } - } - - do { - try task.run() - } catch { - self.addErrorLog("Failed to capture system logs: \(error.localizedDescription)") - } - } - #endif - - // Function to capture standard output and standard error - private func captureStandardOutput() { - #if DEBUG && targetEnvironment(simulator) - // Skip capturing in simulator debug builds to ensure logs appear in Xcode console - return - #endif - - // Save original file descriptors safely - if FileHandle.standardOutput.fileDescriptor >= 0 { - originalStdout = dup(FileHandle.standardOutput.fileDescriptor) - } - if FileHandle.standardError.fileDescriptor >= 0 { - originalStderr = dup(FileHandle.standardError.fileDescriptor) - } - - // Create pipes - stdoutPipe = Pipe() - stderrPipe = Pipe() - - // Redirect stdout and stderr to our pipes only if valid - if let stdoutPipe = stdoutPipe, FileHandle.standardOutput.fileDescriptor >= 0 { - dup2(stdoutPipe.fileHandleForWriting.fileDescriptor, FileHandle.standardOutput.fileDescriptor) - } - if let stderrPipe = stderrPipe, FileHandle.standardError.fileDescriptor >= 0 { - dup2(stderrPipe.fileHandleForWriting.fileDescriptor, FileHandle.standardError.fileDescriptor) - } - - // Start reading from the pipes on a background queue to avoid blocking - stdoutPipe?.fileHandleForReading.readabilityHandler = { [weak self] handle in - let data = handle.availableData - if !data.isEmpty, let string = String(data: data, encoding: .utf8) { - // Write back to original stdout for console viewing - if let strongSelf = self, strongSelf.originalStdout >= 0 { - write(strongSelf.originalStdout, string, string.utf8.count) - } - - self?.logQueue.async { - self?.processStandardOutputLine(string, isError: false) - } - } - } - - stderrPipe?.fileHandleForReading.readabilityHandler = { [weak self] handle in - let data = handle.availableData - if !data.isEmpty, let string = String(data: data, encoding: .utf8) { - // Write back to original stderr for console viewing - if let strongSelf = self, strongSelf.originalStderr >= 0 { - write(strongSelf.originalStderr, string, string.utf8.count) - } - - self?.logQueue.async { - self?.processStandardOutputLine(string, isError: true) - } - } - } - - // Also set up a timer to periodically flush stdout/stderr - Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] _ in - self?.flushPipes() - } - } - - private func flushPipes() { - // Force flush the pipes to ensure all output is captured - fflush(stdout) - fflush(stderr) - } - - // Process standard output/error lines and add to logs - private func processStandardOutputLine(_ line: String, isError: Bool) { - // Split multi-line output - let lines = line.components(separatedBy: .newlines) - - for line in lines where !line.isEmpty { - // Determine log type based on content - let type: LogEntry.LogType - - // Check for error indicators - if line.contains("[ERROR]") || line.contains("Error:") || line.contains("error:") || - line.contains("ERROR:") || line.contains("Failed") || (isError && !line.contains("DEBUG")) { - type = .error - } - // Check for warning indicators - else if line.contains("[WARNING]") || line.contains("Warning:") || line.contains("warning:") || - line.contains("WARN:") || line.contains("WARNING:") { - type = .warning - } - // Check for debug indicators - else if line.contains("[DEBUG]") || line.contains("DEBUG:") || line.contains("debug:") { - type = .debug - } - // Check for info indicators - else if line.contains("[INFO]") || line.contains("INFO:") || line.contains("info:") { - type = .info - } - // Default to info for anything else - else { - type = isError ? .error : .info - } - - // Add to logs - addLog(message: line, type: type) - } } func addLog(message: String, type: LogEntry.LogType) { diff --git a/StikJIT/Views/ConsoleLogsView.swift b/StikJIT/Views/ConsoleLogsView.swift index ee8329b..0659fc2 100644 --- a/StikJIT/Views/ConsoleLogsView.swift +++ b/StikJIT/Views/ConsoleLogsView.swift @@ -77,7 +77,7 @@ struct ConsoleLogsView: View { VStack(spacing: 16) { // Error count with red theme HStack { - Text("\(logManager.errorCount) Errors") + Text("\(logManager.errorCount) Critical Errors.") .font(.headline) .foregroundColor(.white) .padding(.vertical, 12) From 2b4f55edcb07ce62224d1f04dcbab0ffae3cfd4d Mon Sep 17 00:00:00 2001 From: neoarz Date: Sat, 29 Mar 2025 15:49:40 -0400 Subject: [PATCH 13/17] "Add rust logs" --- StikJIT.xcodeproj/project.pbxproj | 20 ++-- StikJIT/Utilities/LogManager.swift | 157 ++++++++++++++++++++++++++++ StikJIT/Views/ConsoleLogsView.swift | 2 +- 3 files changed, 171 insertions(+), 8 deletions(-) diff --git a/StikJIT.xcodeproj/project.pbxproj b/StikJIT.xcodeproj/project.pbxproj index c17ccb1..6b326e2 100644 --- a/StikJIT.xcodeproj/project.pbxproj +++ b/StikJIT.xcodeproj/project.pbxproj @@ -435,10 +435,11 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = StikJIT/StikJIT.entitlements; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"StikJIT/Preview Content\""; - DEVELOPMENT_TEAM = SZ977XLF24; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5W322N3S53; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -463,8 +464,10 @@ ); MACOSX_DEPLOYMENT_TARGET = 15.1; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.stik.StikJIT; + PRODUCT_BUNDLE_IDENTIFIER = com.stikjit.neosign; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = StikJIT; SDKROOT = auto; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -483,10 +486,11 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = StikJIT/StikJIT.entitlements; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"StikJIT/Preview Content\""; - DEVELOPMENT_TEAM = SZ977XLF24; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5W322N3S53; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -511,8 +515,10 @@ ); MACOSX_DEPLOYMENT_TARGET = 15.1; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.stik.StikJIT; + PRODUCT_BUNDLE_IDENTIFIER = com.stikjit.neosign; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = StikJIT; SDKROOT = auto; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -655,4 +661,4 @@ /* End XCConfigurationList section */ }; rootObject = DC6F1D2F2D94EADD0071B2B6 /* Project object */; -} \ No newline at end of file +} diff --git a/StikJIT/Utilities/LogManager.swift b/StikJIT/Utilities/LogManager.swift index 6b72983..eeddc89 100644 --- a/StikJIT/Utilities/LogManager.swift +++ b/StikJIT/Utilities/LogManager.swift @@ -6,6 +6,7 @@ // import Foundation +import os.log class LogManager: ObservableObject { static let shared = LogManager() @@ -13,6 +14,13 @@ class LogManager: ObservableObject { @Published var logs: [LogEntry] = [] @Published var errorCount: Int = 0 + // Add properties to capture stdout/stderr + private var stdoutPipe: Pipe? + private var stderrPipe: Pipe? + private var originalStdout: Int32 = -1 + private var originalStderr: Int32 = -1 + private let logQueue = DispatchQueue(label: "com.stikjit.logQueue") + struct LogEntry: Identifiable { let id = UUID() let timestamp: Date @@ -31,6 +39,155 @@ class LogManager: ObservableObject { // Add initial system info logs addInfoLog("StikJIT starting up") addInfoLog("Initializing environment") + + // Set up stdout and stderr capture + captureStandardOutput() + + // Register for system log notifications + #if os(macOS) + // On macOS, also listen for system log messages + setupMacOSLogCapture() + #endif + } + + #if os(macOS) + private func setupMacOSLogCapture() { + // On macOS we can use the OSLog system + // This is a placeholder for macOS-specific log capture + // Start a background task to read system logs + DispatchQueue.global(qos: .background).async { + self.captureSystemLogs() + } + } + + private func captureSystemLogs() { + // This is a basic implementation to capture macOS logs + // A more comprehensive solution would use the OSLog framework + let task = Process() + let pipe = Pipe() + + task.executableURL = URL(fileURLWithPath: "/usr/bin/log") + task.arguments = ["stream", "--style", "compact"] + task.standardOutput = pipe + + pipe.fileHandleForReading.readabilityHandler = { [weak self] handle in + let data = handle.availableData + if let string = String(data: data, encoding: .utf8), !string.isEmpty { + self?.processStandardOutputLine(string, isError: false) + } + } + + do { + try task.run() + } catch { + self.addErrorLog("Failed to capture system logs: \(error.localizedDescription)") + } + } + #endif + + // Function to capture standard output and standard error + private func captureStandardOutput() { + #if DEBUG && targetEnvironment(simulator) + // Skip capturing in simulator debug builds to ensure logs appear in Xcode console + return + #endif + + // Save original file descriptors safely + if FileHandle.standardOutput.fileDescriptor >= 0 { + originalStdout = dup(FileHandle.standardOutput.fileDescriptor) + } + if FileHandle.standardError.fileDescriptor >= 0 { + originalStderr = dup(FileHandle.standardError.fileDescriptor) + } + + // Create pipes + stdoutPipe = Pipe() + stderrPipe = Pipe() + + // Redirect stdout and stderr to our pipes only if valid + if let stdoutPipe = stdoutPipe, FileHandle.standardOutput.fileDescriptor >= 0 { + dup2(stdoutPipe.fileHandleForWriting.fileDescriptor, FileHandle.standardOutput.fileDescriptor) + } + if let stderrPipe = stderrPipe, FileHandle.standardError.fileDescriptor >= 0 { + dup2(stderrPipe.fileHandleForWriting.fileDescriptor, FileHandle.standardError.fileDescriptor) + } + + // Start reading from the pipes on a background queue to avoid blocking + stdoutPipe?.fileHandleForReading.readabilityHandler = { [weak self] handle in + let data = handle.availableData + if !data.isEmpty, let string = String(data: data, encoding: .utf8) { + // Write back to original stdout for console viewing + if let strongSelf = self, strongSelf.originalStdout >= 0 { + write(strongSelf.originalStdout, string, string.utf8.count) + } + + self?.logQueue.async { + self?.processStandardOutputLine(string, isError: false) + } + } + } + + stderrPipe?.fileHandleForReading.readabilityHandler = { [weak self] handle in + let data = handle.availableData + if !data.isEmpty, let string = String(data: data, encoding: .utf8) { + // Write back to original stderr for console viewing + if let strongSelf = self, strongSelf.originalStderr >= 0 { + write(strongSelf.originalStderr, string, string.utf8.count) + } + + self?.logQueue.async { + self?.processStandardOutputLine(string, isError: true) + } + } + } + + // Also set up a timer to periodically flush stdout/stderr + Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] _ in + self?.flushPipes() + } + } + + private func flushPipes() { + // Force flush the pipes to ensure all output is captured + fflush(stdout) + fflush(stderr) + } + + // Process standard output/error lines and add to logs + private func processStandardOutputLine(_ line: String, isError: Bool) { + // Split multi-line output + let lines = line.components(separatedBy: .newlines) + + for line in lines where !line.isEmpty { + // Determine log type based on content + let type: LogEntry.LogType + + // Check for error indicators + if line.contains("[ERROR]") || line.contains("Error:") || line.contains("error:") || + line.contains("ERROR:") || line.contains("Failed") || (isError && !line.contains("DEBUG")) { + type = .error + } + // Check for warning indicators + else if line.contains("[WARNING]") || line.contains("Warning:") || line.contains("warning:") || + line.contains("WARN:") || line.contains("WARNING:") { + type = .warning + } + // Check for debug indicators + else if line.contains("[DEBUG]") || line.contains("DEBUG:") || line.contains("debug:") { + type = .debug + } + // Check for info indicators + else if line.contains("[INFO]") || line.contains("INFO:") || line.contains("info:") { + type = .info + } + // Default to info for anything else + else { + type = isError ? .error : .info + } + + // Add to logs + addLog(message: line, type: type) + } } func addLog(message: String, type: LogEntry.LogType) { diff --git a/StikJIT/Views/ConsoleLogsView.swift b/StikJIT/Views/ConsoleLogsView.swift index 0659fc2..ee8329b 100644 --- a/StikJIT/Views/ConsoleLogsView.swift +++ b/StikJIT/Views/ConsoleLogsView.swift @@ -77,7 +77,7 @@ struct ConsoleLogsView: View { VStack(spacing: 16) { // Error count with red theme HStack { - Text("\(logManager.errorCount) Critical Errors.") + Text("\(logManager.errorCount) Errors") .font(.headline) .foregroundColor(.white) .padding(.vertical, 12) From d527a660c49b9c8eb21a1505310744dcc34152da Mon Sep 17 00:00:00 2001 From: neoarz Date: Sat, 29 Mar 2025 15:58:44 -0400 Subject: [PATCH 14/17] Revert ""Add rust logs"" This reverts commit 2b4f55edcb07ce62224d1f04dcbab0ffae3cfd4d. --- StikJIT.xcodeproj/project.pbxproj | 20 ++-- StikJIT/Utilities/LogManager.swift | 157 ---------------------------- StikJIT/Views/ConsoleLogsView.swift | 2 +- 3 files changed, 8 insertions(+), 171 deletions(-) diff --git a/StikJIT.xcodeproj/project.pbxproj b/StikJIT.xcodeproj/project.pbxproj index 6b326e2..c17ccb1 100644 --- a/StikJIT.xcodeproj/project.pbxproj +++ b/StikJIT.xcodeproj/project.pbxproj @@ -435,11 +435,10 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = StikJIT/StikJIT.entitlements; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"StikJIT/Preview Content\""; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5W322N3S53; + DEVELOPMENT_TEAM = SZ977XLF24; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -464,10 +463,8 @@ ); MACOSX_DEPLOYMENT_TARGET = 15.1; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.stikjit.neosign; + PRODUCT_BUNDLE_IDENTIFIER = com.stik.StikJIT; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = StikJIT; SDKROOT = auto; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -486,11 +483,10 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = StikJIT/StikJIT.entitlements; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"StikJIT/Preview Content\""; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5W322N3S53; + DEVELOPMENT_TEAM = SZ977XLF24; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -515,10 +511,8 @@ ); MACOSX_DEPLOYMENT_TARGET = 15.1; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.stikjit.neosign; + PRODUCT_BUNDLE_IDENTIFIER = com.stik.StikJIT; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = StikJIT; SDKROOT = auto; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -661,4 +655,4 @@ /* End XCConfigurationList section */ }; rootObject = DC6F1D2F2D94EADD0071B2B6 /* Project object */; -} +} \ No newline at end of file diff --git a/StikJIT/Utilities/LogManager.swift b/StikJIT/Utilities/LogManager.swift index eeddc89..6b72983 100644 --- a/StikJIT/Utilities/LogManager.swift +++ b/StikJIT/Utilities/LogManager.swift @@ -6,7 +6,6 @@ // import Foundation -import os.log class LogManager: ObservableObject { static let shared = LogManager() @@ -14,13 +13,6 @@ class LogManager: ObservableObject { @Published var logs: [LogEntry] = [] @Published var errorCount: Int = 0 - // Add properties to capture stdout/stderr - private var stdoutPipe: Pipe? - private var stderrPipe: Pipe? - private var originalStdout: Int32 = -1 - private var originalStderr: Int32 = -1 - private let logQueue = DispatchQueue(label: "com.stikjit.logQueue") - struct LogEntry: Identifiable { let id = UUID() let timestamp: Date @@ -39,155 +31,6 @@ class LogManager: ObservableObject { // Add initial system info logs addInfoLog("StikJIT starting up") addInfoLog("Initializing environment") - - // Set up stdout and stderr capture - captureStandardOutput() - - // Register for system log notifications - #if os(macOS) - // On macOS, also listen for system log messages - setupMacOSLogCapture() - #endif - } - - #if os(macOS) - private func setupMacOSLogCapture() { - // On macOS we can use the OSLog system - // This is a placeholder for macOS-specific log capture - // Start a background task to read system logs - DispatchQueue.global(qos: .background).async { - self.captureSystemLogs() - } - } - - private func captureSystemLogs() { - // This is a basic implementation to capture macOS logs - // A more comprehensive solution would use the OSLog framework - let task = Process() - let pipe = Pipe() - - task.executableURL = URL(fileURLWithPath: "/usr/bin/log") - task.arguments = ["stream", "--style", "compact"] - task.standardOutput = pipe - - pipe.fileHandleForReading.readabilityHandler = { [weak self] handle in - let data = handle.availableData - if let string = String(data: data, encoding: .utf8), !string.isEmpty { - self?.processStandardOutputLine(string, isError: false) - } - } - - do { - try task.run() - } catch { - self.addErrorLog("Failed to capture system logs: \(error.localizedDescription)") - } - } - #endif - - // Function to capture standard output and standard error - private func captureStandardOutput() { - #if DEBUG && targetEnvironment(simulator) - // Skip capturing in simulator debug builds to ensure logs appear in Xcode console - return - #endif - - // Save original file descriptors safely - if FileHandle.standardOutput.fileDescriptor >= 0 { - originalStdout = dup(FileHandle.standardOutput.fileDescriptor) - } - if FileHandle.standardError.fileDescriptor >= 0 { - originalStderr = dup(FileHandle.standardError.fileDescriptor) - } - - // Create pipes - stdoutPipe = Pipe() - stderrPipe = Pipe() - - // Redirect stdout and stderr to our pipes only if valid - if let stdoutPipe = stdoutPipe, FileHandle.standardOutput.fileDescriptor >= 0 { - dup2(stdoutPipe.fileHandleForWriting.fileDescriptor, FileHandle.standardOutput.fileDescriptor) - } - if let stderrPipe = stderrPipe, FileHandle.standardError.fileDescriptor >= 0 { - dup2(stderrPipe.fileHandleForWriting.fileDescriptor, FileHandle.standardError.fileDescriptor) - } - - // Start reading from the pipes on a background queue to avoid blocking - stdoutPipe?.fileHandleForReading.readabilityHandler = { [weak self] handle in - let data = handle.availableData - if !data.isEmpty, let string = String(data: data, encoding: .utf8) { - // Write back to original stdout for console viewing - if let strongSelf = self, strongSelf.originalStdout >= 0 { - write(strongSelf.originalStdout, string, string.utf8.count) - } - - self?.logQueue.async { - self?.processStandardOutputLine(string, isError: false) - } - } - } - - stderrPipe?.fileHandleForReading.readabilityHandler = { [weak self] handle in - let data = handle.availableData - if !data.isEmpty, let string = String(data: data, encoding: .utf8) { - // Write back to original stderr for console viewing - if let strongSelf = self, strongSelf.originalStderr >= 0 { - write(strongSelf.originalStderr, string, string.utf8.count) - } - - self?.logQueue.async { - self?.processStandardOutputLine(string, isError: true) - } - } - } - - // Also set up a timer to periodically flush stdout/stderr - Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] _ in - self?.flushPipes() - } - } - - private func flushPipes() { - // Force flush the pipes to ensure all output is captured - fflush(stdout) - fflush(stderr) - } - - // Process standard output/error lines and add to logs - private func processStandardOutputLine(_ line: String, isError: Bool) { - // Split multi-line output - let lines = line.components(separatedBy: .newlines) - - for line in lines where !line.isEmpty { - // Determine log type based on content - let type: LogEntry.LogType - - // Check for error indicators - if line.contains("[ERROR]") || line.contains("Error:") || line.contains("error:") || - line.contains("ERROR:") || line.contains("Failed") || (isError && !line.contains("DEBUG")) { - type = .error - } - // Check for warning indicators - else if line.contains("[WARNING]") || line.contains("Warning:") || line.contains("warning:") || - line.contains("WARN:") || line.contains("WARNING:") { - type = .warning - } - // Check for debug indicators - else if line.contains("[DEBUG]") || line.contains("DEBUG:") || line.contains("debug:") { - type = .debug - } - // Check for info indicators - else if line.contains("[INFO]") || line.contains("INFO:") || line.contains("info:") { - type = .info - } - // Default to info for anything else - else { - type = isError ? .error : .info - } - - // Add to logs - addLog(message: line, type: type) - } } func addLog(message: String, type: LogEntry.LogType) { diff --git a/StikJIT/Views/ConsoleLogsView.swift b/StikJIT/Views/ConsoleLogsView.swift index ee8329b..0659fc2 100644 --- a/StikJIT/Views/ConsoleLogsView.swift +++ b/StikJIT/Views/ConsoleLogsView.swift @@ -77,7 +77,7 @@ struct ConsoleLogsView: View { VStack(spacing: 16) { // Error count with red theme HStack { - Text("\(logManager.errorCount) Errors") + Text("\(logManager.errorCount) Critical Errors.") .font(.headline) .foregroundColor(.white) .padding(.vertical, 12) From d769294e6ea2e9a376030ad3bc16c629719fb9e1 Mon Sep 17 00:00:00 2001 From: neoarz <164915254+neoarz@users.noreply.github.com> Date: Sat, 29 Mar 2025 16:09:35 -0400 Subject: [PATCH 15/17] Update ConsoleLogsView.swift --- StikJIT/Views/ConsoleLogsView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/StikJIT/Views/ConsoleLogsView.swift b/StikJIT/Views/ConsoleLogsView.swift index 0659fc2..1522f8d 100644 --- a/StikJIT/Views/ConsoleLogsView.swift +++ b/StikJIT/Views/ConsoleLogsView.swift @@ -14,7 +14,7 @@ struct ConsoleLogsView: View { @State private var autoScroll = true @State private var scrollView: ScrollViewProxy? = nil - // Add these state variables for alert handling + // Alert handlin @State private var showingExportAlert = false @State private var showingCopyAlert = false @State private var alertMessage = "" From 1de374921caecfb313181017de6bfdc855dab29b Mon Sep 17 00:00:00 2001 From: neoarz <164915254+neoarz@users.noreply.github.com> Date: Sat, 29 Mar 2025 16:10:52 -0400 Subject: [PATCH 16/17] Update SettingsView.swift --- StikJIT/Views/SettingsView.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/StikJIT/Views/SettingsView.swift b/StikJIT/Views/SettingsView.swift index bcbc9bb..df55ff9 100644 --- a/StikJIT/Views/SettingsView.swift +++ b/StikJIT/Views/SettingsView.swift @@ -6,9 +6,6 @@ import SwiftUI import UniformTypeIdentifiers -// Add this if ConsoleLogsView is in a different module (unlikely but just in case) -// import ConsoleLogsModule - struct SettingsView: View { @AppStorage("username") private var username = "User" @AppStorage("customBackgroundColor") private var customBackgroundColorHex: String = Color.primaryBackground.toHex() ?? "#000000" From da7d9dfeacfc3b3e72622a2dc05d45105bbec61f Mon Sep 17 00:00:00 2001 From: neoarz <164915254+neoarz@users.noreply.github.com> Date: Sat, 29 Mar 2025 16:12:56 -0400 Subject: [PATCH 17/17] Update HomeView.swift --- StikJIT/Views/HomeView.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/StikJIT/Views/HomeView.swift b/StikJIT/Views/HomeView.swift index 7ec0695..93b9311 100644 --- a/StikJIT/Views/HomeView.swift +++ b/StikJIT/Views/HomeView.swift @@ -265,7 +265,6 @@ struct HomeView: View { DispatchQueue.global(qos: .background).async { JITEnableContext.shared().debugApp(withBundleID: bundleID, logger: { message in - // Safely unwrap the optional message if let message = message { // Log messages from the JIT process LogManager.shared.addInfoLog(message)