use leptos::*; use shared::GlobalLimitRequest; 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 (theme_open, set_theme_open) = create_signal(false); // Dropdown states let (down_menu_open, set_down_menu_open) = create_signal(false); let (up_menu_open, set_up_menu_open) = create_signal(false); // 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), } }); set_down_menu_open.set(false); set_up_menu_open.set(false); }; // Register global click/touch listener to close menus when clicking outside let close_menus = move |_| { if down_menu_open.get_untracked() { set_down_menu_open.set(false); } if up_menu_open.get_untracked() { set_up_menu_open.set(false); } if theme_open.get_untracked() { set_theme_open.set(false); } }; // Use window_event_listener from leptos for both click and touchstart (for iOS) let _ = window_event_listener(ev::click, close_menus); let _ = window_event_listener(ev::touchstart, close_menus); view! {
// --- DOWNLOAD SPEED DROPDOWN ---
{move || format_speed(stats.get().down_rate)} 0) fallback=|| ()> {move || format!("(Limit: {})", format_speed(stats.get().down_limit.unwrap_or(0)))}
// --- UPLOAD SPEED DROPDOWN ---
{move || format_speed(stats.get().up_rate)} 0) fallback=|| ()> {move || format!("(Limit: {})", format_speed(stats.get().up_limit.unwrap_or(0)))}
} }