feat(ui): add configurable scrollback lines and new‑message alert badge
Introduce `ui.scrollback_lines` (default 2000) to cap the number of chat lines kept in memory, with `0` disabling trimming. Implement automatic trimming of older lines, maintain a scroll offset, and show a “↓ New messages (press G)” badge when new messages arrive off‑screen. Update core UI settings, TUI rendering, chat app state, migrations, documentation, and changelog to reflect the new feature.
This commit is contained in:
@@ -826,6 +826,15 @@ fn render_messages(frame: &mut Frame<'_>, area: Rect, app: &mut ChatApp) {
|
||||
lines.push(Line::from("No messages yet. Press 'i' to start typing."));
|
||||
}
|
||||
|
||||
let scrollback_limit = app.scrollback_limit();
|
||||
if scrollback_limit != usize::MAX && lines.len() > scrollback_limit {
|
||||
let removed = lines.len() - scrollback_limit;
|
||||
lines = lines.into_iter().skip(removed).collect();
|
||||
app.apply_chat_scrollback_trim(removed, lines.len());
|
||||
} else {
|
||||
app.apply_chat_scrollback_trim(0, lines.len());
|
||||
}
|
||||
|
||||
// Apply visual selection highlighting if in visual mode and Chat panel is focused
|
||||
if matches!(app.mode(), InputMode::Visual)
|
||||
&& matches!(app.focused_panel(), FocusedPanel::Chat)
|
||||
@@ -860,6 +869,31 @@ fn render_messages(frame: &mut Frame<'_>, area: Rect, app: &mut ChatApp) {
|
||||
|
||||
frame.render_widget(paragraph, area);
|
||||
|
||||
if app.has_new_message_alert() {
|
||||
let badge_text = "↓ New messages (press G)";
|
||||
let text_width = badge_text.chars().count() as u16;
|
||||
let badge_width = text_width.saturating_add(2);
|
||||
if area.width > badge_width + 1 && area.height > 2 {
|
||||
let badge_x = area.x + area.width.saturating_sub(badge_width + 1);
|
||||
let badge_y = area.y + 1;
|
||||
let badge_area = Rect::new(badge_x, badge_y, badge_width, 1);
|
||||
frame.render_widget(Clear, badge_area);
|
||||
let badge_line = Line::from(Span::styled(
|
||||
format!(" {badge_text} "),
|
||||
Style::default()
|
||||
.fg(theme.background)
|
||||
.bg(theme.info)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
));
|
||||
frame.render_widget(
|
||||
Paragraph::new(badge_line)
|
||||
.style(Style::default().bg(theme.info).fg(theme.background))
|
||||
.alignment(Alignment::Center),
|
||||
badge_area,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Render cursor if Chat panel is focused and in Normal mode
|
||||
if matches!(app.focused_panel(), FocusedPanel::Chat) && matches!(app.mode(), InputMode::Normal)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user