The widget now spawns 'claude' via portable-pty, sends /usage, parses the three rendered bars (Current session / Current week all / Current week Sonnet), and shows the real percentages in the ring + weekly bars. A background task refreshes every 5 minutes; the title-bar refresh button forces an immediate fetch. Drops the cap-tuning UI and tier card from Settings; adds a 'claude command' override (e.g. 'wsl.exe -- claude' for Windows-host widgets reading WSL credentials) and a refresh-interval setting. Fixes title-bar buttons getting swallowed as drag attempts via data-tauri-drag-region="false".
63 lines
2 KiB
Rust
63 lines
2 KiB
Rust
//! Process-global mutable state.
|
|
|
|
use parking_lot::{Mutex, RwLock};
|
|
use std::collections::{HashMap, HashSet};
|
|
use std::path::PathBuf;
|
|
use std::sync::Arc;
|
|
|
|
use crate::cli_usage::CliUsage;
|
|
use crate::jsonl::UsageEvent;
|
|
use crate::settings::Settings;
|
|
use crate::watch::WatcherHandle;
|
|
|
|
/// Per-file parse cache. We resume reading from `byte_offset` on the next
|
|
/// poll, so we never re-parse already-seen lines.
|
|
pub struct FileCache {
|
|
pub mtime_ns: i128,
|
|
pub size: u64,
|
|
pub byte_offset: u64,
|
|
pub messages: Vec<UsageEvent>,
|
|
}
|
|
|
|
pub struct AppState {
|
|
pub roots: RwLock<Vec<PathBuf>>,
|
|
pub files: RwLock<HashMap<PathBuf, FileCache>>,
|
|
pub seen_ids: RwLock<HashSet<String>>,
|
|
pub settings: RwLock<Settings>,
|
|
/// Latest /usage result. Refreshed periodically by a background task,
|
|
/// or on-demand via the `refresh_cli_usage` command.
|
|
pub cli_usage: RwLock<Option<CliUsage>>,
|
|
/// Boxed so we can keep the watcher alive across the whole app lifetime
|
|
/// without polluting Tauri's setup hook.
|
|
pub watcher: Mutex<Option<WatcherHandle>>,
|
|
}
|
|
|
|
pub type SharedState = Arc<AppState>;
|
|
|
|
impl AppState {
|
|
pub fn new(settings: Settings) -> SharedState {
|
|
Arc::new(Self {
|
|
roots: RwLock::new(Vec::new()),
|
|
files: RwLock::new(HashMap::new()),
|
|
seen_ids: RwLock::new(HashSet::new()),
|
|
settings: RwLock::new(settings),
|
|
cli_usage: RwLock::new(None),
|
|
watcher: Mutex::new(None),
|
|
})
|
|
}
|
|
|
|
pub fn set_watcher(&self, w: WatcherHandle) {
|
|
*self.watcher.lock() = Some(w);
|
|
}
|
|
|
|
/// Snapshot all events across all cached files in one allocation.
|
|
/// Caller is responsible for sorting if needed.
|
|
pub fn collect_events(&self) -> Vec<UsageEvent> {
|
|
let files = self.files.read();
|
|
let mut out = Vec::with_capacity(files.values().map(|f| f.messages.len()).sum());
|
|
for f in files.values() {
|
|
out.extend(f.messages.iter().cloned());
|
|
}
|
|
out
|
|
}
|
|
}
|