From 9d55d1a1adc8bb2899c89258023c855f3906d18a Mon Sep 17 00:00:00 2001 From: KaraZajac Date: Tue, 17 Feb 2026 20:30:06 -0500 Subject: [PATCH] UI Improvements --- src/app.rs | 25 ++++++++++++++++++++++++- src/main.rs | 5 +++-- src/ui/signal_menu.rs | 21 ++++++--------------- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/app.rs b/src/app.rs index 68a2229..13f4991 100644 --- a/src/app.rs +++ b/src/app.rs @@ -465,6 +465,7 @@ impl App { } /// True if the active device supports transmit (HackRF only; RTL-SDR is receive-only). + #[allow(dead_code)] pub fn can_transmit(&self) -> bool { self.radio.as_ref().map_or(false, |r| r.supports_tx()) } @@ -983,9 +984,31 @@ impl App { // -- Signal Action Menu helpers -- + /// Signal actions shown in the menu: all if HackRF (TX), else only export and delete. + pub fn available_signal_actions(&self) -> Vec { + if self.radio.as_ref().map_or(false, |r| r.supports_tx()) { + SignalAction::ALL.to_vec() + } else { + SignalAction::ALL + .iter() + .filter(|a| { + matches!( + a, + SignalAction::ExportFob | SignalAction::ExportFlipper | SignalAction::Delete + ) + }) + .copied() + .collect() + } + } + /// Execute the currently selected signal action pub fn execute_signal_action(&mut self) -> Result<()> { - let action = SignalAction::ALL[self.signal_menu_index]; + let actions = self.available_signal_actions(); + let idx = self + .signal_menu_index + .min(actions.len().saturating_sub(1)); + let action = actions[idx]; let capture_id = match self.selected_capture { Some(idx) if idx < self.captures.len() => self.captures[idx].id, _ => { diff --git a/src/main.rs b/src/main.rs index eff948f..94b12ec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,7 +23,7 @@ use std::io::{self, Write}; use std::panic; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; -use app::{App, InputMode, SignalAction, SettingsField, ExportFormat}; +use app::{App, InputMode, SettingsField, ExportFormat}; use ui::draw_ui; const VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -188,7 +188,8 @@ fn run_app(terminal: &mut Terminal, app: &mut A } } KeyCode::Down | KeyCode::Char('j') => { - if app.signal_menu_index < SignalAction::ALL.len() - 1 { + let len = app.available_signal_actions().len(); + if len > 0 && app.signal_menu_index < len - 1 { app.signal_menu_index += 1; } } diff --git a/src/ui/signal_menu.rs b/src/ui/signal_menu.rs index aad0b4e..48ed74c 100644 --- a/src/ui/signal_menu.rs +++ b/src/ui/signal_menu.rs @@ -29,10 +29,12 @@ pub fn render_signal_menu(frame: &mut Frame, app: &App) { ("No capture".to_string(), String::new()) }; + let actions = app.available_signal_actions(); + // Menu dimensions - wider to show more info let menu_width = 38u16; let extra_lines = if freq_info.is_empty() { 0u16 } else { 2u16 }; - let menu_height = (SignalAction::ALL.len() as u16) + 4 + extra_lines; + let menu_height = (actions.len() as u16) + 4 + extra_lines; // Center the menu let x = area.width.saturating_sub(menu_width) / 2; @@ -54,8 +56,8 @@ pub fn render_signal_menu(frame: &mut Frame, app: &App) { items.push(ListItem::new(Line::from(Span::raw("")))); } - // Add action items - for (i, action) in SignalAction::ALL.iter().enumerate() { + // Add action items (only available actions are shown) + for (i, action) in actions.iter().enumerate() { let style = if i == app.signal_menu_index { Style::default() .fg(Color::Black) @@ -77,19 +79,8 @@ pub fn render_signal_menu(frame: &mut Frame, app: &App) { " " }; - let is_tx_action = matches!( - action, - SignalAction::Replay | SignalAction::Lock | SignalAction::Unlock - | SignalAction::Trunk | SignalAction::Panic - ); - let suffix = if is_tx_action && !app.can_transmit() { - " (no TX)" - } else { - "" - }; - items.push(ListItem::new(Line::from(Span::styled( - format!("{}{}{}", prefix, action.label(), suffix), + format!("{}{}", prefix, action.label()), style, )))); }