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:
iamtoruk 2026-04-19 03:33:37 -07:00 committed by AgentSeal
parent 72ccf34a5a
commit bc92b49c1b
4 changed files with 153 additions and 59 deletions

View file

@ -183,25 +183,61 @@ private struct BurnFlame: View {
}
private struct Header: View {
@Environment(UpdateChecker.self) private var updateChecker
var body: some View {
VStack(alignment: .leading, spacing: 1) {
(
Text("Code").foregroundStyle(.primary)
+ Text("Burn").foregroundStyle(Theme.brandAccent)
)
.font(.system(size: 13, weight: .semibold))
.tracking(-0.15)
Text("AI Coding Cost Tracker")
.font(.system(size: 10.5))
.foregroundStyle(.secondary)
HStack {
VStack(alignment: .leading, spacing: 1) {
(
Text("Code").foregroundStyle(.primary)
+ Text("Burn").foregroundStyle(Theme.brandAccent)
)
.font(.system(size: 13, weight: .semibold))
.tracking(-0.15)
Text("AI Coding Cost Tracker")
.font(.system(size: 10.5))
.foregroundStyle(.secondary)
}
Spacer()
if updateChecker.updateAvailable {
UpdateBadge()
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, 14)
.padding(.top, 10)
.padding(.bottom, 8)
}
}
private struct UpdateBadge: View {
@Environment(UpdateChecker.self) private var updateChecker
var body: some View {
Button {
updateChecker.performUpdate()
} label: {
HStack(spacing: 4) {
if updateChecker.isUpdating {
ProgressView()
.controlSize(.mini)
.scaleEffect(0.7)
} else {
Image(systemName: "arrow.down.circle.fill")
.font(.system(size: 10))
}
Text(updateChecker.isUpdating ? "Updating..." : "Update")
.font(.system(size: 10, weight: .medium))
}
.padding(.horizontal, 8)
.padding(.vertical, 4)
}
.buttonStyle(.borderedProminent)
.tint(Theme.brandAccent)
.controlSize(.mini)
.disabled(updateChecker.isUpdating)
}
}
struct FlameMark: View {
var body: some View {
ZStack {