diff --git a/src/main.rs b/src/main.rs index f8dfbdb..6348851 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ use crossterm::{ - event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, EventStream}, + event::{DisableMouseCapture, EnableMouseCapture, Event, KeyCode, EventStream}, execute, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, }; @@ -22,6 +22,7 @@ struct App { input: String, username: String, current_room: String, + messages_state: ListState, } impl App { @@ -31,11 +32,14 @@ impl App { messages.push(("System".to_string(), format!("Welcome to the chat, {}!", username))); messages.push(("System".to_string(), "To change your username, type /nick ".to_string())); messages.push(("System".to_string(), format!("You are currently in room: {}. To change room, type /join ", default_room))); + let mut messages_state = ListState::default(); + messages_state.select(Some(messages.len().saturating_sub(1))); App { messages, input: String::new(), username, current_room: default_room, + messages_state, } } } @@ -117,7 +121,7 @@ async fn run_app(terminal: &mut Terminal, mut app: App) -> io::Re let mut reader = EventStream::new(); loop { - terminal.draw(|f| ui(f, &app))?; + terminal.draw(|f| ui(f, &mut app))?; tokio::select! { Some(Ok(event)) = reader.next() => { @@ -130,6 +134,7 @@ async fn run_app(terminal: &mut Terminal, mut app: App) -> io::Re let new_username = message_text.split_whitespace().nth(1).unwrap_or(&app.username).to_string(); app.username = new_username.clone(); app.messages.push(("System".to_string(), format!("Username changed to: {}", app.username))); + app.messages_state.select(Some(app.messages.len().saturating_sub(1))); let chat_message = ChatMessage { username: old_username, @@ -156,6 +161,7 @@ async fn run_app(terminal: &mut Terminal, mut app: App) -> io::Re client_clone.subscribe(&format!("chat/{}", new_room), QoS::AtMostOnce).await.unwrap(); app.current_room = new_room.clone(); app.messages.push(("System".to_string(), format!("Changed room to: {}", new_room))); + app.messages_state.select(Some(app.messages.len().saturating_sub(1))); // Send joining message to new room let joining_message = ChatMessage { @@ -166,6 +172,7 @@ async fn run_app(terminal: &mut Terminal, mut app: App) -> io::Re client_clone.publish(&format!("chat/{}", new_room), QoS::AtMostOnce, false, joining_payload.as_bytes()).await.unwrap(); } else { app.messages.push(("System".to_string(), format!("Already in room: {}", new_room))); + app.messages_state.select(Some(app.messages.len().saturating_sub(1))); } } else { let chat_message = ChatMessage { @@ -194,6 +201,7 @@ async fn run_app(terminal: &mut Terminal, mut app: App) -> io::Re } Some((username, message)) = rx.recv() => { app.messages.push((username, message)); + app.messages_state.select(Some(app.messages.len().saturating_sub(1))); } else => { break; @@ -204,7 +212,7 @@ async fn run_app(terminal: &mut Terminal, mut app: App) -> io::Re Ok(()) } -fn ui(f: &mut Frame, app: &App) { +fn ui(f: &mut Frame, app: &mut App) { let chunks = Layout::default() .direction(Direction::Vertical) .margin(1) @@ -216,9 +224,9 @@ fn ui(f: &mut Frame, app: &App) { .iter() .map(|(username, message)| ListItem::new(format!("{}: {}", username, message))) .collect(); - let messages = List::new(messages) + let messages_list = List::new(messages) .block(Block::default().borders(Borders::ALL).title("Messages")); - f.render_widget(messages, chunks[0]); + f.render_stateful_widget(messages_list, chunks[0], &mut app.messages_state); let input = Paragraph::new(app.input.as_str()) .style(Style::default())