Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94430e00ba | ||
|
|
7b0368b001 | ||
|
|
4629aeffbc | ||
|
|
2cb4ddfe97 | ||
|
|
73b251a1e9 | ||
|
|
7bab6a0df0 | ||
|
|
db6380fa66 | ||
|
|
47a148fa67 |
@@ -15,9 +15,9 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.2.0</string>
|
||||
<string>1.2.1-beta.2</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>48</string>
|
||||
<string>50</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>13.0</string>
|
||||
<key>LSUIElement</key>
|
||||
|
||||
@@ -12,7 +12,7 @@ struct LoginWebView: NSViewRepresentable {
|
||||
|
||||
let webView = WKWebView(frame: .zero, configuration: config)
|
||||
webView.navigationDelegate = context.coordinator
|
||||
webView.load(URLRequest(url: URL(string: "https://claude.ai/login")!))
|
||||
webView.load(URLRequest(url: URL(string: "https://claude.ai")!))
|
||||
return webView
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,16 @@ class UsageViewModel: ObservableObject {
|
||||
burnHistoryStore = saved
|
||||
}
|
||||
loadPlaceholderData()
|
||||
Task { await checkInitialSignInState() }
|
||||
}
|
||||
|
||||
private func checkInitialSignInState() async {
|
||||
let cookies = await WKWebsiteDataStore.default().httpCookieStore.allCookies()
|
||||
let hasSession = cookies.contains {
|
||||
$0.domain.contains("claude.ai") &&
|
||||
($0.name == "sessionKey" || $0.name == "__Secure-next-auth.session-token")
|
||||
}
|
||||
if hasSession { isSignedIn = true }
|
||||
}
|
||||
|
||||
func signOut() async {
|
||||
@@ -140,11 +150,22 @@ class UsageViewModel: ObservableObject {
|
||||
let memberships = (account?["memberships"] ?? json["memberships"]) as? [[String: Any]]
|
||||
let firstOrg = memberships?.first?["organization"] as? [String: Any]
|
||||
|
||||
// org ID — primary path then flat-list fallback
|
||||
// org ID — primary path then flat-list fallback then dedicated endpoint
|
||||
var orgId: String? = firstOrg?["uuid"] as? String
|
||||
if orgId == nil {
|
||||
orgId = (json["organizations"] as? [[String: Any]])?.first?["uuid"] as? String
|
||||
}
|
||||
if orgId == nil, let cookie = await claudeCookieHeader() {
|
||||
// Final fallback: fetch /api/organizations directly
|
||||
var orgsReq = URLRequest(url: URL(string: "https://claude.ai/api/organizations")!)
|
||||
orgsReq.setValue("application/json", forHTTPHeaderField: "accept")
|
||||
orgsReq.setValue(cookie, forHTTPHeaderField: "Cookie")
|
||||
if let (orgsData, orgsResp) = try? await URLSession.shared.data(for: orgsReq),
|
||||
let orgsHttp = orgsResp as? HTTPURLResponse, orgsHttp.statusCode == 200,
|
||||
let orgs = try? JSONSerialization.jsonObject(with: orgsData) as? [[String: Any]] {
|
||||
orgId = orgs.first?["uuid"] as? String
|
||||
}
|
||||
}
|
||||
|
||||
let email = account?["email_address"] as? String
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
[](https://www.apple.com/macos/)
|
||||
[](https://swift.org)
|
||||
[](https://github.com/superdooper86/claudechecker/releases)
|
||||
[](https://github.com/superdooper86/claudechecker/releases)
|
||||
[](LICENSE)
|
||||
[](https://github.com/superdooper86/claudechecker/releases/tag/v1.1.4-beta.7) <!-- BETA_BADGE -->
|
||||
[](https://github.com/superdooper86/claudechecker/releases/tag/v1.2.1-beta.1) <!-- BETA_BADGE -->
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
+6
-9
@@ -1,11 +1,8 @@
|
||||
## What's new in v1.2.0
|
||||
## What's new in v1.2.1
|
||||
|
||||
### Bug fixes
|
||||
- App now works for all users — org ID is fetched dynamically from the API instead of being hardcoded
|
||||
- Plan name (e.g. Pro, Max) now updates correctly on every refresh
|
||||
|
||||
### Improvements
|
||||
- Plan name is read from the API rather than hardcoded
|
||||
- Bootstrap API call consolidated — org ID, email, and plan name fetched in a single request per refresh
|
||||
- Main panel no longer scrolls — popover auto-sizes to fit content
|
||||
- Session Diary card redesigned — sample count and avg burn rate shown left/right above the sparkline, Claude header removed
|
||||
- Fixed "Not signed in" showing incorrectly on launch when the session was already active
|
||||
- Sign-in state is now detected immediately from stored cookies on startup, before the first data refresh completes
|
||||
- Fixed Re-authenticate (and Sign In) not detecting an existing session — the login window now loads `claude.ai` directly so already-signed-in users are detected correctly and the window auto-dismisses
|
||||
- Added `/api/organizations` as a final fallback for org ID resolution when the bootstrap API response doesn't include it
|
||||
- Session cookie detection now checks both `sessionKey` and `__Secure-next-auth.session-token` cookie names
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.1.4-beta.7",
|
||||
"url": "https://github.com/superdooper86/claudechecker/releases/download/v1.1.4-beta.7/ClaudeChecker.zip",
|
||||
"notes": "## What's new in v1.1.4-beta.7\n\n### Bug fix\n- Main panel no longer scrolls — popover now auto-sizes to fit content"
|
||||
"version": "1.2.1-beta.1",
|
||||
"url": "https://github.com/superdooper86/claudechecker/releases/download/v1.2.1-beta.1/ClaudeChecker.zip",
|
||||
"notes": "## What's new in v1.2.1\n\n### Bug fixes\n- Fixed \"Not signed in\" showing incorrectly on launch when the session was already active\n- Sign-in state is now detected immediately from stored cookies on startup, before the first data refresh completes\n- Added `/api/organizations` as a final fallback for org ID resolution when the bootstrap API response doesn't include it\n- Session cookie detection now checks both `sessionKey` and `__Secure-next-auth.session-token` cookie names"
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.1.3",
|
||||
"url": "https://github.com/superdooper86/claudechecker/releases/download/v1.1.3/ClaudeChecker.zip",
|
||||
"notes": "## What's new in v1.1.3\n\n### UI polish\n- Limit headers now read \"5 Hour Limit\" and \"7 Day Limit\"\n- Tapping anywhere on the blue update banner opens the update window\n\n### Session Diary fix\n- Burn history is persisted across app launches — the sparkline populates immediately on first open instead of requiring a manual refresh\n\n### Window sizing fixes\n- The popover now resizes correctly when switching between the main view and settings\n- Background colour no longer shows through during the resize animation"
|
||||
"version": "1.2.0",
|
||||
"url": "https://github.com/superdooper86/claudechecker/releases/download/v1.2.0/ClaudeChecker.zip",
|
||||
"notes": "## What's new in v1.2.0\n\n### Bug fixes\n- App now works for all users — org ID is fetched dynamically from the API instead of being hardcoded\n- Plan name (e.g. Pro, Max) now updates correctly on every refresh\n\n### Improvements\n- Plan name is read from the API rather than hardcoded\n- Bootstrap API call consolidated — org ID, email, and plan name fetched in a single request per refresh\n- Main panel no longer scrolls — popover auto-sizes to fit content\n- Session Diary card redesigned — sample count and avg burn rate shown left/right above the sparkline, Claude header removed"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user