From ca42d83ef5c527df630de6d155dc16c89a16ad47 Mon Sep 17 00:00:00 2001 From: GyulyVGC Date: Thu, 18 Dec 2025 11:39:01 +0100 Subject: [PATCH] make preview_charts a Vec instead of an HashMap --- src/chart/types/preview_chart.rs | 9 ++++-- src/gui/pages/initial_page.rs | 7 +++-- src/gui/sniffer.rs | 51 ++++++++++++++++++++----------- src/networking/traffic_preview.rs | 1 + 4 files changed, 46 insertions(+), 22 deletions(-) diff --git a/src/chart/types/preview_chart.rs b/src/chart/types/preview_chart.rs index 48e131fe..5a2e23e1 100644 --- a/src/chart/types/preview_chart.rs +++ b/src/chart/types/preview_chart.rs @@ -44,13 +44,18 @@ pub fn update_charts_data(&mut self, packets: u128) { let packets_entry = packets as f32; let packets_point = (tot_seconds, packets_entry); - // update sent bytes traffic data + // update traffic data self.packets.update_series(packets_point, true, false); self.max_packets = self.packets.get_max(); } pub fn view(&self) -> Element<'_, Message, StyleType> { - Column::new().height(40).push(ChartWidget::new(self)).into() + if self.max_packets > 0.0 { + Column::new().height(40).push(ChartWidget::new(self)) + } else { + Column::new() + } + .into() } pub fn change_style(&mut self, style: StyleType) { diff --git a/src/gui/pages/initial_page.rs b/src/gui/pages/initial_page.rs index 0f4fcc58..17ba8fc1 100644 --- a/src/gui/pages/initial_page.rs +++ b/src/gui/pages/initial_page.rs @@ -178,7 +178,7 @@ fn get_col_adapter( ) -> Column<'_, Message, StyleType> { let mut dev_str_list = vec![]; // TODO: do not iterate here - for (_, (my_dev, _)) in &sniffer.preview_charts { + for (my_dev, _) in &sniffer.preview_charts { let mut title = String::new(); #[allow(unused_mut)] let mut subtitle: Option<&String> = None; @@ -233,7 +233,10 @@ fn get_col_adapter( } else { Some(Text::new(addrs).font(font)) }; - let my_device_chart = sniffer.preview_charts.get(name); + let my_device_chart = sniffer + .preview_charts + .iter() + .find(|(dev, _)| dev.get_name().eq(name)); scroll_adapters.push( Button::new( Column::new() diff --git a/src/gui/sniffer.rs b/src/gui/sniffer.rs index 4014c679..252c5958 100644 --- a/src/gui/sniffer.rs +++ b/src/gui/sniffer.rs @@ -102,8 +102,7 @@ pub struct Sniffer { /// Traffic chart displayed in the Overview page pub traffic_chart: TrafficChart, /// Traffic preview charts displayed in the initial page - // TODO: make this a Vec<(MyDevice, PreviewChart)> to keep the order of the devices consistent - pub preview_charts: HashMap, + pub preview_charts: Vec<(MyDevice, PreviewChart)>, /// Currently displayed modal; None if no modal is displayed pub modal: Option, /// Currently displayed settings page; None if settings is closed @@ -158,7 +157,7 @@ pub fn new(conf: Conf) -> Self { pcap_error: None, dots_pulse: (".".to_string(), 0), traffic_chart: TrafficChart::new(style, language, data_repr), - preview_charts: HashMap::new(), + preview_charts: Vec::new(), modal: None, settings_page: None, running_page: None, @@ -634,20 +633,34 @@ pub fn update(&mut self, message: Message) -> Task { } } Message::TrafficPreview(msg) => { - // TODO: remove or hide inactive devices + self.preview_charts.retain(|(my_dev, _)| { + msg.data + .iter() + .any(|(d, _)| d.get_name().eq(my_dev.get_name())) + }); for (dev, packets) in msg.data { - self.preview_charts - .entry(dev.get_name().clone()) - .and_modify(|(my_dev, chart)| { - *my_dev = dev.clone(); - chart.update_charts_data(packets); - }) - .or_insert({ - let mut chart = PreviewChart::new(self.conf.settings.style); - chart.update_charts_data(packets); - (dev, chart) - }); + let Some((my_dev, chart)) = self + .preview_charts + .iter_mut() + .find(|(my_dev, _)| my_dev.get_name().eq(dev.get_name())) + else { + let mut chart = PreviewChart::new(self.conf.settings.style); + chart.update_charts_data(packets); + self.preview_charts.push((dev, chart)); + continue; + }; + *my_dev = dev.clone(); + chart.update_charts_data(packets); } + self.preview_charts.sort_by(|(_, c1), (_, c2)| { + if c1.max_packets > 0.0 && c2.max_packets == 0.0 { + std::cmp::Ordering::Less + } else if c1.max_packets == 0.0 && c2.max_packets > 0.0 { + std::cmp::Ordering::Greater + } else { + std::cmp::Ordering::Equal + } + }); } } Task::none() @@ -891,7 +904,9 @@ fn reset(&mut self) { // increment capture id to ignore pending messages from previous captures self.current_capture_rx = (self.current_capture_rx.0 + 1, None); self.info_traffic = InfoTraffic::default(); - self.preview_charts = HashMap::new(); + self.preview_charts + .iter_mut() + .for_each(|(_, chart)| *chart = PreviewChart::new(style)); self.addresses_resolved = HashMap::new(); self.favorite_hosts = HashSet::new(); self.logged_notifications = (VecDeque::new(), 0); @@ -910,7 +925,7 @@ fn reset(&mut self) { } fn set_device(&mut self, name: &str) { - for (_, (my_dev, _)) in &self.preview_charts { + for (my_dev, _) in &self.preview_charts { if my_dev.get_name().eq(&name) { self.conf.device.device_name = name.to_string(); self.capture_source = CaptureSource::Device(my_dev.clone()); @@ -1177,7 +1192,7 @@ pub fn is_capture_source_consistent(&self) -> bool { fn change_charts_style(&mut self) { let style = self.conf.settings.style; self.traffic_chart.change_style(style); - for (_, chart) in self.preview_charts.values_mut() { + for (_, chart) in &mut self.preview_charts { chart.change_style(style); } } diff --git a/src/networking/traffic_preview.rs b/src/networking/traffic_preview.rs index 887642fb..185e227e 100644 --- a/src/networking/traffic_preview.rs +++ b/src/networking/traffic_preview.rs @@ -75,6 +75,7 @@ fn handle_devices_and_previews( continue; } data.insert(dev_name.clone(), 0); + traffic_preview.data.push((my_dev.clone(), 0)); let mut freeze_rx = freeze_tx.subscribe(); let pcap_tx = pcap_tx.clone(); let capture_source = CaptureSource::Device(my_dev);