From 5d53b02b3162e82bdd1467281f04aa7afb59c78b Mon Sep 17 00:00:00 2001 From: frapank Date: Fri, 3 Jul 2026 19:29:18 +0200 Subject: [PATCH 1/4] fix: apply delay only after tc confirms success Previously the interface's delay was updated in the UI state before knowing if `tc` actually succeeded, and any tc error crashed the whole program instead of just failing that one action. --- src/gui/tui.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/tui.rs b/src/gui/tui.rs index 7fa5ea3..5f00b6b 100644 --- a/src/gui/tui.rs +++ b/src/gui/tui.rs @@ -123,9 +123,9 @@ impl Gui { if let Some(iface) = self.ctx.interf_vec.get_mut(self.ctx.interf_sel) { - iface.delay = delay; - if let Err(error) = set_delay(&iface.name, delay) { - return Err(error); + match set_delay(&iface.name, delay) { + Ok(()) => iface.delay = delay, + Err(error) => log::error!("{error}"), } } } From ab11b8fd6bff125b35068129d1b8d34b5ce90e14 Mon Sep 17 00:00:00 2001 From: frapank Date: Fri, 3 Jul 2026 19:29:44 +0200 Subject: [PATCH 2/4] fix: scroll interface list using ListState The list was rendered as a plain widget with the selection drawn by hand, so it never scrolled: navigating past the visible area with j/k left the selected item off-screen on hosts with many interfaces. --- src/gui/tui.rs | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/gui/tui.rs b/src/gui/tui.rs index 5f00b6b..68251d3 100644 --- a/src/gui/tui.rs +++ b/src/gui/tui.rs @@ -4,7 +4,7 @@ use crossterm::event::{self, Event, KeyCode, KeyEventKind}; use ratatui::layout::{Alignment, Constraint, Layout, Rect}; use ratatui::style::{Color, Style}; use ratatui::text::Line; -use ratatui::widgets::{Block, BorderType, Borders, Clear, List, ListItem, Paragraph}; +use ratatui::widgets::{Block, BorderType, Borders, Clear, List, ListItem, ListState, Paragraph}; use std::error::Error; use std::ops::ControlFlow; @@ -55,25 +55,30 @@ impl Gui { .enumerate() .map(|(idx, interf)| { if idx == self.ctx.interf_sel { - ListItem::new(Line::from(format!( - " > {} [{}ms]", - interf.name, interf.delay - ))) - .style(Style::default().fg(Color::Black).bg(Color::LightBlue)) + ListItem::new(Line::from(format!("{} [{}ms]", interf.name, interf.delay))) } else { - ListItem::new(Line::from(format!(" {}", interf.name))) + ListItem::new(Line::from(interf.name.clone())) } }) .collect(); - frame.render_widget( - List::new(items).block( - Block::default() - .borders(Borders::ALL) - .border_type(BorderType::Rounded) - .title(" Interfaces "), - ), + let mut state = ListState::default(); + if !self.ctx.interf_vec.is_empty() { + state.select(Some(self.ctx.interf_sel)); + } + + frame.render_stateful_widget( + List::new(items) + .block( + Block::default() + .borders(Borders::ALL) + .border_type(BorderType::Rounded) + .title(" Interfaces "), + ) + .highlight_style(Style::default().fg(Color::Black).bg(Color::LightBlue)) + .highlight_symbol("> "), general[1], + &mut state, ); if self.popup_open { From 324a6a928447039b7b3e8c91fa770a7f4c4a81db Mon Sep 17 00:00:00 2001 From: frapank Date: Fri, 3 Jul 2026 19:30:07 +0200 Subject: [PATCH 3/4] fix: keep popup open on invalid delay input Enter with an empty or out-of-range value used to close the popup silently with no delay applied, looking like the input was accepted. --- src/gui/tui.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/tui.rs b/src/gui/tui.rs index 68251d3..b0f9463 100644 --- a/src/gui/tui.rs +++ b/src/gui/tui.rs @@ -133,8 +133,8 @@ impl Gui { Err(error) => log::error!("{error}"), } } + self.close_popup(); } - self.close_popup(); } KeyCode::Esc => self.close_popup(), KeyCode::Backspace => { From befff53f2e11b7248a8707393bcb03c5c3f68c73 Mon Sep 17 00:00:00 2001 From: frapank Date: Fri, 3 Jul 2026 19:30:47 +0200 Subject: [PATCH 4/4] fix: run clippy in the CI pipeline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The job was named "Fmt · Clippy · Test" and installed the clippy component, but no step ever invoked it. --- .github/workflows/main.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c4c41e8..c4bc230 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,5 +25,8 @@ jobs: - name: Formato run: cargo fmt --all -- --check + - name: Clippy + run: cargo clippy --all-targets + - name: Test run: cargo test --verbose