aboutsummaryrefslogtreecommitdiff
path: root/src/ui/init.rs
diff options
context:
space:
mode:
authorOxbian <oxbian@mailbox.org>2025-02-21 16:17:00 -0500
committerOxbian <oxbian@mailbox.org>2025-02-21 16:17:00 -0500
commitbc53ad567b82ca354f2b8caf30f242717a5f46a6 (patch)
tree95da9eb36b5a905516bf98e3c88a7af3b19ced1d /src/ui/init.rs
parent3930939d96a50ab41deddbc9fd6ef2b5cc29369e (diff)
downloadNAI-bc53ad567b82ca354f2b8caf30f242717a5f46a6.tar.gz
NAI-bc53ad567b82ca354f2b8caf30f242717a5f46a6.zip
feat: scrollable chatbox
Diffstat (limited to 'src/ui/init.rs')
-rw-r--r--src/ui/init.rs63
1 files changed, 32 insertions, 31 deletions
diff --git a/src/ui/init.rs b/src/ui/init.rs
index 82481cd..7c73d36 100644
--- a/src/ui/init.rs
+++ b/src/ui/init.rs
@@ -5,10 +5,8 @@ use ratatui::{
crossterm::event::{self, Event, KeyCode, KeyEventKind},
layout::{Constraint, Layout, Position},
style::{Color, Style, Stylize},
- text::{Line, Span, Text},
- widgets::{
- Block, List, ListItem, Paragraph, Scrollbar, ScrollbarOrientation, ScrollbarState, Wrap,
- },
+ text::{Line, Text},
+ widgets::{Block, Paragraph, Scrollbar, ScrollbarOrientation, ScrollbarState, Wrap},
DefaultTerminal, Frame,
};
@@ -37,9 +35,24 @@ impl Ui {
}
}
- fn move_messages_up(&mut self) {}
+ fn move_messages_up(&mut self) {
+ if self.message_box_data.nb_line > self.message_box_data.max_line
+ && self.message_box_data.scroll_offset > 0
+ {
+ self.message_box_data.scroll_offset -= 1;
+ }
+ }
- fn move_messages_down(&mut self) {}
+ fn move_messages_down(&mut self) {
+ if self
+ .message_box_data
+ .nb_line
+ .saturating_sub(self.message_box_data.scroll_offset)
+ > self.message_box_data.max_line
+ {
+ self.message_box_data.scroll_offset += 1;
+ }
+ }
pub fn run(mut self, mut terminal: DefaultTerminal) -> Result<()> {
loop {
@@ -52,6 +65,8 @@ impl Ui {
self.input_field.input_mode = InputMode::Editing;
}
KeyCode::Char('q') => return Ok(()),
+ KeyCode::Up => self.move_messages_up(),
+ KeyCode::Down => self.move_messages_down(),
_ => {}
},
InputMode::Editing if key.kind == KeyEventKind::Press => match key.code {
@@ -63,8 +78,6 @@ impl Ui {
KeyCode::Up => self.input_field.move_cursor_up(),
KeyCode::Down => self.input_field.move_cursor_down(),
KeyCode::Esc => self.input_field.input_mode = InputMode::Normal,
- KeyCode::PageUp => self.move_messages_up(),
- KeyCode::PageDown => self.move_messages_down(),
_ => {}
},
InputMode::Editing => {}
@@ -73,21 +86,6 @@ impl Ui {
}
}
- fn wrap_text(&self, text: String, max_width: usize) -> (Vec<Line<'_>>, usize) {
- let mut count = 0; // number of line used
- (
- text.chars()
- .collect::<Vec<_>>()
- .chunks(max_width)
- .map(|chunk| {
- count += 1;
- Line::from(Span::raw(chunk.iter().collect::<String>()))
- })
- .collect(),
- count,
- )
- }
-
fn draw(&mut self, frame: &mut Frame) {
let vertical = Layout::vertical([
Constraint::Length(1),
@@ -159,29 +157,32 @@ impl Ui {
frame.render_stateful_widget(scrollbar_input, input_area, &mut scrollbar_state_input);
let available_width_message = messages_area.width.saturating_sub(2);
- let mut messages: Vec<ListItem> = Vec::new();
+ let mut messages = Vec::new();
let mut max_char_per_line = self.message_box_data.max_char_per_line;
- let mut msg_nb_line = 0;
+ let mut msg_nb_line: usize = 0;
for m in &self.app.messages {
let msg = format!("{}", m);
let size = msg.chars().take(available_width_message as usize).count();
+ let msg_lines = (msg.chars().count() as f64 / size as f64).ceil();
+ msg_nb_line = msg_nb_line.saturating_add(msg_lines as usize);
- let (content, count) = self.wrap_text(msg.clone(), max_char_per_line);
- msg_nb_line = count;
- messages.push(ListItem::new(content.clone()));
+ messages.push(Line::from(msg.clone()));
if size > max_char_per_line {
max_char_per_line = size;
}
}
-
- let messages = List::new(messages).block(Block::bordered().title("Chat with Néo AI"));
+ let messages = Paragraph::new(Text::from(messages))
+ .block(Block::bordered().title("Chat with Néo AI"))
+ .wrap(Wrap { trim: true })
+ .scroll((self.message_box_data.scroll_offset as u16, 0));
frame.render_widget(messages, messages_area);
self.message_box_data.max_char_per_line = max_char_per_line;
self.message_box_data.nb_line = msg_nb_line;
+ self.message_box_data.max_line = messages_area.height.saturating_sub(2) as usize;
- let mut scrollbar_state_message = ScrollbarState::new(self.app.messages.len())
+ let mut scrollbar_state_message = ScrollbarState::new(self.message_box_data.nb_line)
.position(self.message_box_data.scroll_offset);
let scrollbar_message = Scrollbar::new(ScrollbarOrientation::VerticalRight);
frame.render_stateful_widget(
ArKa projects. All rights to me, and your next child right arm.