mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
Displays detailed error log in-app with Quick Look
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
import SafariServices
|
import SafariServices
|
||||||
|
import QuickLook
|
||||||
|
|
||||||
import AltStoreCore
|
import AltStoreCore
|
||||||
import Roxas
|
import Roxas
|
||||||
@@ -37,6 +38,8 @@ final class ErrorLogViewController: UITableViewController
|
|||||||
@IBOutlet private var exportLogButton: UIBarButtonItem!
|
@IBOutlet private var exportLogButton: UIBarButtonItem!
|
||||||
@IBOutlet private var clearLogButton: UIBarButtonItem!
|
@IBOutlet private var clearLogButton: UIBarButtonItem!
|
||||||
|
|
||||||
|
private var _exportedLogURL: URL?
|
||||||
|
|
||||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||||
return .lightContent
|
return .lightContent
|
||||||
}
|
}
|
||||||
@@ -286,10 +289,10 @@ private extension ErrorLogViewController
|
|||||||
|
|
||||||
// All logs since the app launched.
|
// All logs since the app launched.
|
||||||
let position = store.position(timeIntervalSinceLatestBoot: 0)
|
let position = store.position(timeIntervalSinceLatestBoot: 0)
|
||||||
|
let predicate = NSPredicate(format: "subsystem == %@", Logger.altstoreSubsystem)
|
||||||
|
|
||||||
let entries = try store.getEntries(at: position)
|
let entries = try store.getEntries(at: position, matching: predicate)
|
||||||
.compactMap { $0 as? OSLogEntryLog }
|
.compactMap { $0 as? OSLogEntryLog }
|
||||||
.filter { $0.subsystem.contains(Logger.altstoreSubsystem) }
|
|
||||||
.map { "[\($0.date.formatted())] [\($0.category)] [\($0.level.localizedName)] \($0.composedMessage)" }
|
.map { "[\($0.date.formatted())] [\($0.category)] [\($0.level.localizedName)] \($0.composedMessage)" }
|
||||||
|
|
||||||
let outputText = entries.joined(separator: "\n")
|
let outputText = entries.joined(separator: "\n")
|
||||||
@@ -297,35 +300,17 @@ private extension ErrorLogViewController
|
|||||||
let outputDirectory = FileManager.default.uniqueTemporaryURL()
|
let outputDirectory = FileManager.default.uniqueTemporaryURL()
|
||||||
try FileManager.default.createDirectory(at: outputDirectory, withIntermediateDirectories: true)
|
try FileManager.default.createDirectory(at: outputDirectory, withIntermediateDirectories: true)
|
||||||
|
|
||||||
defer {
|
let outputURL = outputDirectory.appendingPathComponent("altstore.log")
|
||||||
do
|
|
||||||
{
|
|
||||||
try FileManager.default.removeItem(at: outputDirectory)
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Logger.main.error("Failed to remove temporary log directory \(outputDirectory.lastPathComponent, privacy: .public). \(error.localizedDescription, privacy: .public)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let outputURL = outputDirectory.appendingPathComponent("altlog.txt")
|
|
||||||
try outputText.write(to: outputURL, atomically: true, encoding: .utf8)
|
try outputText.write(to: outputURL, atomically: true, encoding: .utf8)
|
||||||
|
|
||||||
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
|
await MainActor.run {
|
||||||
Task<Void, Never> { @MainActor in
|
self._exportedLogURL = outputURL
|
||||||
let activityViewController = UIActivityViewController(activityItems: [outputURL], applicationActivities: nil)
|
|
||||||
activityViewController.completionWithItemsHandler = { (activityType, completed, _, error) in
|
let previewController = QLPreviewController()
|
||||||
if let error
|
previewController.delegate = self
|
||||||
{
|
previewController.dataSource = self
|
||||||
continuation.resume(throwing: error)
|
previewController.view.tintColor = .altPrimary
|
||||||
}
|
self.present(previewController, animated: true)
|
||||||
else
|
|
||||||
{
|
|
||||||
continuation.resume()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.present(activityViewController, animated: true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@@ -448,3 +433,34 @@ extension ErrorLogViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension ErrorLogViewController: QLPreviewControllerDataSource, QLPreviewControllerDelegate
|
||||||
|
{
|
||||||
|
func numberOfPreviewItems(in controller: QLPreviewController) -> Int
|
||||||
|
{
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem
|
||||||
|
{
|
||||||
|
return (_exportedLogURL as? NSURL) ?? NSURL()
|
||||||
|
}
|
||||||
|
|
||||||
|
func previewControllerDidDismiss(_ controller: QLPreviewController)
|
||||||
|
{
|
||||||
|
guard let exportedLogURL = _exportedLogURL else { return }
|
||||||
|
|
||||||
|
let parentDirectory = exportedLogURL.deletingLastPathComponent()
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
try FileManager.default.removeItem(at: parentDirectory)
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Logger.main.error("Failed to remove temporary log directory \(parentDirectory.lastPathComponent, privacy: .public). \(error.localizedDescription, privacy: .public)")
|
||||||
|
}
|
||||||
|
|
||||||
|
_exportedLogURL = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
public extension Logger
|
public extension Logger
|
||||||
{
|
{
|
||||||
static let altstoreSubsystem = Bundle.main.bundleIdentifier!
|
static let altstoreSubsystem = "com.rileytestut.AltStore" // Hardcoded because Bundle.main.bundleIdentifier is different for every user
|
||||||
|
|
||||||
static let main = Logger(subsystem: altstoreSubsystem, category: "Main")
|
static let main = Logger(subsystem: altstoreSubsystem, category: "Main")
|
||||||
static let sideload = Logger(subsystem: altstoreSubsystem, category: "Sideload")
|
static let sideload = Logger(subsystem: altstoreSubsystem, category: "Sideload")
|
||||||
|
|||||||
Reference in New Issue
Block a user