v2.0.7 — Show account email in settings auth section
This commit is contained in:
@@ -596,13 +596,31 @@ struct SettingsView: View {
|
||||
.font(.system(size: 12, weight: .medium))
|
||||
.foregroundColor(.secondary)
|
||||
|
||||
HStack(spacing: 6) {
|
||||
Circle()
|
||||
.fill(vm.isSignedIn ? Color.green : Color.orange)
|
||||
.frame(width: 7, height: 7)
|
||||
Text(vm.isSignedIn ? "Signed in to claude.ai" : "Not signed in")
|
||||
.font(.system(size: 12, weight: .medium))
|
||||
.foregroundColor(vm.isSignedIn ? .primary : .orange)
|
||||
if vm.isSignedIn {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
HStack(spacing: 6) {
|
||||
Circle()
|
||||
.fill(Color.green)
|
||||
.frame(width: 7, height: 7)
|
||||
Text("Signed in to claude.ai")
|
||||
.font(.system(size: 13, weight: .semibold))
|
||||
}
|
||||
if !vm.userEmail.isEmpty {
|
||||
Text(vm.userEmail)
|
||||
.font(.system(size: 11.5))
|
||||
.foregroundColor(.secondary)
|
||||
.padding(.leading, 13)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
HStack(spacing: 6) {
|
||||
Circle()
|
||||
.fill(Color.orange)
|
||||
.frame(width: 7, height: 7)
|
||||
Text("Not signed in")
|
||||
.font(.system(size: 13, weight: .semibold))
|
||||
.foregroundColor(.orange)
|
||||
}
|
||||
}
|
||||
|
||||
Text("Your session is stored locally and persists across restarts.")
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.0.6</string>
|
||||
<string>2.0.7</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>13</string>
|
||||
<string>14</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>13.0</string>
|
||||
<key>LSUIElement</key>
|
||||
|
||||
@@ -14,6 +14,7 @@ class UsageViewModel: ObservableObject {
|
||||
@Published var planLabel: String = "Claude"
|
||||
@Published var isNotAuthenticated: Bool = false
|
||||
@Published var isSignedIn: Bool = false
|
||||
@Published var userEmail: String = ""
|
||||
@Published var triggerLogin: Bool = false
|
||||
@Published var showInMenuBar: Bool = true {
|
||||
didSet { UserDefaults.standard.set(showInMenuBar, forKey: "show_in_menubar") }
|
||||
@@ -46,6 +47,7 @@ class UsageViewModel: ObservableObject {
|
||||
isSignedIn = false
|
||||
isNotAuthenticated = true
|
||||
lastUpdated = nil
|
||||
userEmail = ""
|
||||
limits = []
|
||||
extraUsage = nil
|
||||
prepaidCredits = nil
|
||||
@@ -63,7 +65,9 @@ class UsageViewModel: ObservableObject {
|
||||
async let usageFetch = fetchUsage(orgId: orgId)
|
||||
async let prepaidFetch = fetchPrepaidCredits(orgId: orgId)
|
||||
async let overageFetch = fetchOverageSpendLimit(orgId: orgId)
|
||||
let (usage, prepaid, overage) = try await (usageFetch, prepaidFetch, overageFetch)
|
||||
async let emailFetch = fetchUserEmail()
|
||||
let (usage, prepaid, overage, email) = try await (usageFetch, prepaidFetch, overageFetch, emailFetch)
|
||||
if let email { userEmail = email }
|
||||
limits = buildLimits(from: usage)
|
||||
extraUsage = usage.extraUsage
|
||||
prepaidCredits = prepaid
|
||||
@@ -121,6 +125,23 @@ class UsageViewModel: ObservableObject {
|
||||
return try JSONDecoder().decode(UsageResponse.self, from: data)
|
||||
}
|
||||
|
||||
private func fetchUserEmail() async throws -> String? {
|
||||
let url = URL(string: "https://claude.ai/api/bootstrap")!
|
||||
var req = URLRequest(url: url)
|
||||
req.setValue("application/json", forHTTPHeaderField: "accept")
|
||||
let cookies = await WKWebsiteDataStore.default().httpCookieStore.allCookies()
|
||||
let claudeCookies = cookies.filter { $0.domain.contains("claude.ai") }
|
||||
if let header = HTTPCookie.requestHeaderFields(with: claudeCookies)["Cookie"] {
|
||||
req.setValue(header, forHTTPHeaderField: "Cookie")
|
||||
}
|
||||
let (data, response) = try await URLSession.shared.data(for: req)
|
||||
guard let http = response as? HTTPURLResponse, http.statusCode == 200 else { return nil }
|
||||
guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
||||
let account = json["account"] as? [String: Any],
|
||||
let email = account["email_address"] as? String else { return nil }
|
||||
return email
|
||||
}
|
||||
|
||||
private func fetchPrepaidCredits(orgId: String) async throws -> PrepaidCredits? {
|
||||
let url = URL(string: "https://claude.ai/api/organizations/\(orgId)/prepaid/credits")!
|
||||
var req = URLRequest(url: url)
|
||||
|
||||
Reference in New Issue
Block a user