UI Improvements
This commit is contained in:
+24
-1
@@ -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<SignalAction> {
|
||||
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,
|
||||
_ => {
|
||||
|
||||
+3
-2
@@ -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<B: ratatui::backend::Backend>(terminal: &mut Terminal<B>, 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;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-15
@@ -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,
|
||||
))));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user