aboutsummaryrefslogtreecommitdiffstats
path: root/src/tui/ui.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tui/ui.rs')
-rw-r--r--src/tui/ui.rs43
1 files changed, 40 insertions, 3 deletions
diff --git a/src/tui/ui.rs b/src/tui/ui.rs
index 4a243ad..f6c5369 100644
--- a/src/tui/ui.rs
+++ b/src/tui/ui.rs
@@ -1,3 +1,4 @@
+use super::app::AppState;
use ratatui::{
Frame,
layout::{Constraint, Direction, Layout, Rect},
@@ -5,8 +6,7 @@ use ratatui::{
text::{Line, Span, Text},
widgets::{Block, BorderType, Borders, List, ListItem, Paragraph, Wrap},
};
-
-use super::app::AppState;
+use unicode_width::UnicodeWidthStr;
// ── Colour palette ────────────────────────────────────────────────────────────
// Dark terminal aesthetic: near-black background, cool grey chrome,
@@ -102,8 +102,11 @@ fn draw_chat_log(f: &mut Frame, area: Rect, state: &AppState) {
.border_style(Style::default().fg(ORANGE))
.style(Style::default().bg(BG));
+ let inner_width = area.width.saturating_sub(2) as usize;
let inner_height = area.height.saturating_sub(2) as usize;
- let scroll = lines.len().saturating_sub(inner_height);
+
+ let total_wrapped = count_wrapped_lines(&lines, inner_width);
+ let scroll = total_wrapped.saturating_sub(inner_height);
f.render_widget(
Paragraph::new(Text::from(lines))
.block(block)
@@ -113,6 +116,40 @@ fn draw_chat_log(f: &mut Frame, area: Rect, state: &AppState) {
);
}
+fn count_wrapped_lines(lines: &[Line], width: usize) -> usize {
+ if width == 0 {
+ return lines.len();
+ }
+ lines
+ .iter()
+ .map(|line| {
+ let full_text: String = line
+ .spans
+ .iter()
+ .map(|span| span.content.as_ref())
+ .collect();
+
+ if full_text.is_empty() {
+ return 1;
+ }
+
+ let mut row_count = 1;
+ let mut current_width = 0;
+
+ for word in full_text.split_inclusive(' ') {
+ let word_width = UnicodeWidthStr::width(word);
+ if current_width + word_width > width {
+ row_count += 1;
+ current_width = word_width;
+ } else {
+ current_width += word_width;
+ }
+ }
+ row_count
+ })
+ .sum()
+}
+
fn render_chat_line(msg: &super::app::ChatLine) -> Line<'static> {
if msg.is_system {
return Line::from(Span::styled(