mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-04-29 23:49:39 +00:00
feat(mac): auto-update checker and Plan pane button cleanup
Remove the broken "Connect Claude" / "Reconnect Claude" buttons from the Plan pane -- they opened a terminal session that did nothing useful for already-logged-in users. Keep only the "Retry" button. Add an auto-update checker that queries GitHub releases every 2 days in the background. When a newer menubar build is available, an "Update" pill appears in the header. Clicking it runs the existing installer flow (download, replace, relaunch) with no manual steps.
This commit is contained in:
parent
72ccf34a5a
commit
bc92b49c1b
4 changed files with 153 additions and 59 deletions
87
mac/Sources/CodeBurnMenubar/Data/UpdateChecker.swift
Normal file
87
mac/Sources/CodeBurnMenubar/Data/UpdateChecker.swift
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
import Foundation
|
||||
import Observation
|
||||
|
||||
private let releasesAPI = "https://api.github.com/repos/getagentseal/codeburn/releases/latest"
|
||||
private let checkIntervalSeconds: TimeInterval = 2 * 24 * 60 * 60
|
||||
private let lastCheckKey = "UpdateChecker.lastCheckDate"
|
||||
private let cachedVersionKey = "UpdateChecker.latestVersion"
|
||||
|
||||
@MainActor
|
||||
@Observable
|
||||
final class UpdateChecker {
|
||||
var latestVersion: String?
|
||||
var isUpdating = false
|
||||
var updateError: String?
|
||||
|
||||
var updateAvailable: Bool {
|
||||
guard let latest = latestVersion else { return false }
|
||||
let current = currentVersion
|
||||
return !current.isEmpty && current != "dev" && latest != current
|
||||
}
|
||||
|
||||
var currentVersion: String {
|
||||
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
|
||||
}
|
||||
|
||||
func checkIfNeeded() async {
|
||||
let lastCheck = UserDefaults.standard.double(forKey: lastCheckKey)
|
||||
let now = Date().timeIntervalSince1970
|
||||
if now - lastCheck < checkIntervalSeconds {
|
||||
latestVersion = UserDefaults.standard.string(forKey: cachedVersionKey)
|
||||
return
|
||||
}
|
||||
await check()
|
||||
}
|
||||
|
||||
func check() async {
|
||||
guard let url = URL(string: releasesAPI) else { return }
|
||||
var request = URLRequest(url: url)
|
||||
request.setValue("codeburn-menubar-updater", forHTTPHeaderField: "User-Agent")
|
||||
request.setValue("application/vnd.github+json", forHTTPHeaderField: "Accept")
|
||||
|
||||
do {
|
||||
let (data, _) = try await URLSession.shared.data(for: request)
|
||||
let release = try JSONDecoder().decode(GitHubRelease.self, from: data)
|
||||
guard let asset = release.assets.first(where: {
|
||||
$0.name.hasPrefix("CodeBurnMenubar-") && $0.name.hasSuffix(".zip")
|
||||
}) else { return }
|
||||
|
||||
let version = asset.name
|
||||
.replacingOccurrences(of: "CodeBurnMenubar-", with: "")
|
||||
.replacingOccurrences(of: ".zip", with: "")
|
||||
|
||||
latestVersion = version
|
||||
UserDefaults.standard.set(Date().timeIntervalSince1970, forKey: lastCheckKey)
|
||||
UserDefaults.standard.set(version, forKey: cachedVersionKey)
|
||||
} catch {
|
||||
NSLog("CodeBurn: update check failed: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func performUpdate() {
|
||||
isUpdating = true
|
||||
updateError = nil
|
||||
|
||||
let process = CodeburnCLI.makeProcess(subcommand: ["menubar", "--force"])
|
||||
process.standardOutput = FileHandle.nullDevice
|
||||
process.standardError = FileHandle.nullDevice
|
||||
|
||||
do {
|
||||
try process.run()
|
||||
} catch {
|
||||
isUpdating = false
|
||||
updateError = error.localizedDescription
|
||||
NSLog("CodeBurn: update spawn failed: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct GitHubRelease: Decodable {
|
||||
let tag_name: String
|
||||
let assets: [GitHubAsset]
|
||||
}
|
||||
|
||||
private struct GitHubAsset: Decodable {
|
||||
let name: String
|
||||
let browser_download_url: String
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue