added input modes
This commit is contained in:
+39
-16
@@ -15,6 +15,12 @@ use std::io::{self};
|
||||
use crate::radio::station::StationInfo;
|
||||
use ratatui::widgets::{List, ListItem, ListState};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum InputMode {
|
||||
Normal,
|
||||
Search,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct App {
|
||||
exit: bool,
|
||||
@@ -22,6 +28,7 @@ pub struct App {
|
||||
station_list_state: ListState,
|
||||
filtered_stations: Vec<StationInfo>,
|
||||
search_query: String,
|
||||
input_mode: InputMode,
|
||||
}
|
||||
|
||||
impl Default for App {
|
||||
@@ -35,6 +42,7 @@ impl Default for App {
|
||||
state
|
||||
},
|
||||
filtered_stations: Vec::new(),
|
||||
input_mode: InputMode::Normal,
|
||||
search_query: String::new(),
|
||||
}
|
||||
}
|
||||
@@ -57,10 +65,13 @@ impl App {
|
||||
.areas(area);
|
||||
|
||||
let [top_right, bottom_right] =
|
||||
Layout::vertical([Constraint::Percentage(50), Constraint::Percentage(50)]).areas(right);
|
||||
Layout::vertical([Constraint::Percentage(10), Constraint::Percentage(90)]).areas(right);
|
||||
|
||||
let [top_left, bottom_left] =
|
||||
Layout::vertical([Constraint::Percentage(50), Constraint::Percentage(50)]).areas(left);
|
||||
|
||||
// Render the left block (e.g., station selection)
|
||||
let max_name_len = left.width.saturating_sub(4) as usize;
|
||||
let max_name_len = top_left.width.saturating_sub(4) as usize;
|
||||
let station_items: Vec<ListItem> = self
|
||||
.filtered_stations
|
||||
.iter()
|
||||
@@ -79,27 +90,28 @@ impl App {
|
||||
.highlight_symbol(">>")
|
||||
.highlight_style(ratatui::style::Style::default().reversed());
|
||||
|
||||
frame.render_stateful_widget(stations_list, left, &mut self.station_list_state.clone());
|
||||
|
||||
frame.render_widget(Block::bordered().title("Played Songs"), bottom_right);
|
||||
|
||||
let search = Paragraph::new(format!("Search: {}", self.search_query))
|
||||
.block(Block::bordered().title("Search"));
|
||||
frame.render_widget(search, top_right);
|
||||
frame.render_stateful_widget(
|
||||
stations_list,
|
||||
top_left,
|
||||
&mut self.station_list_state.clone(),
|
||||
);
|
||||
|
||||
let station = self
|
||||
.station_list_state
|
||||
.selected()
|
||||
.and_then(|i| self.stations.get(i));
|
||||
|
||||
.and_then(|i| self.filtered_stations.get(i));
|
||||
let paragraph = Paragraph::new(
|
||||
station
|
||||
.map(|s| format!("Now selected: {}\n{}", s.name, s.url))
|
||||
.unwrap_or_else(|| "No station selected".into()),
|
||||
)
|
||||
.block(Block::bordered().title("Info"));
|
||||
frame.render_widget(paragraph, bottom_left);
|
||||
|
||||
frame.render_widget(paragraph, bottom_right);
|
||||
let search = Paragraph::new(format!("{}", self.search_query))
|
||||
.block(Block::bordered().title("Search"));
|
||||
frame.render_widget(search, top_right);
|
||||
frame.render_widget(Block::bordered().title("Played Songs"), bottom_right);
|
||||
}
|
||||
|
||||
fn handle_events(&mut self) -> io::Result<()> {
|
||||
@@ -113,7 +125,12 @@ impl App {
|
||||
}
|
||||
|
||||
fn handle_key_event(&mut self, key_event: KeyEvent) {
|
||||
match key_event.code {
|
||||
match self.input_mode {
|
||||
InputMode::Normal => match key_event.code {
|
||||
KeyCode::Char('/') => {
|
||||
self.input_mode = InputMode::Search;
|
||||
self.search_query.clear();
|
||||
}
|
||||
KeyCode::Char('q') => self.exit(),
|
||||
KeyCode::Down | KeyCode::Char('j') => {
|
||||
if let Some(i) = self.station_list_state.selected() {
|
||||
@@ -127,6 +144,9 @@ impl App {
|
||||
self.station_list_state.select(Some(prev));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
InputMode::Search => match key_event.code {
|
||||
KeyCode::Char(c) => {
|
||||
self.search_query.push(c);
|
||||
self.update_filter();
|
||||
@@ -135,7 +155,11 @@ impl App {
|
||||
self.search_query.pop();
|
||||
self.update_filter();
|
||||
}
|
||||
KeyCode::Esc | KeyCode::Enter => {
|
||||
self.input_mode = InputMode::Normal;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,9 +179,6 @@ impl App {
|
||||
.await
|
||||
.map_err(|e| eyre!("Failed to fetch station: {e}"))?;
|
||||
|
||||
self.filtered_stations = self.stations.clone();
|
||||
|
||||
eprintln!("Loaded {} stations", stations.len());
|
||||
if self.stations.is_empty() {
|
||||
self.stations.push(StationInfo {
|
||||
name: "No stations found".into(),
|
||||
@@ -173,6 +194,8 @@ impl App {
|
||||
})
|
||||
.collect();
|
||||
|
||||
self.update_filter();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user