Something went wrong. Try again.
become more token aware with this one free trick! providers hate her
Something went wrong. Try again.
8.1 kB · 243 lines
Swift
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244import AppKitimport SwiftUIimport Combine
@MainActorpublic class UsageStore: ObservableObject { @Published public var providers: [ProviderUsage] = [] @Published public var harmonized: HarmonizedUsage = .empty() @Published public var config: AppConfig = AppConfig()
public var isLoading: Bool = false public var lastUpdated: Date? = nil
public var statusItemTitle: String { if harmonized.isExhausted { return " 100%" } else if harmonized.usedPercent > 0.0 { return String(format: " %.0f%%", harmonized.usedPercent) } else { return "" } }
private var refreshTimer: Timer? private var authFileSource: DispatchSourceFileSystemObject? private var configFileSource: DispatchSourceFileSystemObject? private var lastFetchTime: Date? private var isScreenSleeping = false private var lastSelfAuthSave: Date? private var authDebounceTask: Task<Void, Never>? private var configDebounceTask: Task<Void, Never>?
public init() { self.config = AppConfig.load() loadInitialCache() setupSleepObserver() setupAuthSaveHook() startFileWatchers() startTimer() Task(priority: .utility) { @MainActor [weak self] in await self?.refresh(force: true) } }
isolated deinit { stopFileWatchers() refreshTimer?.invalidate() }
private func setupSleepObserver() { let nc = NSWorkspace.shared.notificationCenter nc.addObserver(forName: NSWorkspace.screensDidSleepNotification, object: nil, queue: .main) { [weak self] _ in Task { @MainActor [weak self] in self?.isScreenSleeping = true } } nc.addObserver(forName: NSWorkspace.screensDidWakeNotification, object: nil, queue: .main) { [weak self] _ in Task { @MainActor [weak self] in guard let self = self else { return } self.isScreenSleeping = false await self.refresh(force: false) } } }
private func setupAuthSaveHook() { AuthStorage.onAuthSaved = { [weak self] in Task { @MainActor [weak self] in self?.lastSelfAuthSave = Date() } } }
private func loadInitialCache() { let cached = UsageCache.load() guard !cached.isEmpty else { return }
let excluded = Set(config.excludedProviders) var list = cached.values.map { p -> ProviderUsage in var copy = p copy.isShared = excluded.contains(p.id) copy.isCached = true return copy }
list.sort { ProviderOrder.rank($0.id) < ProviderOrder.rank($1.id) }
self.providers = list self.harmonized = Harmonizer.compute(providers: list, config: config) }
public func refresh(force: Bool = false) async { if !force && isScreenSleeping { return }
if !force, let last = lastFetchTime, Date().timeIntervalSince(last) < 45 { return }
guard !isLoading else { return } isLoading = true
guard let auth = AuthStorage.loadAuth() else { isLoading = false return }
let newlyFetched = await UsageFetcher.fetchAll(auth: auth) let excluded = Set(config.excludedProviders)
var merged: [ProviderUsage] = [] for newP in newlyFetched { var finalP = newP if let oldP = self.providers.first(where: { $0.id == newP.id }) { if newP.windows.isEmpty && !oldP.windows.isEmpty { finalP.windows = oldP.windows } if newP.isRateLimited || newP.isCached { finalP.windows = oldP.windows finalP.balance = oldP.balance ?? newP.balance } } if excluded.contains(finalP.id) { finalP.isShared = true } merged.append(finalP) }
self.providers = merged self.harmonized = Harmonizer.compute(providers: merged, config: config) self.lastUpdated = Date() self.lastFetchTime = Date() self.isLoading = false }
private func startTimer() { let timer = Timer.scheduledTimer(withTimeInterval: 120, repeats: true) { [weak self] _ in Task(priority: .utility) { @MainActor [weak self] in await self?.refresh(force: false) } } timer.tolerance = 30.0 self.refreshTimer = timer }
private func startFileWatchers() { watchAuthFile() watchConfigFile() }
private func stopFileWatchers() { authDebounceTask?.cancel() configDebounceTask?.cancel() authFileSource?.cancel() configFileSource?.cancel() }
private func watchAuthFile() { authFileSource?.cancel() authFileSource = nil
let path = AuthStorage.authURL.path guard FileManager.default.fileExists(atPath: path) else { return } let fd = open(path, O_EVTONLY) guard fd >= 0 else { return }
let source = DispatchSource.makeFileSystemObjectSource( fileDescriptor: fd, eventMask: [.write, .extend, .attrib, .rename, .delete], queue: DispatchQueue.main ) source.setEventHandler { [weak self, weak source] in guard let self = self, let src = source else { return } let data = src.data
if let lastSave = self.lastSelfAuthSave, Date().timeIntervalSince(lastSave) < 2.0 { // Ignore self-triggered auth updates } else { self.authDebounceTask?.cancel() self.authDebounceTask = Task { @MainActor [weak self] in try? await Task.sleep(nanoseconds: 400_000_000) guard !Task.isCancelled else { return } await self?.refresh(force: true) } }
if data.contains(.delete) || data.contains(.rename) { src.cancel() DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in self?.watchAuthFile() } } } let fdToClose = fd source.setCancelHandler { close(fdToClose) } source.resume() self.authFileSource = source }
private func watchConfigFile() { configFileSource?.cancel() configFileSource = nil
let path = AppConfig.configURL.path guard FileManager.default.fileExists(atPath: path) else { return } let fd = open(path, O_EVTONLY) guard fd >= 0 else { return }
let source = DispatchSource.makeFileSystemObjectSource( fileDescriptor: fd, eventMask: [.write, .extend, .attrib, .rename, .delete], queue: DispatchQueue.main ) source.setEventHandler { [weak self, weak source] in guard let self = self, let src = source else { return } let data = src.data
self.configDebounceTask?.cancel() self.configDebounceTask = Task { @MainActor [weak self] in try? await Task.sleep(nanoseconds: 300_000_000) guard let self = self, !Task.isCancelled else { return } self.config = AppConfig.load() self.harmonized = Harmonizer.compute(providers: self.providers, config: self.config) }
if data.contains(.delete) || data.contains(.rename) { src.cancel() DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in self?.watchConfigFile() } } } let fdToClose = fd source.setCancelHandler { close(fdToClose) } source.resume() self.configFileSource = source }}