(&self, frame: &mut Frame, area: Rect, theme: &Theme)
| 81 | } |
| 82 | |
| 83 | pub fn render(&self, frame: &mut Frame, area: Rect, theme: &Theme) { |
| 84 | if !self.open { |
| 85 | return; |
| 86 | } |
| 87 | let dialog_width = 70u16.min(area.width.saturating_sub(4)); |
| 88 | let dialog_height = 20u16.min(area.height.saturating_sub(4)); |
| 89 | let dialog_area = centered_rect(dialog_width, dialog_height, area); |
| 90 | frame.render_widget(Clear, dialog_area); |
| 91 | let block = Block::default() |
| 92 | .title(Span::styled( |
| 93 | " Fork Session ", |
| 94 | Style::default() |
| 95 | .fg(theme.primary) |
| 96 | .add_modifier(Modifier::BOLD), |
| 97 | )) |
| 98 | .borders(Borders::ALL) |
| 99 | .border_style(Style::default().fg(theme.border)) |
| 100 | .style(Style::default().bg(theme.background_panel)); |
| 101 | let inner = super::dialog_inner(block.inner(dialog_area)); |
| 102 | frame.render_widget(block, dialog_area); |
| 103 | if self.entries.is_empty() { |
| 104 | let empty = ratatui::widgets::Paragraph::new("No messages to fork from") |
| 105 | .style(Style::default().fg(theme.text_muted)); |
| 106 | frame.render_widget(empty, inner); |
| 107 | return; |
| 108 | } |
| 109 | let hint = ratatui::widgets::Paragraph::new( |
| 110 | "Select a message to fork from. Enter to confirm, Esc to cancel.", |
| 111 | ) |
| 112 | .style(Style::default().fg(theme.text_muted)); |
| 113 | frame.render_widget( |
| 114 | hint, |
| 115 | Rect { |
| 116 | x: inner.x, |
| 117 | y: inner.y, |
| 118 | width: inner.width, |
| 119 | height: 1, |
| 120 | }, |
| 121 | ); |
| 122 | let list_area = Rect { |
| 123 | x: inner.x, |
| 124 | y: inner.y + 2, |
| 125 | width: inner.width, |
| 126 | height: inner.height.saturating_sub(2), |
| 127 | }; |
| 128 | let items: Vec<ListItem> = self |
| 129 | .entries |
| 130 | .iter() |
| 131 | .map(|entry| { |
| 132 | let role_icon = match entry.role.as_str() { |
| 133 | "user" => "[U]", |
| 134 | "assistant" => "[A]", |
| 135 | _ => "[S]", |
| 136 | }; |
| 137 | ListItem::new(Line::from(vec![ |
| 138 | Span::styled( |
| 139 | format!("{} ", role_icon), |
| 140 | Style::default().fg(theme.primary), |
nothing calls this directly
no test coverage detected