import AppKitimport SwiftUI @MainActorstruct AboutPane: View { let updater: UpdaterProviding @State private var iconHover = false @AppStorage("autoUpdateEnabled") private var autoUpdateEnabled: Bool = true @State private var didLoadUpdaterState = false private var versionString: String { let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "–" let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String return build.map { "\(version) (\($0))" } ?? version } private var buildTimestamp: String? { guard let raw = Bundle.main.object(forInfoDictionaryKey: "CodexBuildTimestamp") as? String else { return nil } let parser = ISO8601DateFormatter() parser.formatOptions = [.withInternetDateTime] guard let date = parser.date(from: raw) else { return raw } let formatter = DateFormatter() formatter.dateStyle = .medium formatter.timeStyle = .short formatter.locale = .current return formatter.string(from: date) } var body: some View { VStack(spacing: 12) { if let image = NSApplication.shared.applicationIconImage { Button(action: self.openProjectHome) { Image(nsImage: image) .resizable() .frame(width: 92, height: 92) .cornerRadius(16) .scaleEffect(self.iconHover ? 1.05 : 1.0) .shadow(color: self.iconHover ? .accentColor.opacity(0.25) : .clear, radius: 6) } .buttonStyle(.plain) .onHover { hovering in withAnimation(.spring(response: 0.32, dampingFraction: 0.78)) { self.iconHover = hovering } } } VStack(spacing: 2) { Text("CodexBar") .font(.title3).bold() Text("Version \(self.versionString)") .foregroundStyle(.secondary) if let buildTimestamp { Text("Built \(buildTimestamp)") .font(.footnote) .foregroundStyle(.secondary) } Text("May your tokens never run out—keep agent limits in view.") .font(.footnote) .foregroundStyle(.secondary) } VStack(alignment: .leading, spacing: 12) { // Original Author Section VStack(alignment: .leading, spacing: 6) { Text("Original Author") .font(.caption) .foregroundStyle(.secondary) VStack(alignment: .leading, spacing: 4) { AboutLinkRow( icon: "chevron.left.slash.chevron.right", title: "GitHub (steipete)", url: "https://github.com/steipete/CodexBar") AboutLinkRow(icon: "globe", title: "codexbar.app", url: "https://codexbar.app") } } Divider() // Fork Maintainer Section VStack(alignment: .leading, spacing: 6) { Text("Fork Maintainer") .font(.caption) .foregroundStyle(.secondary) VStack(alignment: .leading, spacing: 4) { AboutLinkRow( icon: "chevron.left.slash.chevron.right", title: "GitHub (bcharleson)", url: "https://github.com/bcharleson/codexbar") AboutLinkRow(icon: "globe", title: "topoffunnel.com", url: "https://topoffunnel.com") } } } .padding(.top, 8) .frame(maxWidth: .infinity, alignment: .leading) .padding(.horizontal, 20) Divider() if self.updater.isAvailable { VStack(spacing: 10) { Toggle("Check for updates automatically", isOn: self.$autoUpdateEnabled) .toggleStyle(.checkbox) .frame(maxWidth: .infinity, alignment: .center) Button("Check for Updates…") { self.updater.checkForUpdates(nil) } } } else { Text(self.updater.unavailableReason ?? "Updates unavailable in this build.") .foregroundStyle(.secondary) } VStack(spacing: 2) { Text("Originally created by Peter Steinberger") .font(.footnote) .foregroundStyle(.secondary) Text("Enhanced and maintained by Brandon Charleson") .font(.footnote) .foregroundStyle(.secondary) Text("MIT License") .font(.footnote) .foregroundStyle(.secondary) } .padding(.top, 4) Spacer(minLength: 0) } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) .padding(.top, 4) .padding(.horizontal, 24) .padding(.bottom, 24) .onAppear { guard !self.didLoadUpdaterState else { return } // Align Sparkle's flag with the persisted preference on first load. self.updater.automaticallyChecksForUpdates = self.autoUpdateEnabled self.updater.automaticallyDownloadsUpdates = self.autoUpdateEnabled self.didLoadUpdaterState = true } .onChange(of: self.autoUpdateEnabled) { _, newValue in self.updater.automaticallyChecksForUpdates = newValue self.updater.automaticallyDownloadsUpdates = newValue } } private func openProjectHome() { guard let url = URL(string: "https://github.com/bcharleson/codexbar") else { return } NSWorkspace.shared.open(url) }}
import AppKit
import SwiftUI
@MainActor
struct AboutPane: View {
let updater: UpdaterProviding
@State private var iconHover = false
@AppStorage("autoUpdateEnabled") private var autoUpdateEnabled: Bool = true
@State private var didLoadUpdaterState = false
private var versionString: String {
let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "–"
let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String
return build.map { "\(version) (\($0))" } ?? version
}
private var buildTimestamp: String? {
guard let raw = Bundle.main.object(forInfoDictionaryKey: "CodexBuildTimestamp") as? String else { return nil }
let parser = ISO8601DateFormatter()
parser.formatOptions = [.withInternetDateTime]
guard let date = parser.date(from: raw) else { return raw }
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
formatter.locale = .current
return formatter.string(from: date)
}
var body: some View {
VStack(spacing: 12) {
if let image = NSApplication.shared.applicationIconImage {
Button(action: self.openProjectHome) {
Image(nsImage: image)
.resizable()
.frame(width: 92, height: 92)
.cornerRadius(16)
.scaleEffect(self.iconHover ? 1.05 : 1.0)
.shadow(color: self.iconHover ? .accentColor.opacity(0.25) : .clear, radius: 6)
}
.buttonStyle(.plain)
.onHover { hovering in
withAnimation(.spring(response: 0.32, dampingFraction: 0.78)) {
self.iconHover = hovering
}
}
}
VStack(spacing: 2) {
Text("CodexBar")
.font(.title3).bold()
Text("Version \(self.versionString)")
.foregroundStyle(.secondary)
if let buildTimestamp {
Text("Built \(buildTimestamp)")
.font(.footnote)
.foregroundStyle(.secondary)
}
Text("May your tokens never run out—keep agent limits in view.")
.font(.footnote)
.foregroundStyle(.secondary)
}
VStack(alignment: .leading, spacing: 12) {
// Original Author Section
VStack(alignment: .leading, spacing: 6) {
Text("Original Author")
.font(.caption)
.foregroundStyle(.secondary)
VStack(alignment: .leading, spacing: 4) {
AboutLinkRow(
icon: "chevron.left.slash.chevron.right",
title: "GitHub (steipete)",
url: "https://github.com/steipete/CodexBar")
AboutLinkRow(icon: "globe", title: "codexbar.app", url: "https://codexbar.app")
}
}
Divider()
// Fork Maintainer Section
VStack(alignment: .leading, spacing: 6) {
Text("Fork Maintainer")
.font(.caption)
.foregroundStyle(.secondary)
VStack(alignment: .leading, spacing: 4) {
AboutLinkRow(
icon: "chevron.left.slash.chevron.right",
title: "GitHub (bcharleson)",
url: "https://github.com/bcharleson/codexbar")
AboutLinkRow(icon: "globe", title: "topoffunnel.com", url: "https://topoffunnel.com")
}
}
}
.padding(.top, 8)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, 20)
Divider()
if self.updater.isAvailable {
VStack(spacing: 10) {
Toggle("Check for updates automatically", isOn: self.$autoUpdateEnabled)
.toggleStyle(.checkbox)
.frame(maxWidth: .infinity, alignment: .center)
Button("Check for Updates…") { self.updater.checkForUpdates(nil) }
}
} else {
Text(self.updater.unavailableReason ?? "Updates unavailable in this build.")
.foregroundStyle(.secondary)
}
VStack(spacing: 2) {
Text("Originally created by Peter Steinberger")
.font(.footnote)
.foregroundStyle(.secondary)
Text("Enhanced and maintained by Brandon Charleson")
.font(.footnote)
.foregroundStyle(.secondary)
Text("MIT License")
.font(.footnote)
.foregroundStyle(.secondary)
}
.padding(.top, 4)
Spacer(minLength: 0)
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
.padding(.top, 4)
.padding(.horizontal, 24)
.padding(.bottom, 24)
.onAppear {
guard !self.didLoadUpdaterState else { return }
// Align Sparkle's flag with the persisted preference on first load.
self.updater.automaticallyChecksForUpdates = self.autoUpdateEnabled
self.updater.automaticallyDownloadsUpdates = self.autoUpdateEnabled
self.didLoadUpdaterState = true
}
.onChange(of: self.autoUpdateEnabled) { _, newValue in
self.updater.automaticallyChecksForUpdates = newValue
self.updater.automaticallyDownloadsUpdates = newValue
}
}
private func openProjectHome() {
guard let url = URL(string: "https://github.com/bcharleson/codexbar") else { return }
NSWorkspace.shared.open(url)
}
}