Add GitHub update checker and installer

This commit is contained in:
世界
2026-03-30 23:02:42 +08:00
parent 6b790c7a80
commit 63d1d0fe3f
15 changed files with 1663 additions and 2 deletions
+71
View File
@@ -9,7 +9,9 @@ public struct MacApplication: Scene {
@State private var showMenuBarExtra = false
@State private var menuBarExtraSpeedMode = MenuBarExtraSpeedMode.enabled.rawValue
@StateObject private var environments = ExtensionEnvironments()
@StateObject private var updateManager = UpdateManager()
@State private var statusBarController: StatusBarController?
@State private var showUpdateCheckPrompt = false
private let profileEditor: (Binding<String>, Bool) -> AnyView = { text, isEditable in
AnyView(ProfileEditorWrapperView(text: text, isEditable: isEditable))
@@ -27,6 +29,32 @@ public struct MacApplication: Scene {
.environment(\.showMenuBarExtra, $showMenuBarExtra)
.environment(\.menuBarExtraSpeedMode, $menuBarExtraSpeedMode)
.environmentObject(environments)
.environmentObject(updateManager)
.alert(
"Check Update",
isPresented: $showUpdateCheckPrompt
) {
Button("Ok") {
Task {
await SharedPreferences.updateCheckPrompted.set(true)
await SharedPreferences.checkUpdateEnabled.set(true)
await runAutomaticUpdateCheck()
}
}
Button("No, thanks", role: .cancel) {
Task {
await SharedPreferences.updateCheckPrompted.set(true)
}
}
} message: {
Text("Would you like to enable automatic update checking from **GitHub**?")
}
.sheet(isPresented: $updateManager.isUpdateSheetPresented, onDismiss: {
updateManager.dismissUpdateSheet()
}) {
UpdateSheet(updateManager: updateManager)
.environmentObject(environments)
}
.onChangeCompat(of: showMenuBarExtra) { newValue in
statusBarController?.updateVisibility(newValue)
Task {
@@ -81,6 +109,49 @@ public struct MacApplication: Scene {
statusBarController = StatusBarController(environments: environments)
statusBarController?.updateVisibility(showMenuBarExtra)
statusBarController?.updateSpeedMode(menuBarExtraSpeedMode)
if Variant.useSystemExtension {
let shouldPresentCachedUpdate = await updateManager.loadCachedUpdate()
let checkUpdateEnabled = await SharedPreferences.checkUpdateEnabled.get()
let prompted = await SharedPreferences.updateCheckPrompted.get()
if !prompted {
showUpdateCheckPrompt = true
} else if checkUpdateEnabled {
if shouldPresentCachedUpdate {
await presentUpdateSheet()
}
Task {
await runAutomaticUpdateCheck()
}
}
}
}
private func runAutomaticUpdateCheck() async {
let shouldPresent = await updateManager.checkForUpdate(presentIfFound: true, showsAlertOnFailure: false)
if shouldPresent {
await presentUpdateSheet()
}
}
private func presentUpdateSheet() async {
guard updateManager.updateInfo != nil else { return }
await openMainWindowIfNeeded()
await updateManager.showUpdateSheet()
}
private func openMainWindowIfNeeded() async {
let mainWindow = NSApp.windows.first(where: { $0.identifier?.rawValue == "main" })
let shouldActivate = NSApp.activationPolicy() == .accessory || !(mainWindow?.isVisible ?? false) || !NSApp.isActive
guard shouldActivate else { return }
NSApp.setActivationPolicy(.regular)
mainWindow?.makeKeyAndOrderFront(nil)
if let dockApp = NSRunningApplication.runningApplications(withBundleIdentifier: "com.apple.dock").first {
dockApp.activate()
try? await Task.sleep(for: .milliseconds(100))
}
NSApp.activate(ignoringOtherApps: true)
}
private func hide(closeApp: Bool) {