use leptos::*; use shared::GlobalLimitRequest; use wasm_bindgen::JsCast; fn format_bytes(bytes: i64) -> String { const UNITS: [&str; 6] = ["B", "KB", "MB", "GB", "TB", "PB"]; if bytes < 1024 { return format!("{} B", bytes); } let i = (bytes as f64).log2().div_euclid(10.0) as usize; format!( "{:.1} {}", (bytes as f64) / 1024_f64.powi(i as i32), UNITS[i] ) } fn format_speed(bytes_per_sec: i64) -> String { if bytes_per_sec == 0 { return "0 B/s".to_string(); } format!("{}/s", format_bytes(bytes_per_sec)) } #[component] pub fn StatusBar() -> impl IntoView { let store = use_context::().expect("store not provided"); let stats = store.global_stats; let (current_theme, set_current_theme) = create_signal("light".to_string()); create_effect(move |_| { if let Some(win) = web_sys::window() { if let Some(storage) = win.local_storage().ok().flatten() { if let Ok(Some(stored_theme)) = storage.get_item("vibetorrent_theme") { set_current_theme.set(stored_theme.clone()); if let Some(doc) = win.document() { let _ = doc .document_element() .unwrap() .set_attribute("data-theme", &stored_theme); } } } } }); // Preset limits in bytes/s let limits: Vec<(i64, &str)> = vec![ (0, "Unlimited"), (100 * 1024, "100 KB/s"), (500 * 1024, "500 KB/s"), (1024 * 1024, "1 MB/s"), (2 * 1024 * 1024, "2 MB/s"), (5 * 1024 * 1024, "5 MB/s"), (10 * 1024 * 1024, "10 MB/s"), (20 * 1024 * 1024, "20 MB/s"), ]; let set_limit = move |limit_type: &str, val: i64| { let limit_type = limit_type.to_string(); logging::log!("Setting {} limit to {}", limit_type, val); spawn_local(async move { let req_body = if limit_type == "down" { GlobalLimitRequest { max_download_rate: Some(val), max_upload_rate: None, } } else { GlobalLimitRequest { max_download_rate: None, max_upload_rate: Some(val), } }; let client = gloo_net::http::Request::post("/api/settings/global-limits").json(&req_body); match client { Ok(req) => match req.send().await { Ok(resp) => { if !resp.ok() { logging::error!( "Failed to set limit: {} {}", resp.status(), resp.status_text() ); } else { logging::log!("Limit set successfully"); } } Err(e) => logging::error!("Network error setting limit: {}", e), }, Err(e) => logging::error!("Failed to create request: {}", e), } }); }; // Helper to close dropdowns by blurring the active element let close_dropdown = move || { if let Some(doc) = web_sys::window().and_then(|w| w.document()) { if let Some(active) = doc.active_element() { let _ = active .dyn_into::() .map(|el| el.blur()); } } }; // Global listener to force blur on touchstart (for iOS "tap outside" closing) let force_blur = move |_| { if let Some(doc) = web_sys::window().and_then(|w| w.document()) { if let Some(active) = doc.active_element() { // If something is focused, blur it to close dropdowns let _ = active .dyn_into::() .map(|el| el.blur()); } } }; let _ = window_event_listener(ev::touchstart, force_blur); view! {
// --- DOWNLOAD SPEED DROPDOWN --- // --- UPLOAD SPEED DROPDOWN ---
} }