mirror of
https://github.com/hanzoai/dev.git
synced 2026-10-25 03:32:32 +00:00
fix(tui/resume): apply theme bg/fg + border to dialog block for consistent theming across all popups
This commit is contained in:
@@ -129,10 +129,14 @@ impl BottomPaneView<'_> for ResumeSelectionView {
|
||||
fn render(&self, area: Rect, buf: &mut Buffer) {
|
||||
if area.height == 0 || area.width == 0 { return; }
|
||||
|
||||
// Clear and draw a bordered block that uses the active theme colors.
|
||||
// Other popups (e.g., list_selection_view) already do this; mirroring
|
||||
// that treatment ensures dialogs respect dark/light themes.
|
||||
Clear.render(area, buf);
|
||||
let block = Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_style(Style::default().fg(crate::colors::light_blue()))
|
||||
.border_style(Style::default().fg(crate::colors::border()))
|
||||
.style(Style::default().bg(crate::colors::background()).fg(crate::colors::text()))
|
||||
.title(self.title.clone())
|
||||
.title_alignment(Alignment::Center);
|
||||
let inner = block.inner(area);
|
||||
@@ -205,6 +209,8 @@ impl BottomPaneView<'_> for ResumeSelectionView {
|
||||
Span::styled("Esc", Style::default().fg(crate::colors::error())),
|
||||
Span::raw(" Cancel"),
|
||||
]);
|
||||
Paragraph::new(footer_line).render(footer, buf);
|
||||
Paragraph::new(footer_line)
|
||||
.style(Style::default().bg(crate::colors::background()).fg(crate::colors::text()))
|
||||
.render(footer, buf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3093,7 +3093,7 @@ impl HistoryCell for CollapsibleReasoningCell {
|
||||
pub(crate) struct StreamingContentCell {
|
||||
pub(crate) id: Option<String>,
|
||||
pub(crate) lines: Vec<Line<'static>>,
|
||||
// Show an ellipsis on a new line while streaming is in progress
|
||||
// Show an ellipsis appended to the last line while streaming
|
||||
pub(crate) show_ellipsis: bool,
|
||||
}
|
||||
|
||||
@@ -3193,9 +3193,7 @@ impl HistoryCell for StreamingContentCell {
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut total = total.saturating_add(2);
|
||||
if self.show_ellipsis { total = total.saturating_add(1); }
|
||||
total
|
||||
total.saturating_add(2)
|
||||
}
|
||||
fn custom_render_with_skip(&self, area: Rect, buf: &mut Buffer, skip_rows: u16) {
|
||||
// Render with a 1-row top and bottom padding, all using the assistant bg tint.
|
||||
@@ -3255,9 +3253,19 @@ impl HistoryCell for StreamingContentCell {
|
||||
_is_first_output_line = false;
|
||||
}
|
||||
if !text_buf.is_empty() { segs.push(Seg::Text(std::mem::take(&mut text_buf))); }
|
||||
// Append an ellipsis line as its own segment when streaming
|
||||
// If streaming, append an ellipsis span to the last line of the last segment
|
||||
if self.show_ellipsis {
|
||||
segs.push(Seg::Text(vec![Line::from("…".dim())]));
|
||||
if let Some(last) = segs.last_mut() {
|
||||
match last {
|
||||
Seg::Text(lines) | Seg::Bullet(lines) | Seg::Code(lines) => {
|
||||
if let Some(last_line) = lines.last_mut() {
|
||||
let mut spans = std::mem::take(&mut last_line.spans);
|
||||
spans.push(Span::styled(" …", Style::default().fg(crate::colors::text_dim())));
|
||||
last_line.spans = spans;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Streaming-style top padding row
|
||||
|
||||
@@ -621,12 +621,53 @@ impl StreamController {
|
||||
message.len()
|
||||
);
|
||||
let committed = state.collector.committed_count();
|
||||
// Heuristic fix: if the very first committed line looks like
|
||||
// a truncated title (prefix of the final first line), drop it
|
||||
// from the committed region so the final replaces it.
|
||||
let cfg = self.config.clone();
|
||||
// Render current buffer preview
|
||||
let prior_src = state.collector.full_render_source_preview();
|
||||
let mut prior_lines: Vec<ratatui::text::Line<'static>> = Vec::new();
|
||||
crate::markdown::append_markdown(&prior_src, &mut prior_lines, &cfg);
|
||||
// Extract first non-blank among the already committed lines
|
||||
let committed_first = if committed > 0 {
|
||||
let mut out = String::new();
|
||||
for l in prior_lines.iter().take(committed) {
|
||||
if !crate::render::line_utils::is_blank_line_trim(l) {
|
||||
out = l.spans.iter().map(|s| s.content.clone()).collect::<Vec<_>>().join("");
|
||||
break;
|
||||
}
|
||||
}
|
||||
out
|
||||
} else { String::new() };
|
||||
// Render final message's first line
|
||||
let mut final_lines: Vec<ratatui::text::Line<'static>> = Vec::new();
|
||||
let mut msg_preview = message.to_string();
|
||||
if !msg_preview.ends_with('\n') { msg_preview.push('\n'); }
|
||||
crate::markdown::append_markdown(&msg_preview, &mut final_lines, &cfg);
|
||||
let final_first = final_lines.iter()
|
||||
.find(|l| !crate::render::line_utils::is_blank_line_trim(l))
|
||||
.map(|l| l.spans.iter().map(|s| s.content.clone()).collect::<Vec<_>>().join(""))
|
||||
.unwrap_or_default();
|
||||
let mut committed_adj = committed;
|
||||
if committed > 0
|
||||
&& !committed_first.is_empty()
|
||||
&& final_first.starts_with(&committed_first)
|
||||
&& final_first.len() > committed_first.len()
|
||||
&& committed_first.chars().count() <= 16
|
||||
{
|
||||
committed_adj = committed.saturating_sub(1);
|
||||
tracing::debug!(
|
||||
"reasoning prefix-upgrade: committed_first='{}' -> final_first='{}' (committed {}->{}))",
|
||||
committed_first, final_first, committed, committed_adj
|
||||
);
|
||||
}
|
||||
let mut msg = message.to_owned();
|
||||
if !msg.ends_with('\n') { msg.push('\n'); }
|
||||
let state_mut = self.state_mut(kind);
|
||||
state_mut
|
||||
.collector
|
||||
.replace_with_and_mark_committed(&msg, committed);
|
||||
.replace_with_and_mark_committed(&msg, committed_adj);
|
||||
return self.finalize(kind, immediate, sink);
|
||||
}
|
||||
// For Answer (or empty message), finalize existing streamed content.
|
||||
|
||||
Reference in New Issue
Block a user