Remove the Show/Hide Logs button and logs view from the Updates preferences tab. Keep the logging infrastructure in SparkleUpdater for diagnostics, but don't display it in the UI.
128 lines
4.5 KiB
Swift
128 lines
4.5 KiB
Swift
import Sparkle
|
|
import Foundation
|
|
import OSLog
|
|
|
|
@MainActor
|
|
final class SparkleUpdater: NSObject, ObservableObject {
|
|
private lazy var controller: SPUStandardUpdaterController = {
|
|
SPUStandardUpdaterController(startingUpdater: true, updaterDelegate: self, userDriverDelegate: nil)
|
|
}()
|
|
private let logger = Logger(subsystem: "net.24unix.iKeyMon", category: "Sparkle")
|
|
private let verboseLogging: Bool
|
|
@Published var logMessages: [String] = []
|
|
|
|
override init() {
|
|
self.verboseLogging = ProcessInfo.processInfo.environment["SPARKLE_VERBOSE_LOGGING"] == "1"
|
|
super.init()
|
|
_ = controller
|
|
log("Sparkle updater initialized (verbose=\(verboseLogging)).")
|
|
}
|
|
|
|
var automaticallyChecksForUpdates: Bool {
|
|
get { controller.updater.automaticallyChecksForUpdates }
|
|
set { controller.updater.automaticallyChecksForUpdates = newValue }
|
|
}
|
|
|
|
var automaticallyDownloadsUpdates: Bool {
|
|
get { controller.updater.automaticallyDownloadsUpdates }
|
|
set { controller.updater.automaticallyDownloadsUpdates = newValue }
|
|
}
|
|
|
|
func checkForUpdates() {
|
|
log("Manual check for updates triggered.")
|
|
controller.checkForUpdates(nil)
|
|
}
|
|
|
|
private func log(_ message: String) {
|
|
logger.log("\(message, privacy: .public)")
|
|
addLogMessage("[INFO] \(message)")
|
|
if verboseLogging {
|
|
print("[Sparkle] \(message)")
|
|
}
|
|
}
|
|
|
|
private func logError(_ message: String) {
|
|
logger.error("\(message, privacy: .public)")
|
|
addLogMessage("[ERROR] \(message)")
|
|
if verboseLogging {
|
|
fputs("[Sparkle][error] \(message)\n", stderr)
|
|
}
|
|
}
|
|
|
|
private func addLogMessage(_ message: String) {
|
|
let timestamp = DateFormatter.localizedString(from: Date(), dateStyle: .none, timeStyle: .medium)
|
|
let timestampedMessage = "[\(timestamp)] \(message)"
|
|
logMessages.append(timestampedMessage)
|
|
if logMessages.count > 100 {
|
|
logMessages.removeFirst()
|
|
}
|
|
}
|
|
|
|
private func describe(update item: SUAppcastItem) -> String {
|
|
let short = item.displayVersionString
|
|
let build = item.versionString
|
|
return "\(short) (build \(build))"
|
|
}
|
|
}
|
|
|
|
extension SparkleUpdater: SPUUpdaterDelegate {
|
|
nonisolated func updater(_ updater: SPUUpdater, didFinishLoading appcast: SUAppcast) {
|
|
Task { @MainActor in
|
|
log("Loaded Sparkle appcast containing \(appcast.items.count) item(s).")
|
|
}
|
|
}
|
|
|
|
nonisolated func updater(_ updater: SPUUpdater, didFindValidUpdate item: SUAppcastItem) {
|
|
Task { @MainActor in
|
|
log("Found valid update \(describe(update: item))")
|
|
}
|
|
}
|
|
|
|
nonisolated func updaterDidNotFindUpdate(_ updater: SPUUpdater) {
|
|
Task { @MainActor in
|
|
log("No updates available.")
|
|
}
|
|
}
|
|
|
|
nonisolated func updater(_ updater: SPUUpdater, willDownloadUpdate item: SUAppcastItem, with request: NSMutableURLRequest) {
|
|
Task { @MainActor in
|
|
log("Downloading \(describe(update: item)) from \(request.url?.absoluteString ?? "unknown URL")")
|
|
}
|
|
}
|
|
|
|
nonisolated func updater(_ updater: SPUUpdater, didDownloadUpdate item: SUAppcastItem) {
|
|
Task { @MainActor in
|
|
log("Finished downloading \(describe(update: item))")
|
|
}
|
|
}
|
|
|
|
nonisolated func updater(_ updater: SPUUpdater, failedToDownloadUpdate item: SUAppcastItem, error: Error) {
|
|
Task { @MainActor in
|
|
logError("Failed to download \(describe(update: item)): \(error.localizedDescription)")
|
|
}
|
|
}
|
|
|
|
nonisolated func userDidCancelDownload(_ updater: SPUUpdater) {
|
|
Task { @MainActor in
|
|
log("User cancelled Sparkle download.")
|
|
}
|
|
}
|
|
|
|
nonisolated func updater(_ updater: SPUUpdater, willInstallUpdate item: SUAppcastItem) {
|
|
Task { @MainActor in
|
|
log("Will install update \(describe(update: item))")
|
|
}
|
|
}
|
|
|
|
nonisolated func updater(_ updater: SPUUpdater, didAbortWithError error: Error) {
|
|
Task { @MainActor in
|
|
let errorDescription = error as NSError
|
|
let details = "Domain: \(errorDescription.domain), Code: \(errorDescription.code), Description: \(error.localizedDescription)"
|
|
logError("Sparkle aborted: \(details)")
|
|
if let underlying = errorDescription.userInfo[NSUnderlyingErrorKey] as? NSError {
|
|
logError("Underlying error: Domain: \(underlying.domain), Code: \(underlying.code), Description: \(underlying.localizedDescription)")
|
|
}
|
|
}
|
|
}
|
|
}
|