added enter and backspace commands
This commit is contained in:
108
src/main.rs
108
src/main.rs
@@ -17,9 +17,18 @@ use ratatui::{
|
|||||||
};
|
};
|
||||||
use ratatui::backend::CrosstermBackend;
|
use ratatui::backend::CrosstermBackend;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
enum View {
|
||||||
|
Categories,
|
||||||
|
Placeholder(String), // temporary for testing navigation
|
||||||
|
}
|
||||||
|
|
||||||
struct App {
|
struct App {
|
||||||
should_exit: bool,
|
should_exit: bool,
|
||||||
status: String,
|
status: String,
|
||||||
|
|
||||||
|
view_stack: Vec<View>,
|
||||||
|
|
||||||
items: Vec<String>,
|
items: Vec<String>,
|
||||||
selected: usize,
|
selected: usize,
|
||||||
}
|
}
|
||||||
@@ -29,6 +38,8 @@ impl Default for App {
|
|||||||
Self {
|
Self {
|
||||||
should_exit: false,
|
should_exit: false,
|
||||||
status: "Press q to quit".to_string(),
|
status: "Press q to quit".to_string(),
|
||||||
|
view_stack: vec![View::Categories],
|
||||||
|
|
||||||
items: vec![
|
items: vec![
|
||||||
"Shows".into(),
|
"Shows".into(),
|
||||||
"Movies".into(),
|
"Movies".into(),
|
||||||
@@ -45,6 +56,12 @@ impl Default for App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl App {
|
||||||
|
fn current_view(&self) -> &View {
|
||||||
|
self.view_stack.last().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> io::Result<()> {
|
fn main() -> io::Result<()> {
|
||||||
// Terminal setup
|
// Terminal setup
|
||||||
enable_raw_mode()?;
|
enable_raw_mode()?;
|
||||||
@@ -93,6 +110,26 @@ fn handle_key(app: &mut App, code: KeyCode) {
|
|||||||
match code {
|
match code {
|
||||||
KeyCode::Char('q') => app.should_exit = true,
|
KeyCode::Char('q') => app.should_exit = true,
|
||||||
|
|
||||||
|
KeyCode::Enter => {
|
||||||
|
match app.current_view() {
|
||||||
|
View::Categories => {
|
||||||
|
let selected = app.items[app.selected].clone();
|
||||||
|
app.view_stack.push(View::Placeholder(selected.clone()));
|
||||||
|
app.status = format!("Entered {}", selected);
|
||||||
|
app.selected = 0;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyCode::Esc | KeyCode::Backspace => {
|
||||||
|
if app.view_stack.len() > 1 {
|
||||||
|
app.view_stack.pop();
|
||||||
|
app.status = "Went back".to_string();
|
||||||
|
app.selected = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
KeyCode::Up | KeyCode::Char('k') => {
|
KeyCode::Up | KeyCode::Char('k') => {
|
||||||
if app.items.is_empty() {
|
if app.items.is_empty() {
|
||||||
return;
|
return;
|
||||||
@@ -123,30 +160,16 @@ fn ui(frame: &mut Frame, app: &App) {
|
|||||||
// Top
|
// Top
|
||||||
frame.render_widget(Block::bordered().title("cj-jftui"), panes.top);
|
frame.render_widget(Block::bordered().title("cj-jftui"), panes.top);
|
||||||
|
|
||||||
// Left Main
|
// Main
|
||||||
let items: Vec<ListItem> = app
|
|
||||||
.items
|
|
||||||
.iter()
|
|
||||||
.map(|s| ListItem::new(s.as_str()))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let list = List::new(items)
|
match app.current_view() {
|
||||||
.block(Block::bordered().title("List").merge_borders(MergeStrategy::Exact))
|
View::Categories => {
|
||||||
.highlight_symbol("> ")
|
render_categories(frame, app, panes.left_main, panes.right_main);
|
||||||
.highlight_style(Style::default().add_modifier(Modifier::REVERSED));
|
}
|
||||||
|
View::Placeholder(name) => {
|
||||||
let mut state = ListState::default();
|
render_placeholder(frame, name, panes.left_main, panes.right_main);
|
||||||
state.select(Some(app.selected));
|
}
|
||||||
|
}
|
||||||
frame.render_stateful_widget(list, panes.left_main, &mut state);
|
|
||||||
|
|
||||||
//Right Main
|
|
||||||
let detail = format!("Details for:\n\n{}", app.items[app.selected]);
|
|
||||||
frame.render_widget(
|
|
||||||
Paragraph::new(detail)
|
|
||||||
.block(Block::bordered().title("Details").merge_borders(MergeStrategy::Exact)),
|
|
||||||
panes.right_main,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Bottom
|
// Bottom
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
@@ -160,6 +183,45 @@ fn ui(frame: &mut Frame, app: &App) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_categories(frame: &mut Frame, app: &App, left: Rect, right: Rect) {
|
||||||
|
let items: Vec<ListItem> = app
|
||||||
|
.items
|
||||||
|
.iter()
|
||||||
|
.map(|s| ListItem::new(s.as_str()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let list = List::new(items)
|
||||||
|
.block(Block::bordered().title("Categories").merge_borders(MergeStrategy::Exact))
|
||||||
|
.highlight_symbol("> ")
|
||||||
|
.highlight_style(Style::default().add_modifier(Modifier::REVERSED));
|
||||||
|
|
||||||
|
let mut state = ListState::default();
|
||||||
|
state.select(Some(app.selected));
|
||||||
|
|
||||||
|
frame.render_stateful_widget(list, left, &mut state);
|
||||||
|
|
||||||
|
let detail = format!("Details for:\n\n{}", app.items[app.selected]);
|
||||||
|
frame.render_widget(
|
||||||
|
Paragraph::new(detail)
|
||||||
|
.block(Block::bordered().title("Details").merge_borders(MergeStrategy::Exact)),
|
||||||
|
right,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_placeholder(frame: &mut Frame, name: &str, left: Rect, right: Rect) {
|
||||||
|
frame.render_widget(
|
||||||
|
Paragraph::new(format!("Inside {}\n\nPress Esc to go back", name))
|
||||||
|
.block(Block::bordered().title("Library").merge_borders(MergeStrategy::Exact)),
|
||||||
|
left,
|
||||||
|
);
|
||||||
|
|
||||||
|
frame.render_widget(
|
||||||
|
Paragraph::new("Right pane reserved for item details / thumbnails")
|
||||||
|
.block(Block::bordered().title("Details").merge_borders(MergeStrategy::Exact)),
|
||||||
|
right,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
struct Panes {
|
struct Panes {
|
||||||
top: Rect,
|
top: Rect,
|
||||||
left_main: Rect,
|
left_main: Rect,
|
||||||
|
|||||||
Reference in New Issue
Block a user