Allow changelog URL callback to be set

This commit is contained in:
2024-06-16 18:25:44 +02:00
parent a4f1f0e33d
commit 50da591a6a
3 changed files with 49 additions and 33 deletions

View File

@ -10,7 +10,11 @@ let package = Package(
products: [
.library(name: "NVAppUpdater", targets: ["NVAppUpdater"]),
],
dependencies: [
.package(name: "NVAlert", path: "/Users/nicoverbruggen/Code/SwiftPM/NVAlert")
// .package(url: "https://github.com/nicoverbruggen/NVAlert", branch: "main")
],
targets: [
.target(name: "NVAppUpdater"),
.target(name: "NVAppUpdater", dependencies: ["NVAlert"]),
]
)

View File

@ -5,16 +5,17 @@
import Foundation
import Cocoa
import NVAlert
open class UpdateCheck
{
let caskUrl: URL
let promptOnFailure: Bool
let selfUpdaterName: String
let selfUpdaterPath: String
var caskFile: CaskFile!
var newerVersion: AppVersion!
private var releaseNotesUrlCallback: ((CaskFile) -> URL?)? = nil
private var caskFile: CaskFile!
private var newerVersion: AppVersion!
/**
* Create a new update check instance. Once created, you should call `perform` on this instance.
@ -28,30 +29,33 @@ open class UpdateCheck
*
* - Parameter caskUrl: The URL where the Cask file is expected to be located. Redirects will
* be followed when retrieving and validating the Cask file.
*/
public init(
selfUpdaterName: String,
selfUpdaterPath: String,
caskUrl: URL
) {
self.selfUpdaterName = selfUpdaterName
self.selfUpdaterPath = selfUpdaterPath
self.caskUrl = caskUrl
}
public func resolvingReleaseNotes(with callback: @escaping (CaskFile) -> URL?) -> Self {
self.releaseNotesUrlCallback = callback
return self
}
/**
* Perform the check for a new version.
*
* - Parameter promptOnFailure: Whether user interaction is required when failing to check
* or no new update is found. A user usually expects a prompt if they manually searched
* for updates.
*/
public init(
selfUpdaterName: String,
selfUpdaterPath: String,
caskUrl: URL,
promptOnFailure: Bool
) {
self.selfUpdaterName = selfUpdaterName
self.selfUpdaterPath = selfUpdaterPath
self.caskUrl = caskUrl
self.promptOnFailure = promptOnFailure
}
/**
Perform the check for a new version.
*/
public func perform() async {
guard let caskFile = await CaskFile.from(url: caskUrl) else {
public func perform(promptOnFailure: Bool = true) async {
guard let caskFile = CaskFile.from(url: caskUrl) else {
Log.text("The contents of the CaskFile at '\(caskUrl.absoluteString)' could not be retrieved.")
return await presentCouldNotRetrieveUpdate()
return await presentCouldNotRetrieveUpdate(promptOnFailure)
}
self.caskFile = caskFile
@ -60,7 +64,7 @@ open class UpdateCheck
guard let onlineVersion = AppVersion.from(caskFile.version) else {
Log.text("The version string from the CaskFile could not be read.")
return await presentCouldNotRetrieveUpdate()
return await presentCouldNotRetrieveUpdate(promptOnFailure)
}
self.newerVersion = onlineVersion
@ -71,13 +75,13 @@ open class UpdateCheck
if onlineVersion > currentVersion {
await presentNewerVersionAvailable()
} else if promptOnFailure {
await presentVersionIsUpToDate()
await presentVersionIsUpToDate(promptOnFailure)
}
}
// MARK: - Alerts
private func presentCouldNotRetrieveUpdate() async {
private func presentCouldNotRetrieveUpdate(_ promptOnFailure: Bool) async {
Log.text("Could not retrieve update manifest!")
if promptOnFailure {
@ -88,7 +92,7 @@ open class UpdateCheck
}
}
private func presentVersionIsUpToDate() async {
private func presentVersionIsUpToDate(_ promptOnFailure: Bool) async {
Log.text("Version is up-to-date!")
if promptOnFailure {
@ -104,22 +108,30 @@ open class UpdateCheck
let current = AppVersion.fromCurrentVersion()
let outcome = await Alert.choose(
let alert = await NVAlert().withInformation(
title: "An updated version of \(Executable.name) is available.",
description: """
Version \(newerVersion.version) is available for download.
(This is currently version \(current.version).)
Do you want to download and install this updated version?
""",
options: [
"Update Now",
"Cancel"
])
if outcome == .alertFirstButtonReturn {
launchSelfUpdater()
subtitle: "Version \(newerVersion.version) is available for download.",
description: "Do you want to download and install this updated version?"
)
.withPrimary(
text: "Install",
action: { vc in
vc.close(with: .OK)
self.launchSelfUpdater()
}
)
.withTertiary(text: "Dismiss", action: { vc in
vc.close(with: .OK)
})
if let callback = self.releaseNotesUrlCallback,
let url = callback(self.caskFile) {
await alert.withSecondary(text: "View Release Notes") { _ in
NSWorkspace.shared.open(url)
}
}
await alert.show()
}
// MARK: - Functional

View File

@ -5,7 +5,7 @@
import Foundation
struct CaskFile {
public struct CaskFile {
var properties: [String: String]
var name: String { return self.properties["name"]! }