Compare commits

..
13 Commits
Author SHA1 Message Date
James Bone abf05b04fc v1.1.1 — clearer limit labels and login window fix 2026-05-07 22:25:26 +02:00
github-actions[bot] 849e94c942 Release v1.1.0 2026-05-07 16:34:12 +00:00
superdooper86 d76c7496bb Release v1.1.0 2026-05-07 18:33:04 +02:00
github-actions[bot] 45a3925f65 Release v1.0.12 2026-05-07 16:29:13 +00:00
superdooper86 113e91583d Release v1.0.12 2026-05-07 18:28:11 +02:00
github-actions[bot] c60fb93e1a Release v1.0.11 2026-05-07 16:24:21 +00:00
superdooper86 b16c24cb44 Release v1.0.11 — update indicator in menubar, undismissable banner
- Menubar shows ↑ Update alongside limits when an update is available
- Removed × dismiss button from update banner; it stays until installed
2026-05-07 18:23:26 +02:00
superdooper86 89a79c6f13 Temporary: bump version.json to 1.1.1 for update testing 2026-05-07 18:14:08 +02:00
github-actions[bot] aa529835f7 Release v1.0.10 2026-05-07 16:13:13 +00:00
superdooper86 b5c3cc6379 Rerelease as v1.0.10 (was incorrectly versioned as v1.1.0) 2026-05-07 18:11:45 +02:00
github-actions[bot] c8adaf1baf Release v1.1.0 2026-05-07 16:02:51 +00:00
superdooper86 3e99e1417e Release v1.1.0 — always open to main window
Post popoverWillOpen notification on show; ContentView resets showSettings
on receive so reopening always lands on the main window, not Settings.
2026-05-07 18:02:04 +02:00
github-actions[bot] e41d3d0c0f Release v1.0.9 2026-05-07 15:56:24 +00:00
8 changed files with 71 additions and 26 deletions
+14 -1
View File
@@ -60,6 +60,11 @@ class AppDelegate: NSObject, NSApplicationDelegate {
.sink { [weak self] _ in self?.updateStatusItem() }
.store(in: &cancellables)
updateManager.$updateAvailable
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in self?.updateStatusItem() }
.store(in: &cancellables)
// Refresh timer
scheduleTimer(interval: usageViewModel.refreshInterval)
@@ -166,7 +171,13 @@ class AppDelegate: NSObject, NSApplicationDelegate {
let sdStr = sd.map { "\(Int($0.usedPercent.rounded()))%" } ?? ""
button.image = nil
button.attributedTitle = NSAttributedString(string: "")
button.title = "\(fhStr) \(sdStr)"
let updatePrefix = updateManager.updateAvailable ? "↑ Update " : ""
button.title = "\(updatePrefix)\(fhStr) \(sdStr)"
button.font = NSFont.monospacedDigitSystemFont(ofSize: 12, weight: .medium)
} else if updateManager.updateAvailable {
button.image = nil
button.attributedTitle = NSAttributedString(string: "")
button.title = "↑ Update"
button.font = NSFont.monospacedDigitSystemFont(ofSize: 12, weight: .medium)
} else {
button.title = ""
@@ -199,6 +210,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
@objc func showPopover() {
guard let button = statusItem?.button, let popover else { return }
if !popover.isShown {
NotificationCenter.default.post(name: .popoverWillOpen, object: nil)
popover.show(relativeTo: button.bounds, of: button, preferredEdge: .minY)
NSApp.activate(ignoringOtherApps: true)
}
@@ -209,6 +221,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
if popover.isShown {
popover.performClose(nil)
} else {
NotificationCenter.default.post(name: .popoverWillOpen, object: nil)
popover.show(relativeTo: button.bounds, of: button, preferredEdge: .minY)
NSApp.activate(ignoringOtherApps: true)
}
+23 -10
View File
@@ -47,13 +47,29 @@ struct ContentView: View {
EmptyStateView()
.padding(.vertical, 40)
} else {
VStack(spacing: 1) {
VStack(spacing: 8) {
ForEach(vm.limits) { limit in
LimitCard(limit: limit)
VStack(spacing: 0) {
HStack {
Text(limit.window == .fiveHour ? "5hr Limit" : "7 Day Limit")
.font(.system(size: 11, weight: .semibold))
.foregroundColor(.secondary)
.textCase(.uppercase)
Spacer()
}
.padding(.horizontal, 16)
.padding(.top, 10)
.padding(.bottom, 4)
LimitCard(limit: limit)
.background(Color(nsColor: .controlBackgroundColor))
.cornerRadius(8)
.overlay(RoundedRectangle(cornerRadius: 8).stroke(Color.primary.opacity(0.08), lineWidth: 0.5))
.padding(.horizontal, 8)
}
}
}
.background(Color.primary.opacity(0.05))
.padding(.vertical, 1)
.padding(.bottom, 4)
// Extra credits row
if let extra = vm.extraUsage, extra.isEnabled {
@@ -94,6 +110,9 @@ struct ContentView: View {
}
.frame(width: 480)
.animation(.easeInOut(duration: 0.2), value: showSettings)
.onReceive(NotificationCenter.default.publisher(for: .popoverWillOpen)) { _ in
showSettings = false
}
.onReceive(NotificationCenter.default.publisher(for: .openUpdateSheet)) { _ in
showSettings = false
showUpdateSheet = true
@@ -1029,12 +1048,6 @@ struct UpdateBanner: View {
Button("Update") { showSheet = true }
.buttonStyle(.borderedProminent)
.controlSize(.small)
Button { updater.updateAvailable = false } label: {
Image(systemName: "xmark")
.font(.system(size: 10, weight: .medium))
.foregroundColor(.secondary)
}
.buttonStyle(.plain)
}
.padding(.horizontal, 16)
.padding(.vertical, 10)
+2 -2
View File
@@ -15,9 +15,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.9</string>
<string>1.1.1</string>
<key>CFBundleVersion</key>
<string>28</string>
<string>34</string>
<key>LSMinimumSystemVersion</key>
<string>13.0</string>
<key>LSUIElement</key>
+21 -6
View File
@@ -24,21 +24,27 @@ struct LoginWebView: NSViewRepresentable {
class Coordinator: NSObject, WKNavigationDelegate {
let onAuthenticated: () -> Void
var didAuthenticate = false
init(onAuthenticated: @escaping () -> Void) {
self.onAuthenticated = onAuthenticated
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
guard !didAuthenticate else { return }
// Don't fire on the login/auth pages themselves
if let url = webView.url?.absoluteString,
url.contains("/login") || url.contains("/auth") { return }
WKWebsiteDataStore.default().httpCookieStore.getAllCookies { cookies in
let hasSession = cookies.contains {
$0.domain.contains("claude.ai") &&
($0.name == "sessionKey" || $0.name == "__Secure-next-auth.session-token")
}
if hasSession {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.onAuthenticated()
}
guard hasSession, !self.didAuthenticate else { return }
self.didAuthenticate = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.onAuthenticated()
}
}
}
@@ -58,9 +64,18 @@ struct LoginSheetView: View {
Text(authenticated ? "✓ Signed in — loading data…" : "Sign in to Claude")
.font(.system(size: 13, weight: .semibold))
Spacer()
Button("Cancel") { isPresented = false }
.buttonStyle(.bordered)
if authenticated {
Button("Done") {
isPresented = false
onDone()
}
.buttonStyle(.borderedProminent)
.controlSize(.small)
} else {
Button("Cancel") { isPresented = false }
.buttonStyle(.bordered)
.controlSize(.small)
}
}
.padding(.horizontal, 14)
.padding(.vertical, 10)
+1
View File
@@ -307,6 +307,7 @@ extension Notification.Name {
static let refreshIntervalChanged = Notification.Name("refreshIntervalChanged")
static let closePopover = Notification.Name("closePopover")
static let showPopover = Notification.Name("showPopover")
static let popoverWillOpen = Notification.Name("popoverWillOpen")
static let updateDetected = Notification.Name("updateDetected")
static let limitWarning = Notification.Name("limitWarning")
static let limitReset = Notification.Name("limitReset")
+1 -1
View File
@@ -8,7 +8,7 @@
[![macOS](https://img.shields.io/badge/macOS-13.0+-000000?style=flat&logo=apple&logoColor=white)](https://www.apple.com/macos/)
[![Swift](https://img.shields.io/badge/Swift-5.9-F05138?style=flat&logo=swift&logoColor=white)](https://swift.org)
[![Version](https://img.shields.io/badge/version-1.0.8-orange?style=flat)](https://github.com/superdooper86/claudechecker/releases)
[![Version](https://img.shields.io/badge/version-1.1.0-orange?style=flat)](https://github.com/superdooper86/claudechecker/releases)
[![License](https://img.shields.io/badge/license-MIT-blue?style=flat)](LICENSE)
</div>
+6 -3
View File
@@ -1,4 +1,7 @@
## What's new in v1.0.9
## What's new in v1.1.1
### Fixed update notification popup
The notification popup now correctly shows **"Tap to view release notes & update now!"** instead of the raw markdown release notes text.
### Clearer limit labels
The 5hr and 7 Day usage cards now have clear section headers so it's immediately obvious which limit is which.
### Login window fix
The sign-in sheet now reliably closes after a successful login. A **Done** button also appears as a fallback once authentication is detected — no more being stuck with only a Cancel button.
+3 -3
View File
@@ -1,5 +1,5 @@
{
"version": "1.0.8",
"url": "https://github.com/superdooper86/claudechecker/releases/download/v1.0.8/ClaudeChecker.zip",
"notes": "## What's new in v1.0.8\n\n### Release notes now render correctly\nFixed markdown rendering in the update banner and update sheet — headers, **bold text**, and bullet points now display properly instead of showing raw `##` and `**` characters."
"version": "1.1.0",
"url": "https://github.com/superdooper86/claudechecker/releases/download/v1.1.0/ClaudeChecker.zip",
"notes": "## What's new in v1.1.0\n\n### Clickable notifications\nTapping a limit warning or reset notification opens the main window. Tapping an update notification opens the update sheet directly — no need to manually click the menubar icon.\n\n### Update indicator in menubar\nWhen an update is available, the menubar shows **↑ Update** alongside your usage percentages so you know at a glance without opening the app.\n\n### Release notes render correctly\nThe update banner and update sheet now render markdown formatting — headers, **bold text**, and bullet points display properly.\n\n### Update notification improved\nThe update popup now reads **\"Tap to view release notes & update now!\"** making it clear you can read what changed before installing.\n\n### Main window always opens on click\nClosing the app while Settings was open would cause the next click to reopen straight to Settings. The app now always returns to the main window."
}