v2.0.9 — limit notifications at 80%/95% and on reset

This commit is contained in:
superdooper86
2026-05-07 15:40:13 +02:00
parent 2b48114996
commit b95102cb1b
6 changed files with 72 additions and 7 deletions
+48
View File
@@ -1,5 +1,6 @@
import SwiftUI
import WebKit
import UserNotifications
@MainActor
class UsageViewModel: ObservableObject {
@@ -29,6 +30,8 @@ class UsageViewModel: ObservableObject {
private var burnHistoryStore: [String: [Double]] = [:]
private let maxHistorySamples = 24
private var cachedOrgId: String?
private var previousPercents: [String: Double] = [:]
private var firedThresholds: [String: Set<Int>] = [:]
init() {
cachedOrgId = UserDefaults.standard.string(forKey: "claude_org_id") ?? Self.orgId
@@ -84,6 +87,7 @@ class UsageViewModel: ObservableObject {
burnHistoryStore[key] = history
if history.count > 1 { limits[i].burnHistory = history }
}
checkLimitNotifications(for: limits)
} catch AppError.notAuthenticated {
isNotAuthenticated = true
errorMessage = "Not signed in"
@@ -234,6 +238,50 @@ class UsageViewModel: ObservableObject {
return result
}
// MARK: - Limit notifications
private func checkLimitNotifications(for limits: [AgentLimit]) {
let center = UNUserNotificationCenter.current()
let thresholds = [80, 95]
for limit in limits {
let key = limit.window.rawValue
let curr = limit.usedPercent
let prev = previousPercents[key]
var fired = firedThresholds[key] ?? []
// Threshold warnings (80% and 95%)
for t in thresholds {
let threshold = Double(t)
guard curr >= threshold, prev ?? threshold < threshold, !fired.contains(t) else { continue }
fired.insert(t)
let content = UNMutableNotificationContent()
content.title = "Claude \(limit.window.displayName) limit"
content.body = t == 95
? "\(Int(curr.rounded()))% used — almost at your limit"
: "\(Int(curr.rounded()))% used — approaching your limit"
content.sound = .default
center.add(UNNotificationRequest(identifier: "cc_limit_\(key)_\(t)", content: content, trigger: nil))
}
// Reset detection: was high, now low
if let prev, prev > 50, curr < 20 {
fired.removeAll()
let content = UNMutableNotificationContent()
content.title = "Claude \(limit.window.displayName) limit reset"
content.body = "Your \(limit.window.displayName) quota has been reset"
content.sound = .default
center.add(UNNotificationRequest(
identifier: "cc_reset_\(key)_\(Int(Date().timeIntervalSince1970))",
content: content, trigger: nil
))
}
firedThresholds[key] = fired
previousPercents[key] = curr
}
}
private func loadPlaceholderData() {
let now = Date()
limits = [