//! Overlay: Rewind / session history — shows recent messages and lets the user //! pick a point to rewind the transcript back to. //! //! Flow: reads the last 8 messages from `state.transcript_cache.messages`, //! renders each with a role tag and content preview; an overflow note is //! appended when there are more than 8 messages. The input controller handles //! ↑/↓ navigation and Enter to confirm the rewind point. use ratatui::style::{Modifier, Style}; use ratatui::text::{Line, Span}; use ratatui::widgets::{Block, Paragraph}; use ratatui::Frame; use crate::view::theme::Theme; use tracing; /// Render the Rewind overlay — message list with role tags and previews. pub fn render( frame: &mut Frame, area: ratatui::layout::Rect, block: Block<'static>, state: &crate::app::state::rest::AppStateRest, ) { tracing::debug!("overlay: Rewind (messages={})", state.transcript_cache.messages.len()); let block = block .title(Span::styled( " Rewind ", Style::default() .fg(Theme::ACCENT_ORANGE) .add_modifier(Modifier::BOLD), )) .border_style(Style::default().fg(Theme::ACCENT_ORANGE)); let mut lines: Vec = vec![ Line::from(Span::styled( " Use ↑↓ to navigate, Enter to rewind to that point", Style::default().fg(Theme::TEXT_DIM), )), Line::from(Span::raw("")), ]; let messages = &state.transcript_cache.messages; if messages.is_empty() { lines.push(Line::from(Span::styled( " No messages in current session.", Style::default().fg(Theme::TEXT_DIM), ))); } else { let start = if messages.len() > 8 { messages.len() - 8 } else { 0 }; for msg in &messages[start..] { let role_str = match msg.role { crate::dto::chat::message::Role::User => "User", crate::dto::chat::message::Role::Assistant => "Asst", crate::dto::chat::message::Role::System => "Sys", crate::dto::chat::message::Role::Tool => "Tool", }; let preview: String = msg.content.chars().take(70).collect(); lines.push(Line::from(Span::styled( format!(" [{role_str}] {preview}"), Style::default().fg( if matches!(msg.role, crate::dto::chat::message::Role::User) { Theme::INFO } else { Theme::TEXT }, ), ))); } if messages.len() > 8 { lines.push(Line::from(Span::styled( format!(" ... and {} more messages", messages.len() - 8), Style::default().fg(Theme::TEXT_DIM), ))); } } let paragraph = Paragraph::new(lines).block(block); frame.render_widget(paragraph, area); }