... at the end of the dialog truncation
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -436,6 +436,7 @@ dependencies = [
|
|||||||
"toml",
|
"toml",
|
||||||
"tonic",
|
"tonic",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"unicode-segmentation",
|
||||||
"unicode-width 0.2.0",
|
"unicode-width 0.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -19,4 +19,5 @@ tokio = { version = "1.43.0", features = ["full", "macros"] }
|
|||||||
toml = "0.8.20"
|
toml = "0.8.20"
|
||||||
tonic = "0.12.3"
|
tonic = "0.12.3"
|
||||||
tracing = "0.1.41"
|
tracing = "0.1.41"
|
||||||
|
unicode-segmentation = "1.12.0"
|
||||||
unicode-width = "0.2.0"
|
unicode-width = "0.2.0"
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
// src/components/common/dialog.rs
|
|
||||||
use crate::config::colors::themes::Theme;
|
use crate::config::colors::themes::Theme;
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
layout::{Constraint, Direction, Layout, Margin, Rect},
|
layout::{Constraint, Direction, Layout, Margin, Rect},
|
||||||
prelude::Alignment,
|
prelude::Alignment,
|
||||||
style::{Modifier, Style},
|
style::{Modifier, Style},
|
||||||
text::{Line, Span, Text},
|
text::{Line, Span, Text},
|
||||||
widgets::{Block, BorderType, Borders, Paragraph, Clear}, // Added Clear
|
widgets::{Block, BorderType, Borders, Paragraph, Clear},
|
||||||
Frame,
|
Frame,
|
||||||
};
|
};
|
||||||
|
use unicode_segmentation::UnicodeSegmentation; // For grapheme clusters
|
||||||
|
use unicode_width::UnicodeWidthStr; // For accurate width calculation
|
||||||
|
|
||||||
pub fn render_dialog(
|
pub fn render_dialog(
|
||||||
f: &mut Frame,
|
f: &mut Frame,
|
||||||
@@ -18,15 +19,16 @@ pub fn render_dialog(
|
|||||||
dialog_buttons: &[String],
|
dialog_buttons: &[String],
|
||||||
dialog_active_button_index: usize,
|
dialog_active_button_index: usize,
|
||||||
) {
|
) {
|
||||||
|
// Calculate required height based on the actual number of lines in the message
|
||||||
let message_lines: Vec<_> = dialog_message.lines().collect();
|
let message_lines: Vec<_> = dialog_message.lines().collect();
|
||||||
let message_height = message_lines.len() as u16;
|
let message_height = message_lines.len() as u16;
|
||||||
let button_row_height = if dialog_buttons.is_empty() { 0 } else { 3 };
|
let button_row_height = if dialog_buttons.is_empty() { 0 } else { 3 };
|
||||||
let vertical_padding = 2; // Block borders (top/bottom)
|
let vertical_padding = 2; // Block borders (top/bottom)
|
||||||
let inner_vertical_margin = 2; // Margin inside block (top/bottom)
|
let inner_vertical_margin = 2; // Margin inside block (top/bottom)
|
||||||
|
|
||||||
|
// Calculate required height based on actual message lines
|
||||||
let required_inner_height =
|
let required_inner_height =
|
||||||
message_height + button_row_height + inner_vertical_margin;
|
message_height + button_row_height + inner_vertical_margin;
|
||||||
// Add block border height
|
|
||||||
let required_total_height = required_inner_height + vertical_padding;
|
let required_total_height = required_inner_height + vertical_padding;
|
||||||
|
|
||||||
// Use a fixed percentage width, clamped to min/max
|
// Use a fixed percentage width, clamped to min/max
|
||||||
@@ -61,10 +63,10 @@ pub fn render_dialog(
|
|||||||
vertical: 1, // Top/Bottom padding inside border
|
vertical: 1, // Top/Bottom padding inside border
|
||||||
});
|
});
|
||||||
|
|
||||||
// Layout for Message and Buttons
|
// Layout for Message and Buttons based on actual message height
|
||||||
let mut constraints = vec![
|
let mut constraints = vec![
|
||||||
// Allocate space for message, ensuring at least 1 line height
|
// Allocate space for message, ensuring at least 1 line height
|
||||||
Constraint::Min(message_height.max(1)),
|
Constraint::Length(message_height.max(1)), // Use actual calculated height
|
||||||
];
|
];
|
||||||
if button_row_height > 0 {
|
if button_row_height > 0 {
|
||||||
constraints.push(Constraint::Length(button_row_height));
|
constraints.push(Constraint::Length(button_row_height));
|
||||||
@@ -76,15 +78,39 @@ pub fn render_dialog(
|
|||||||
.split(inner_area);
|
.split(inner_area);
|
||||||
|
|
||||||
// Render Message
|
// Render Message
|
||||||
let message_text = Text::from(
|
let available_width = inner_area.width as usize;
|
||||||
|
let ellipsis = "...";
|
||||||
|
let ellipsis_width = UnicodeWidthStr::width(ellipsis);
|
||||||
|
|
||||||
|
let processed_lines: Vec<Line> =
|
||||||
message_lines
|
message_lines
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|l| Line::from(Span::styled(l, Style::default().fg(theme.fg))))
|
.map(|line| {
|
||||||
.collect::<Vec<_>>(),
|
let line_width = UnicodeWidthStr::width(line);
|
||||||
);
|
if line_width > available_width {
|
||||||
|
// Truncate with ellipsis
|
||||||
|
let mut truncated_len = 0;
|
||||||
|
let mut current_width = 0;
|
||||||
|
// Iterate over graphemes to handle multi-byte characters correctly
|
||||||
|
for (idx, grapheme) in line.grapheme_indices(true) {
|
||||||
|
let grapheme_width = UnicodeWidthStr::width(grapheme);
|
||||||
|
if current_width + grapheme_width > available_width.saturating_sub(ellipsis_width) {
|
||||||
|
break; // Stop before exceeding width needed for text + ellipsis
|
||||||
|
}
|
||||||
|
current_width += grapheme_width;
|
||||||
|
truncated_len = idx + grapheme.len(); // Store the byte index of the end of the last fitting grapheme
|
||||||
|
}
|
||||||
|
let truncated_line = format!("{}{}", &line[..truncated_len], ellipsis);
|
||||||
|
Line::from(Span::styled(truncated_line, Style::default().fg(theme.fg)))
|
||||||
|
} else {
|
||||||
|
// Line fits, use it as is
|
||||||
|
Line::from(Span::styled(line, Style::default().fg(theme.fg)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
let message_paragraph =
|
let message_paragraph =
|
||||||
Paragraph::new(message_text).alignment(Alignment::Center);
|
Paragraph::new(Text::from(processed_lines)).alignment(Alignment::Center);
|
||||||
// Render message in the first chunk
|
// Render message in the first chunk
|
||||||
f.render_widget(message_paragraph, chunks[0]);
|
f.render_widget(message_paragraph, chunks[0]);
|
||||||
|
|
||||||
@@ -143,4 +169,3 @@ pub fn render_dialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user