mirror of
https://github.com/nicoverbruggen/NVAppUpdater.git
synced 2025-12-21 08:50:07 +01:00
Use NVAlert 2.0 with urgency
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"originHash" : "0b9d136f905253e9368420218eda771d18cfa528b15553cb08a34c9e5ecdfea7",
|
"originHash" : "699c69d1c5c91fc14af71a7c0e846526c570ff854487f4866cea7b5caa49b7fe",
|
||||||
"pins" : [
|
"pins" : [
|
||||||
{
|
{
|
||||||
"identity" : "nvalert",
|
"identity" : "nvalert",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/nicoverbruggen/NVAlert",
|
"location" : "https://github.com/nicoverbruggen/NVAlert",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "2d649465067e3fc053bc64beed0e2ffea7e1cbe2",
|
"revision" : "1bbaad37697e4ad4c047eec2a8fc9834c2b5d98a",
|
||||||
"version" : "1.0.0"
|
"version" : "2.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ let package = Package(
|
|||||||
.library(name: "NVAppUpdater", targets: ["NVAppUpdater"]),
|
.library(name: "NVAppUpdater", targets: ["NVAppUpdater"]),
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.package(url: "https://github.com/nicoverbruggen/NVAlert", from: "1.0.0")
|
.package(url: "https://github.com/nicoverbruggen/NVAlert", from: "2.0.0")
|
||||||
],
|
],
|
||||||
targets: [
|
targets: [
|
||||||
.target(name: "NVAppUpdater", dependencies: ["NVAlert"]),
|
.target(name: "NVAppUpdater", dependencies: ["NVAlert"]),
|
||||||
|
|||||||
@@ -68,7 +68,8 @@ await UpdateCheck(
|
|||||||
selfUpdaterName: "MyApp Self-Updater.app",
|
selfUpdaterName: "MyApp Self-Updater.app",
|
||||||
selfUpdaterPath: "~/.config/com.example.my-app/updater",
|
selfUpdaterPath: "~/.config/com.example.my-app/updater",
|
||||||
caskUrl: URL(string: "https://my-app.test/latest/build.rb")!,
|
caskUrl: URL(string: "https://my-app.test/latest/build.rb")!,
|
||||||
).perform(promptOnFailure: true)
|
isInteractive: true,
|
||||||
|
).perform()
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also specify what callback needs to be used to determine the correct URL for the release notes. You may need to get some information from the CaskFile, which you are free to source. For example:
|
You can also specify what callback needs to be used to determine the correct URL for the release notes. You may need to get some information from the CaskFile, which you are free to source. For example:
|
||||||
@@ -80,11 +81,12 @@ await UpdateCheck(
|
|||||||
selfUpdaterName: "MyApp Self-Updater.app",
|
selfUpdaterName: "MyApp Self-Updater.app",
|
||||||
selfUpdaterPath: "~/.config/com.example.my-app/updater",
|
selfUpdaterPath: "~/.config/com.example.my-app/updater",
|
||||||
caskUrl: URL(string: "https://my-app.test/latest/build.rb")!,
|
caskUrl: URL(string: "https://my-app.test/latest/build.rb")!,
|
||||||
|
isInteractive: true,
|
||||||
)
|
)
|
||||||
.resolvingReleaseNotes(with: { caskFile in
|
.resolvingReleaseNotes(with: { caskFile in
|
||||||
return URL(string: "https://my-app.com/release-notes/\(caskFile.version)")!
|
return URL(string: "https://my-app.com/release-notes/\(caskFile.version)")!
|
||||||
})
|
})
|
||||||
.perform(promptOnFailure: true)
|
.perform()
|
||||||
```
|
```
|
||||||
|
|
||||||
## Self-Updater
|
## Self-Updater
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ open class UpdateCheck
|
|||||||
let caskUrl: URL
|
let caskUrl: URL
|
||||||
let selfUpdaterName: String
|
let selfUpdaterName: String
|
||||||
let selfUpdaterPath: String
|
let selfUpdaterPath: String
|
||||||
|
let isInteractive: Bool
|
||||||
|
|
||||||
private var releaseNotesUrlCallback: ((NVCaskFile) -> URL?)? = nil
|
private var releaseNotesUrlCallback: ((NVCaskFile) -> URL?)? = nil
|
||||||
private var caskFile: NVCaskFile!
|
private var caskFile: NVCaskFile!
|
||||||
@@ -59,15 +60,21 @@ open class UpdateCheck
|
|||||||
*
|
*
|
||||||
* - Parameter caskUrl: The URL where the Cask file is expected to be located. Redirects will
|
* - Parameter caskUrl: The URL where the Cask file is expected to be located. Redirects will
|
||||||
* be followed when retrieving and validating the Cask file.
|
* be followed when retrieving and validating the Cask file.
|
||||||
|
*
|
||||||
|
* - Parameter isInteractive: 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(
|
public init(
|
||||||
selfUpdaterName: String,
|
selfUpdaterName: String,
|
||||||
selfUpdaterPath: String,
|
selfUpdaterPath: String,
|
||||||
caskUrl: URL
|
caskUrl: URL,
|
||||||
|
isInteractive: Bool
|
||||||
) {
|
) {
|
||||||
self.selfUpdaterName = selfUpdaterName
|
self.selfUpdaterName = selfUpdaterName
|
||||||
self.selfUpdaterPath = selfUpdaterPath
|
self.selfUpdaterPath = selfUpdaterPath
|
||||||
self.caskUrl = caskUrl
|
self.caskUrl = caskUrl
|
||||||
|
self.isInteractive = isInteractive
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,15 +89,11 @@ open class UpdateCheck
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform the check for a new version.
|
* 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 func perform(promptOnFailure: Bool = true) async {
|
public func perform() async {
|
||||||
guard let caskFile = NVCaskFile.from(url: caskUrl) else {
|
guard let caskFile = NVCaskFile.from(url: caskUrl) else {
|
||||||
Log.text("The contents of the CaskFile at '\(caskUrl.absoluteString)' could not be retrieved.")
|
Log.text("The contents of the CaskFile at '\(caskUrl.absoluteString)' could not be retrieved.")
|
||||||
return await presentCouldNotRetrieveUpdate(promptOnFailure)
|
return await presentCouldNotRetrieveUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
self.caskFile = caskFile
|
self.caskFile = caskFile
|
||||||
@@ -99,7 +102,7 @@ open class UpdateCheck
|
|||||||
|
|
||||||
guard let onlineVersion = AppVersion.from(caskFile.version) else {
|
guard let onlineVersion = AppVersion.from(caskFile.version) else {
|
||||||
Log.text("The version string from the CaskFile could not be read.")
|
Log.text("The version string from the CaskFile could not be read.")
|
||||||
return await presentCouldNotRetrieveUpdate(promptOnFailure)
|
return await presentCouldNotRetrieveUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
self.newerVersion = onlineVersion
|
self.newerVersion = onlineVersion
|
||||||
@@ -108,29 +111,19 @@ open class UpdateCheck
|
|||||||
Log.text("The current version is v\(currentVersion.computerReadable).")
|
Log.text("The current version is v\(currentVersion.computerReadable).")
|
||||||
|
|
||||||
if onlineVersion > currentVersion {
|
if onlineVersion > currentVersion {
|
||||||
|
// A newer version is available
|
||||||
await presentNewerVersionAvailable()
|
await presentNewerVersionAvailable()
|
||||||
} else if promptOnFailure {
|
} else {
|
||||||
await presentVersionIsUpToDate(promptOnFailure)
|
await presentVersionUpToDate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Alerts
|
// MARK: - Alerts
|
||||||
|
|
||||||
private func presentCouldNotRetrieveUpdate(_ promptOnFailure: Bool) async {
|
private func presentVersionUpToDate() async {
|
||||||
Log.text("Could not retrieve update manifest!")
|
Log.text("Application is up-to-date!")
|
||||||
|
|
||||||
if promptOnFailure {
|
if isInteractive {
|
||||||
await Alert.confirm(
|
|
||||||
title: translations.couldNotRetrieveUpdateTitle,
|
|
||||||
description: translations.couldNotRetrieveUpdateDescription
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func presentVersionIsUpToDate(_ promptOnFailure: Bool) async {
|
|
||||||
Log.text("Version is up-to-date!")
|
|
||||||
|
|
||||||
if promptOnFailure {
|
|
||||||
await Alert.confirm(
|
await Alert.confirm(
|
||||||
title: translations.appIsUpToDateTitle
|
title: translations.appIsUpToDateTitle
|
||||||
.replacingOccurrences(of: "%@", with: Executable.name),
|
.replacingOccurrences(of: "%@", with: Executable.name),
|
||||||
@@ -139,6 +132,17 @@ open class UpdateCheck
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func presentCouldNotRetrieveUpdate() async {
|
||||||
|
Log.text("Could not retrieve update manifest!")
|
||||||
|
|
||||||
|
if isInteractive {
|
||||||
|
await Alert.confirm(
|
||||||
|
title: translations.couldNotRetrieveUpdateTitle,
|
||||||
|
description: translations.couldNotRetrieveUpdateDescription
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func presentNewerVersionAvailable() async {
|
private func presentNewerVersionAvailable() async {
|
||||||
Log.text("A newer version is available!")
|
Log.text("A newer version is available!")
|
||||||
|
|
||||||
@@ -167,7 +171,7 @@ open class UpdateCheck
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await alert.show()
|
await alert.show(urgency: isInteractive ? .bringToFront : .urgentRequestAttention)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Functional
|
// MARK: - Functional
|
||||||
|
|||||||
Reference in New Issue
Block a user