diff --git a/src/main.rs b/src/main.rs index 38f6d7f..b7cc6fa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,9 +17,18 @@ use ratatui::{ }; use ratatui::backend::CrosstermBackend; +#[derive(Clone)] +enum View { + Categories, + Placeholder(String), // temporary for testing navigation +} + struct App { should_exit: bool, status: String, + + view_stack: Vec, + items: Vec, selected: usize, } @@ -29,6 +38,8 @@ impl Default for App { Self { should_exit: false, status: "Press q to quit".to_string(), + view_stack: vec![View::Categories], + items: vec![ "Shows".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<()> { // Terminal setup enable_raw_mode()?; @@ -93,6 +110,26 @@ fn handle_key(app: &mut App, code: KeyCode) { match code { 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') => { if app.items.is_empty() { return; @@ -123,30 +160,16 @@ fn ui(frame: &mut Frame, app: &App) { // Top frame.render_widget(Block::bordered().title("cj-jftui"), panes.top); - // Left Main - let items: Vec = app - .items - .iter() - .map(|s| ListItem::new(s.as_str())) - .collect(); + // Main - let list = List::new(items) - .block(Block::bordered().title("List").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, 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, - ); + match app.current_view() { + View::Categories => { + render_categories(frame, app, panes.left_main, panes.right_main); + } + View::Placeholder(name) => { + render_placeholder(frame, name, panes.left_main, panes.right_main); + } + } // Bottom 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 = 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 { top: Rect, left_main: Rect,