96 lines
2.9 KiB
Swift
96 lines
2.9 KiB
Swift
import Foundation
|
|
#if os(macOS)
|
|
import AppKit
|
|
#endif
|
|
|
|
@MainActor
|
|
final class UpdateViewModel: ObservableObject {
|
|
struct StatusAlert: Identifiable {
|
|
let id = UUID()
|
|
let title: String
|
|
let message: String
|
|
}
|
|
|
|
@Published var availableRelease: ReleaseInfo?
|
|
@Published var latestFetchedRelease: ReleaseInfo?
|
|
@Published var statusAlert: StatusAlert?
|
|
@Published var isChecking = false
|
|
|
|
private let service: UpdateService
|
|
private let userDefaults: UserDefaults
|
|
private let autoCheckKey = "autoCheckUpdates"
|
|
private let includePrereleaseKey = "includePrereleaseUpdates"
|
|
|
|
init(service: UpdateService = UpdateService(), userDefaults: UserDefaults = .standard) {
|
|
self.service = service
|
|
self.userDefaults = userDefaults
|
|
registerDefaultsIfNeeded()
|
|
}
|
|
|
|
func startAutomaticCheckIfNeeded() {
|
|
if userDefaults.bool(forKey: autoCheckKey) {
|
|
checkForUpdates(userInitiated: false)
|
|
}
|
|
}
|
|
|
|
func checkForUpdates(userInitiated: Bool) {
|
|
guard !isChecking else { return }
|
|
isChecking = true
|
|
|
|
Task {
|
|
do {
|
|
let release = try await service.fetchLatestRelease(includePrerelease: userDefaults.bool(forKey: includePrereleaseKey))
|
|
handle(release: release, userInitiated: userInitiated)
|
|
} catch {
|
|
if userInitiated {
|
|
statusAlert = StatusAlert(
|
|
title: "Update Check Failed",
|
|
message: error.localizedDescription
|
|
)
|
|
}
|
|
}
|
|
self.isChecking = false
|
|
}
|
|
}
|
|
|
|
func openReleaseNotes() {
|
|
guard let releaseURL = availableRelease?.releaseURL ?? latestFetchedRelease?.releaseURL else { return }
|
|
#if os(macOS)
|
|
NSWorkspace.shared.open(releaseURL)
|
|
#endif
|
|
}
|
|
|
|
func downloadLatest() {
|
|
let release = availableRelease ?? latestFetchedRelease
|
|
availableRelease = nil
|
|
guard let downloadURL = release?.downloadURL else { return }
|
|
#if os(macOS)
|
|
NSWorkspace.shared.open(downloadURL)
|
|
#endif
|
|
}
|
|
|
|
private func handle(release: ReleaseInfo, userInitiated: Bool) {
|
|
let currentVersion = VersionNumber(
|
|
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "0.0.0"
|
|
)
|
|
|
|
latestFetchedRelease = release
|
|
|
|
if release.version > currentVersion {
|
|
availableRelease = release
|
|
} else if userInitiated {
|
|
statusAlert = StatusAlert(
|
|
title: "You're Up To Date",
|
|
message: "iKeyMon \(currentVersion.rawValue) is the latest version."
|
|
)
|
|
}
|
|
}
|
|
|
|
private func registerDefaultsIfNeeded() {
|
|
userDefaults.register(defaults: [
|
|
autoCheckKey: true,
|
|
includePrereleaseKey: true
|
|
])
|
|
}
|
|
}
|