diff --git a/AltStore/AppDelegate.swift b/AltStore/AppDelegate.swift index ec270382..6539cdcb 100644 --- a/AltStore/AppDelegate.swift +++ b/AltStore/AppDelegate.swift @@ -45,7 +45,21 @@ final class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // navigation bar buttons spacing is too much (so hack it to use minimal spacing) + // this is swift-5 specific behavior and might change + // https://stackoverflow.com/a/64988363/11971304 + // + // Warning: this affects all screens through out the app, and basically overrides storyboard + let stackViewAppearance = UIStackView.appearance(whenContainedInInstancesOf: [UINavigationBar.self]) + stackViewAppearance.spacing = -8 // adjust as needed + + // TODO: @mahee96: the capture is started, but when application sleeps/pushed to bg + // terminate might be called even if the application is not really closed? + // so the log gets rotated making write to a new log on wake up here + // thereby splitting the logs of current session into multiple ones + // + // Fix this later! // start logging to console immediately on startup consoleLog.startCapturing() diff --git a/AltStore/Settings/Error Log/ErrorLogViewController.swift b/AltStore/Settings/Error Log/ErrorLogViewController.swift index 28578194..546299b2 100644 --- a/AltStore/Settings/Error Log/ErrorLogViewController.swift +++ b/AltStore/Settings/Error Log/ErrorLogViewController.swift @@ -60,8 +60,46 @@ final class ErrorLogViewController: UITableViewController, QLPreviewControllerDe // Assign just clearLogButton to hide export button. self.navigationItem.rightBarButtonItems = [self.clearLogButton] } + +// // Adjust the width of the right bar button items +// adjustRightBarButtonWidth() } + +// func adjustRightBarButtonWidth() { +// // Access the current rightBarButtonItems +// if let rightBarButtonItems = self.navigationItem.rightBarButtonItems { +// for barButtonItem in rightBarButtonItems { +// // Check if the button is a system button, and if so, replace it with a custom button +// if barButtonItem.customView == nil { +// // Replace with a custom UIButton for each bar button item +// let customButton = UIButton(type: .custom) +// if let image = barButtonItem.image { +// customButton.setImage(image, for: .normal) +// } +// if let action = barButtonItem.action{ +// customButton.addTarget(barButtonItem.target, action: action, for: .touchUpInside) +// } +// +// // Calculate the original size based on the system button +// let originalSize = customButton.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)) +// +// let scaleFactor = 0.7 +// +// // Scale the size by 0.7 (70%) +// let scaledSize = CGSize(width: originalSize.width * scaleFactor, height: originalSize.height * scaleFactor) +// +// // Adjust the custom button's width +//// customButton.frame.size = CGSize(width: 22, height: 22) // Adjust width as needed +// customButton.frame.size = scaledSize // Adjust width as needed +// +// // Set the custom button as the custom view for the UIBarButtonItem +// barButtonItem.customView = customButton +// } +// } +// } +// } + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard let loggedError = sender as? LoggedError, segue.identifier == "showErrorDetails" else { return } @@ -222,44 +260,6 @@ private extension ErrorLogViewController case consoleLog = "console-log" case minimuxerLog = "minimuxer-log" -// // This class will manage the QLPreviewController and the timer. -// private class LogViewManager { -// var previewController: QLPreviewController -// var refreshTimer: Timer? -// -// init(previewController: QLPreviewController) { -// self.previewController = previewController -// } -// -// // Start refreshing the preview controller every second -// func startRefreshing() { -// refreshTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(refreshPreview), userInfo: nil, repeats: true) -// } -// -// @objc private func refreshPreview() { -// previewController.reloadData() -// } -// -// // Stop the timer to prevent leaks -// func stopRefreshing() { -// refreshTimer?.invalidate() -// refreshTimer = nil -// } -// } -// -// // Method to get the QLPreviewController for this log type -// func getViewController(_ dataSource: QLPreviewControllerDataSource) -> QLPreviewController { -// let previewController = QLPreviewController() -// previewController.restorationIdentifier = self.rawValue -// previewController.dataSource = dataSource -// -// // Create LogViewManager and start refreshing -// let manager = LogViewManager(previewController: previewController) -// manager.startRefreshing() -// -// return previewController -// } - // This class will manage the QLPreviewController and the timer. private class LogViewManager { var previewController: QLPreviewController @@ -300,7 +300,7 @@ private extension ErrorLogViewController // Create LogViewManager and start refreshing let manager = LogViewManager(previewController: previewController, logView: self) - manager.startRefreshing() +// manager.startRefreshing() // DO NOT REFRESH the full view contents causing flickering return previewController } @@ -316,7 +316,7 @@ private extension ErrorLogViewController } } - @IBAction func showMinimuxerLogs(_ sender: UIBarButtonItem) { + @IBAction func showConsoleLogs(_ sender: UIBarButtonItem) { // Create the SwiftUI ConsoleLogView with the URL let consoleLogView = ConsoleLogView(logURL: (UIApplication.shared.delegate as! AppDelegate).consoleLog.logFileURL) @@ -395,66 +395,74 @@ private extension ErrorLogViewController self.performSegue(withIdentifier: "showErrorDetails", sender: loggedError) } - @available(iOS 15, *) - @IBAction func exportDetailedLog(_ sender: UIBarButtonItem) + @IBAction func showMinimuxerLogs(_ sender: UIBarButtonItem) { - self.exportLogButton.isIndicatingActivity = true - - Task.detached(priority: .userInitiated) { - do - { - let store = try OSLogStore(scope: .currentProcessIdentifier) - - // All logs since the app launched. - let position = store.position(timeIntervalSinceLatestBoot: 0) -// let predicate = NSPredicate(format: "subsystem == %@", Logger.altstoreSubsystem) -// -// let entries = try store.getEntries(at: position, matching: predicate) -// .compactMap { $0 as? OSLogEntryLog } -// .map { "[\($0.date.formatted())] [\($0.category)] [\($0.level.localizedName)] \($0.composedMessage)" } -// - // Remove the predicate to get all log entries -// let entries = try store.getEntries(at: position) -// .compactMap { $0 as? OSLogEntryLog } -// .map { "[\($0.date.formatted())] [\($0.category)] [\($0.level.localizedName)] \($0.composedMessage)" } - - let entries = try store.getEntries(at: position) - -// let outputText = entries.joined(separator: "\n") - let outputText = entries.map { $0.description }.joined(separator: "\n") - - let outputDirectory = FileManager.default.uniqueTemporaryURL() - try FileManager.default.createDirectory(at: outputDirectory, withIntermediateDirectories: true) - - let outputURL = outputDirectory.appendingPathComponent("altstore.log") - try outputText.write(to: outputURL, atomically: true, encoding: .utf8) - - await MainActor.run { - self._exportedLogURL = outputURL - - let previewController = QLPreviewController() - previewController.delegate = self - previewController.dataSource = self - previewController.view.tintColor = .altPrimary - self.present(previewController, animated: true) - } - } - catch - { - Logger.main.error("Failed to export OSLog entries. \(error.localizedDescription, privacy: .public)") - - await MainActor.run { - let alertController = UIAlertController(title: NSLocalizedString("Unable to Export Detailed Log", comment: ""), message: error.localizedDescription, preferredStyle: .alert) - alertController.addAction(.ok) - self.present(alertController, animated: true) - } - } - - await MainActor.run { - self.exportLogButton.isIndicatingActivity = false - } - } + // Show minimuxer.log + let previewController = LogView.minimuxerLog.getViewController(self) + let navigationController = UINavigationController(rootViewController: previewController) + present(navigationController, animated: true, completion: nil) } + +// @available(iOS 15, *) +// @IBAction func exportDetailedLog(_ sender: UIBarButtonItem) +// { +// self.exportLogButton.isIndicatingActivity = true +// +// Task.detached(priority: .userInitiated) { +// do +// { +// let store = try OSLogStore(scope: .currentProcessIdentifier) +// +// // All logs since the app launched. +// let position = store.position(timeIntervalSinceLatestBoot: 0) +//// let predicate = NSPredicate(format: "subsystem == %@", Logger.altstoreSubsystem) +//// +//// let entries = try store.getEntries(at: position, matching: predicate) +//// .compactMap { $0 as? OSLogEntryLog } +//// .map { "[\($0.date.formatted())] [\($0.category)] [\($0.level.localizedName)] \($0.composedMessage)" } +//// +// // Remove the predicate to get all log entries +//// let entries = try store.getEntries(at: position) +//// .compactMap { $0 as? OSLogEntryLog } +//// .map { "[\($0.date.formatted())] [\($0.category)] [\($0.level.localizedName)] \($0.composedMessage)" } +// +// let entries = try store.getEntries(at: position) +// +//// let outputText = entries.joined(separator: "\n") +// let outputText = entries.map { $0.description }.joined(separator: "\n") +// +// let outputDirectory = FileManager.default.uniqueTemporaryURL() +// try FileManager.default.createDirectory(at: outputDirectory, withIntermediateDirectories: true) +// +// let outputURL = outputDirectory.appendingPathComponent("altstore.log") +// try outputText.write(to: outputURL, atomically: true, encoding: .utf8) +// +// await MainActor.run { +// self._exportedLogURL = outputURL +// +// let previewController = QLPreviewController() +// previewController.delegate = self +// previewController.dataSource = self +// previewController.view.tintColor = .altPrimary +// self.present(previewController, animated: true) +// } +// } +// catch +// { +// Logger.main.error("Failed to export OSLog entries. \(error.localizedDescription, privacy: .public)") +// +// await MainActor.run { +// let alertController = UIAlertController(title: NSLocalizedString("Unable to Export Detailed Log", comment: ""), message: error.localizedDescription, preferredStyle: .alert) +// alertController.addAction(.ok) +// self.present(alertController, animated: true) +// } +// } +// +// await MainActor.run { +// self.exportLogButton.isIndicatingActivity = false +// } +// } +// } } extension ErrorLogViewController diff --git a/AltStore/Settings/Settings.storyboard b/AltStore/Settings/Settings.storyboard index 4e4c302f..3cda8c21 100644 --- a/AltStore/Settings/Settings.storyboard +++ b/AltStore/Settings/Settings.storyboard @@ -4,6 +4,7 @@ + @@ -21,7 +22,7 @@ - +