mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-10-12 21:06:18 +00:00
macos: hook up our new update controller
This commit is contained in:
@@ -99,11 +99,10 @@ class AppDelegate: NSObject,
|
|||||||
)
|
)
|
||||||
|
|
||||||
/// Manages updates
|
/// Manages updates
|
||||||
let updaterController: SPUStandardUpdaterController
|
let updateController = UpdateController()
|
||||||
let updaterDelegate: UpdaterDelegate = UpdaterDelegate()
|
var updateViewModel: UpdateViewModel {
|
||||||
|
updateController.viewModel
|
||||||
/// Update view model for UI display
|
}
|
||||||
@Published private(set) var updateViewModel = UpdateViewModel()
|
|
||||||
|
|
||||||
/// The elapsed time since the process was started
|
/// The elapsed time since the process was started
|
||||||
var timeSinceLaunch: TimeInterval {
|
var timeSinceLaunch: TimeInterval {
|
||||||
@@ -130,15 +129,6 @@ class AppDelegate: NSObject,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
updaterController = SPUStandardUpdaterController(
|
|
||||||
// Important: we must not start the updater here because we need to read our configuration
|
|
||||||
// first to determine whether we're automatically checking, downloading, etc. The updater
|
|
||||||
// is started later in applicationDidFinishLaunching
|
|
||||||
startingUpdater: false,
|
|
||||||
updaterDelegate: updaterDelegate,
|
|
||||||
userDriverDelegate: nil
|
|
||||||
)
|
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
ghostty.delegate = self
|
ghostty.delegate = self
|
||||||
@@ -183,7 +173,7 @@ class AppDelegate: NSObject,
|
|||||||
ghosttyConfigDidChange(config: ghostty.config)
|
ghosttyConfigDidChange(config: ghostty.config)
|
||||||
|
|
||||||
// Start our update checker.
|
// Start our update checker.
|
||||||
updaterController.startUpdater()
|
updateController.startUpdater()
|
||||||
|
|
||||||
// Register our service provider. This must happen after everything is initialized.
|
// Register our service provider. This must happen after everything is initialized.
|
||||||
NSApp.servicesProvider = ServiceProvider()
|
NSApp.servicesProvider = ServiceProvider()
|
||||||
@@ -810,12 +800,12 @@ class AppDelegate: NSObject,
|
|||||||
// defined by our "auto-update" configuration (if set) or fall back to Sparkle
|
// defined by our "auto-update" configuration (if set) or fall back to Sparkle
|
||||||
// user-based defaults.
|
// user-based defaults.
|
||||||
if Bundle.main.infoDictionary?["SUEnableAutomaticChecks"] as? Bool == false {
|
if Bundle.main.infoDictionary?["SUEnableAutomaticChecks"] as? Bool == false {
|
||||||
updaterController.updater.automaticallyChecksForUpdates = false
|
updateController.updater.automaticallyChecksForUpdates = false
|
||||||
updaterController.updater.automaticallyDownloadsUpdates = false
|
updateController.updater.automaticallyDownloadsUpdates = false
|
||||||
} else if let autoUpdate = config.autoUpdate {
|
} else if let autoUpdate = config.autoUpdate {
|
||||||
updaterController.updater.automaticallyChecksForUpdates =
|
updateController.updater.automaticallyChecksForUpdates =
|
||||||
autoUpdate == .check || autoUpdate == .download
|
autoUpdate == .check || autoUpdate == .download
|
||||||
updaterController.updater.automaticallyDownloadsUpdates =
|
updateController.updater.automaticallyDownloadsUpdates =
|
||||||
autoUpdate == .download
|
autoUpdate == .download
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1008,7 +998,8 @@ class AppDelegate: NSObject,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func checkForUpdates(_ sender: Any?) {
|
@IBAction func checkForUpdates(_ sender: Any?) {
|
||||||
UpdateSimulator.permissionRequest.simulate(with: updateViewModel)
|
updateController.checkForUpdates()
|
||||||
|
//UpdateSimulator.permissionRequest.simulate(with: updateViewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
55
macos/Sources/Features/Update/UpdateController.swift
Normal file
55
macos/Sources/Features/Update/UpdateController.swift
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import Sparkle
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
/// Standard controller for managing Sparkle updates in Ghostty.
|
||||||
|
///
|
||||||
|
/// This controller wraps SPUStandardUpdaterController to provide a simpler interface
|
||||||
|
/// for managing updates with Ghostty's custom driver and delegate. It handles
|
||||||
|
/// initialization, starting the updater, and provides the check for updates action.
|
||||||
|
class UpdateController {
|
||||||
|
private(set) var updater: SPUUpdater
|
||||||
|
private let userDriver: UpdateDriver
|
||||||
|
private let updaterDelegate = UpdaterDelegate()
|
||||||
|
|
||||||
|
var viewModel: UpdateViewModel {
|
||||||
|
userDriver.viewModel
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialize a new update controller.
|
||||||
|
init() {
|
||||||
|
let hostBundle = Bundle.main
|
||||||
|
self.userDriver = UpdateDriver(viewModel: .init())
|
||||||
|
self.updater = SPUUpdater(
|
||||||
|
hostBundle: hostBundle,
|
||||||
|
applicationBundle: hostBundle,
|
||||||
|
userDriver: userDriver,
|
||||||
|
delegate: updaterDelegate
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start the updater.
|
||||||
|
///
|
||||||
|
/// This must be called before the updater can check for updates. If starting fails,
|
||||||
|
/// an error alert will be shown after a short delay.
|
||||||
|
func startUpdater() {
|
||||||
|
try? updater.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check for updates.
|
||||||
|
///
|
||||||
|
/// This is typically connected to a menu item action.
|
||||||
|
@objc func checkForUpdates() {
|
||||||
|
updater.checkForUpdates()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Validate the check for updates menu item.
|
||||||
|
///
|
||||||
|
/// - Parameter item: The menu item to validate
|
||||||
|
/// - Returns: Whether the menu item should be enabled
|
||||||
|
func validateMenuItem(_ item: NSMenuItem) -> Bool {
|
||||||
|
if item.action == #selector(checkForUpdates) {
|
||||||
|
return updater.canCheckForUpdates
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
@@ -1,13 +1,12 @@
|
|||||||
|
import Cocoa
|
||||||
import Sparkle
|
import Sparkle
|
||||||
|
|
||||||
/// Implement the SPUUserDriver to modify our UpdateViewModel for custom presentation.
|
/// Implement the SPUUserDriver to modify our UpdateViewModel for custom presentation.
|
||||||
class UpdateDriver: NSObject, SPUUserDriver {
|
class UpdateDriver: NSObject, SPUUserDriver {
|
||||||
let viewModel: UpdateViewModel
|
let viewModel: UpdateViewModel
|
||||||
let retryHandler: () -> Void
|
|
||||||
|
|
||||||
init(viewModel: UpdateViewModel, retryHandler: @escaping () -> Void) {
|
init(viewModel: UpdateViewModel) {
|
||||||
self.viewModel = viewModel
|
self.viewModel = viewModel
|
||||||
self.retryHandler = retryHandler
|
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +37,16 @@ class UpdateDriver: NSObject, SPUUserDriver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func showUpdaterError(_ error: any Error, acknowledgement: @escaping () -> Void) {
|
func showUpdaterError(_ error: any Error, acknowledgement: @escaping () -> Void) {
|
||||||
viewModel.state = .error(.init(error: error, retry: retryHandler, dismiss: { [weak viewModel] in
|
viewModel.state = .error(.init(
|
||||||
|
error: error,
|
||||||
|
retry: {
|
||||||
|
guard let delegate = NSApp.delegate as? AppDelegate else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO fill this in
|
||||||
|
},
|
||||||
|
dismiss: { [weak viewModel] in
|
||||||
viewModel?.state = .idle
|
viewModel?.state = .idle
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user