swiftui-multiplatform/macOS/Settings/MacUpdatesViewModel.swift
Angelo Stavrow 549ad3039f
Clean up project warnings (#199)
* Set "recommended project settings" for Mac app

* Add default fallback for font typingAttribute

* Clean up linter errors

* Update extension iconset

* Fix spm errors and upgrade sparkle (#203)

* Switch WriteFreely package import from ssh to https

* Sign macOS project target for Development

This fixes a crash-on-launch bug when running Product > Run from Xcode (Product > Archive should work correctly). See https://github.com/sparkle-project/Sparkle/issues/2056 for more details.

Bug introduced by commit:
671b0540ac

* Update Sparkle to v2.0 from official repo

Previously, we forked the repo to the WriteFreely org because Sparkle didn't support tag-based SPM updates. We therefore had to pull from the `master` branch, so forking insulated us from unexpected changes.

As of 2.x Sparkle now allows for tag-based updating via SPM; we'll allow patch updates but stop short of 2.1 until we can vet changes.

* Add MacUpdatesViewModel ObservableObject

* Use MacUpdatesViewModel to handle Sparkle update logic
2022-04-02 08:04:50 -04:00

74 lines
2.4 KiB
Swift

/// See https://sparkle-project.org/documentation/programmatic-setup#create-an-updater-in-swiftui
import SwiftUI
import Sparkle
/// This view model class manages Sparkle's updater and publishes when new updates are allowed to be checked.
final class MacUpdatesViewModel: ObservableObject {
@Published var canCheckForUpdates = false
private let updaterController: SPUStandardUpdaterController
private let updaterDelegate = MacUpdatesViewModelDelegate()
var automaticallyCheckForUpdates: Bool {
get {
return updaterController.updater.automaticallyChecksForUpdates
}
set(newValue) {
updaterController.updater.automaticallyChecksForUpdates = newValue
}
}
init() {
updaterController = SPUStandardUpdaterController(startingUpdater: true,
updaterDelegate: updaterDelegate,
userDriverDelegate: nil)
updaterController.updater.publisher(for: \.canCheckForUpdates)
.assign(to: &$canCheckForUpdates)
if automaticallyCheckForUpdates {
updaterController.updater.checkForUpdatesInBackground()
}
}
func checkForUpdates() {
updaterController.checkForUpdates(nil)
}
func getLastUpdateCheckDate() -> Date? {
return updaterController.updater.lastUpdateCheckDate
}
@discardableResult
func toggleAllowedChannels() -> Set<String> {
return updaterDelegate.allowedChannels(for: updaterController.updater)
}
}
final class MacUpdatesViewModelDelegate: NSObject, SPUUpdaterDelegate {
@AppStorage(WFDefaults.subscribeToBetaUpdates, store: UserDefaults.shared)
var subscribeToBetaUpdates: Bool = false
func allowedChannels(for updater: SPUUpdater) -> Set<String> {
let allowedChannels = Set(subscribeToBetaUpdates ? ["beta"] : [])
return allowedChannels
}
}
// This additional view is needed for the disabled state on the menu item to work properly before Monterey.
// See https://stackoverflow.com/questions/68553092/menu-not-updating-swiftui-bug for more information
struct CheckForUpdatesView: View {
@ObservedObject var updaterViewModel: MacUpdatesViewModel
var body: some View {
Button("Check for Updates…", action: updaterViewModel.checkForUpdates)
.disabled(!updaterViewModel.canCheckForUpdates)
}
}