use leptos::*; use leptos_use::storage::use_local_storage; use codee::string::FromToStringCodec; use shared::GlobalLimitRequest; use crate::api; 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; // Use leptos-use for reactive localStorage management let (current_theme, set_current_theme, _) = use_local_storage::("vibetorrent_theme"); // Initialize with default if empty if current_theme.get_untracked().is_empty() { set_current_theme.set("dark".to_string()); } // Automatically sync theme to document attribute create_effect(move |_| { let theme = current_theme.get().to_lowercase(); if let Some(doc) = document().document_element() { let _ = doc.set_attribute("data-theme", &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); let req = 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), } }; spawn_local(async move { if let Err(e) = api::settings::set_global_limits(&req).await { logging::error!("Failed to set limit: {:?}", e); } else { logging::log!("Limit set successfully"); } }); }; // Refs for click outside detection (Handled globally via JS in index.html for better iOS support) let down_details_ref = create_node_ref::(); let up_details_ref = create_node_ref::(); let theme_details_ref = create_node_ref::(); // Helper to close a details element let close_details = |node_ref: NodeRef| { if let Some(el) = node_ref.get_untracked() { el.set_open(false); } }; view! {
// --- DOWNLOAD SPEED DROPDOWN --- // --- UPLOAD SPEED DROPDOWN ---
} }