use crate::app::agent::agent::loop_::cli::theme::{SCROLLBAR_THUMB, SCROLLBAR_TRACK};
use ratatui::text::{Line, Span, Text};
use ratatui::widgets::Paragraph;
fn u16_from_usize_saturating(value: usize) -> u16 {
u16::try_from(value).unwrap_or(u16::MAX)
}
fn u32_from_usize_saturating(value: usize) -> u32 {
u32::try_from(value).unwrap_or(u32::MAX)
}
fn usize_from_u64_saturating(value: u64) -> usize {
usize::try_from(value).unwrap_or(usize::MAX)
}
pub(crate) fn render_scrollbar(
f: &mut ratatui::Frame<'_>,
area: ratatui::layout::Rect,
conversation_lines: &[String],
effective_scroll: u16,
) {
let inner_h = usize::from(area.height);
let total_lines = conversation_lines.len();
let base_scroll_for_bar = u16_from_usize_saturating(total_lines.saturating_sub(inner_h));
if inner_h == 0 {
return;
}
let bar_x = area.x.saturating_add(area.width.saturating_sub(1));
let bar_y = area.y;
let mut bar =
vec![
Line::from(Span::styled("│", ratatui::style::Style::default().fg(SCROLLBAR_TRACK)));
inner_h
];
if base_scroll_for_bar > 0 {
let inner_h_u32 = u32_from_usize_saturating(inner_h);
let total_lines_u32 = u32_from_usize_saturating(total_lines.max(1));
let thumb_h = ((inner_h_u32 * inner_h_u32) / total_lines_u32).max(1).min(inner_h_u32);
let thumb_h = usize::try_from(thumb_h).unwrap_or(inner_h);
let max_pos = inner_h.saturating_sub(thumb_h);
let thumb_top = if max_pos == 0 {
0
} else {
let max_pos_u64 = u64::try_from(max_pos).unwrap_or(u64::MAX);
usize_from_u64_saturating(
u64::from(effective_scroll) * max_pos_u64 / u64::from(base_scroll_for_bar),
)
};
for line in
bar.iter_mut().take(thumb_top.saturating_add(thumb_h).min(inner_h)).skip(thumb_top)
{
*line =
Line::from(Span::styled("█", ratatui::style::Style::default().fg(SCROLLBAR_THUMB)));
}
} else {
for line in &mut bar {
*line =
Line::from(Span::styled("█", ratatui::style::Style::default().fg(SCROLLBAR_TRACK)));
}
}
let bar_area = ratatui::layout::Rect {
x: bar_x,
y: bar_y,
width: 1,
height: u16_from_usize_saturating(inner_h),
};
f.render_widget(Paragraph::new(Text::from(bar)), bar_area);
}
#[cfg(test)]
#[path = "scroll_tests.rs"]
mod scroll_tests;