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