From 664e9e944a01bd028aa1f79f016327f9f615689c Mon Sep 17 00:00:00 2001 From: cwj3rcb Date: Fri, 13 Feb 2026 20:24:27 -0600 Subject: [PATCH] Added List --- src/main.rs | 77 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 13 deletions(-) diff --git a/src/main.rs b/src/main.rs index a85d447..a42c424 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,15 +11,37 @@ use crossterm::{ use ratatui::{ layout::{Constraint, Layout, Rect, Spacing}, symbols::merge::MergeStrategy, - widgets::{Block, Paragraph}, + widgets::{Block, List, ListItem, ListState, Paragraph}, Frame, Terminal, }; use ratatui::backend::CrosstermBackend; -#[derive(Default)] struct App { should_exit: bool, status: String, + items: Vec, + selected: usize, +} + +impl Default for App { + fn default() -> Self { + Self { + should_exit: false, + status: "Press q to quit".to_string(), + items: vec![ + "Shows".into(), + "Movies".into(), + "Music".into(), + "Playlists".into(), + "Collections".into(), + "Continue Watching".into(), + "Recently Added".into(), + "Downloads".into(), + "Settings".into(), + ], + selected: 0, + } + } } fn main() -> io::Result<()> { @@ -44,11 +66,7 @@ fn main() -> io::Result<()> { fn run_app(terminal: &mut Terminal>) -> io::Result<()> { let tick_rate = Duration::from_millis(16); // ~60fps let mut last_tick = Instant::now(); - - let mut app = App { - status: "Press q to quit".to_string(), - ..Default::default() - }; + let mut app = App::default(); while !app.should_exit { terminal.draw(|f| ui(f, &app))?; @@ -66,15 +84,28 @@ fn run_app(terminal: &mut Terminal>) -> io::Result< // tick-based updates go here later (smooth nav, download polling, etc.) last_tick = Instant::now(); } - } - + }; Ok(()) } fn handle_key(app: &mut App, code: KeyCode) { match code { KeyCode::Char('q') => app.should_exit = true, - KeyCode::Char('h') => app.status = "hi".to_string(), + + KeyCode::Up | KeyCode::Char('k') => { + if app.selected > 0 { + app.selected -= 1; + } + app.status = format!("Selected: {}", app.items[app.selected]); + } + + KeyCode::Down | KeyCode::Char('j') => { + if app.selected + 1 < app.items.len() { + app.selected += 1; + } + app.status = format!("Selected: {}", app.items[app.selected]); + } + _ => {} } } @@ -86,9 +117,29 @@ fn ui(frame: &mut Frame, app: &App) { // Top frame.render_widget(Block::bordered().title("cj-jftui"), panes.top); - // Main - frame.render_widget(Block::bordered().title("List").merge_borders(MergeStrategy::Exact), panes.left_main); - frame.render_widget(Block::bordered().title("Details").merge_borders(MergeStrategy::Exact), panes.right_main); + // Left Main + let items: Vec = app + .items + .iter() + .map(|s| ListItem::new(s.as_str())) + .collect(); + + let list = List::new(items) + .block(Block::bordered().title("List").merge_borders(MergeStrategy::Exact)) + .highlight_symbol("> "); + + 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, + ); // Bottom frame.render_widget(