diff --git a/frontend/src/components/layout/sidebar.rs b/frontend/src/components/layout/sidebar.rs index 1a0568b..cfd73c7 100644 --- a/frontend/src/components/layout/sidebar.rs +++ b/frontend/src/components/layout/sidebar.rs @@ -6,52 +6,47 @@ use crate::api; pub fn Sidebar() -> impl IntoView { let store = use_context::().expect("store not provided"); - let total_count = move || store.torrents.get().len(); + let total_count = move || store.torrents.with(|map| map.len()); let downloading_count = move || { - store - .torrents - .get() - .iter() - .filter(|t| t.status == shared::TorrentStatus::Downloading) - .count() + store.torrents.with(|map| { + map.values() + .filter(|t| t.status == shared::TorrentStatus::Downloading) + .count() + }) }; let seeding_count = move || { - store - .torrents - .get() - .iter() - .filter(|t| t.status == shared::TorrentStatus::Seeding) - .count() + store.torrents.with(|map| { + map.values() + .filter(|t| t.status == shared::TorrentStatus::Seeding) + .count() + }) }; let completed_count = move || { - store - .torrents - .get() - .iter() - .filter(|t| { - t.status == shared::TorrentStatus::Seeding - || (t.status == shared::TorrentStatus::Paused && t.percent_complete >= 100.0) - }) - .count() + store.torrents.with(|map| { + map.values() + .filter(|t| { + t.status == shared::TorrentStatus::Seeding + || (t.status == shared::TorrentStatus::Paused && t.percent_complete >= 100.0) + }) + .count() + }) }; let paused_count = move || { - store - .torrents - .get() - .iter() - .filter(|t| t.status == shared::TorrentStatus::Paused) - .count() + store.torrents.with(|map| { + map.values() + .filter(|t| t.status == shared::TorrentStatus::Paused) + .count() + }) }; let inactive_count = move || { - store - .torrents - .get() - .iter() - .filter(|t| { - t.status == shared::TorrentStatus::Paused - || t.status == shared::TorrentStatus::Error - }) - .count() + store.torrents.with(|map| { + map.values() + .filter(|t| { + t.status == shared::TorrentStatus::Paused + || t.status == shared::TorrentStatus::Error + }) + .count() + }) }; let close_drawer = move || { diff --git a/frontend/src/components/torrent/table.rs b/frontend/src/components/torrent/table.rs index 0f2ba6e..5d86fc4 100644 --- a/frontend/src/components/torrent/table.rs +++ b/frontend/src/components/torrent/table.rs @@ -82,9 +82,10 @@ pub fn TorrentTable() -> impl IntoView { let sort_dir = create_rw_signal(SortDirection::Descending); let filtered_torrents = move || { - let mut torrents = store - .torrents - .get() + // Convert HashMap values to Vec for filtering and sorting + let torrents: Vec = store.torrents.with(|map| map.values().cloned().collect()); + + let mut torrents = torrents .into_iter() .filter(|t| { let filter = store.filter.get(); diff --git a/frontend/src/store.rs b/frontend/src/store.rs index a525905..f5400ed 100644 --- a/frontend/src/store.rs +++ b/frontend/src/store.rs @@ -113,9 +113,11 @@ impl FilterStatus { } } +use std::collections::HashMap; + #[derive(Clone, Copy, Debug)] pub struct TorrentStore { - pub torrents: RwSignal>, + pub torrents: RwSignal>, pub filter: RwSignal, pub search_query: RwSignal, pub global_stats: RwSignal, @@ -124,7 +126,7 @@ pub struct TorrentStore { } pub fn provide_torrent_store() { - let torrents = create_rw_signal(Vec::::new()); + let torrents = create_rw_signal(HashMap::new()); let filter = create_rw_signal(FilterStatus::All); let search_query = create_rw_signal(String::new()); let global_stats = create_rw_signal(GlobalStats::default()); @@ -193,12 +195,15 @@ pub fn provide_torrent_store() { if let Ok(event) = serde_json::from_str::(&data_str) { match event { AppEvent::FullList { torrents: list, .. } => { - torrents.set(list); + let map: HashMap = list + .into_iter() + .map(|t| (t.hash.clone(), t)) + .collect(); + torrents.set(map); } AppEvent::Update(update) => { - torrents.update(|list| { - if let Some(t) = list.iter_mut().find(|t| t.hash == update.hash) - { + torrents.update(|map| { + if let Some(t) = map.get_mut(&update.hash) { if let Some(name) = update.name { t.name = name; }