fix: always reserve space for selection marker to prevent text shift #23
@@ -221,9 +221,9 @@ pub fn render_message_bubble(
|
||||
let mut lines = Vec::new();
|
||||
let is_selected = selected_msg_id == Some(msg.id());
|
||||
|
||||
// Маркер выбора
|
||||
let selection_marker = if is_selected { "▶ " } else { "" };
|
||||
let marker_len = selection_marker.chars().count();
|
||||
// Маркер выбора (всегда резервируем место для ▶, чтобы текст не сдвигался)
|
||||
let selection_marker = if is_selected { "▶ " } else { " " };
|
||||
let marker_len = 2;
|
||||
|
||||
// Цвет сообщения
|
||||
let msg_color = if is_selected {
|
||||
@@ -306,16 +306,16 @@ pub fn render_message_bubble(
|
||||
let full_len = line_len + time_mark_len + marker_len;
|
||||
let padding = content_width.saturating_sub(full_len + 1);
|
||||
let mut line_spans = vec![Span::raw(" ".repeat(padding))];
|
||||
if is_selected && i == 0 {
|
||||
// Одна строка — маркер на ней
|
||||
if i == 0 {
|
||||
// Первая (или единственная) строка — маркер
|
||||
line_spans.push(Span::styled(
|
||||
selection_marker,
|
||||
Style::default()
|
||||
.fg(Color::Yellow)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
));
|
||||
} else if is_selected {
|
||||
// Последняя строка multi-line — пробелы вместо маркера
|
||||
} else {
|
||||
// Остальные строки multi-line — пробелы вместо маркера
|
||||
line_spans.push(Span::raw(" ".repeat(marker_len)));
|
||||
}
|
||||
line_spans.extend(formatted_spans);
|
||||
@@ -327,14 +327,14 @@ pub fn render_message_bubble(
|
||||
} else {
|
||||
let padding = content_width.saturating_sub(line_len + marker_len + 1);
|
||||
let mut line_spans = vec![Span::raw(" ".repeat(padding))];
|
||||
if i == 0 && is_selected {
|
||||
if i == 0 {
|
||||
line_spans.push(Span::styled(
|
||||
selection_marker,
|
||||
Style::default()
|
||||
.fg(Color::Yellow)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
));
|
||||
} else if is_selected {
|
||||
} else {
|
||||
// Средние строки multi-line — пробелы вместо маркера
|
||||
line_spans.push(Span::raw(" ".repeat(marker_len)));
|
||||
}
|
||||
@@ -364,14 +364,12 @@ pub fn render_message_bubble(
|
||||
|
||||
if i == 0 {
|
||||
let mut line_spans = vec![];
|
||||
if is_selected {
|
||||
line_spans.push(Span::styled(
|
||||
selection_marker,
|
||||
Style::default()
|
||||
.fg(Color::Yellow)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
));
|
||||
}
|
||||
line_spans
|
||||
.push(Span::styled(format!(" {}", time_str), Style::default().fg(Color::Gray)));
|
||||
line_spans.push(Span::raw(" "));
|
||||
@@ -548,8 +546,8 @@ pub fn render_album_bubble(
|
||||
let is_selected = messages.iter().any(|m| selected_msg_id == Some(m.id()));
|
||||
let is_outgoing = messages.first().is_some_and(|m| m.is_outgoing());
|
||||
|
||||
// Selection marker
|
||||
let selection_marker = if is_selected { "▶ " } else { "" };
|
||||
// Selection marker (всегда резервируем место)
|
||||
let selection_marker = if is_selected { "▶ " } else { " " };
|
||||
|
||||
// Фильтруем фото
|
||||
let photos: Vec<&MessageInfo> = messages.iter().filter(|m| m.has_photo()).collect();
|
||||
@@ -567,15 +565,13 @@ pub fn render_album_bubble(
|
||||
let cols = photo_count.min(ALBUM_GRID_MAX_COLS);
|
||||
let rows = photo_count.div_ceil(cols);
|
||||
|
||||
// Добавляем маркер выбора на первую строку
|
||||
if is_selected {
|
||||
// Добавляем маркер выбора на первую строку (всегда — для постоянного отступа)
|
||||
lines.push(Line::from(vec![Span::styled(
|
||||
selection_marker,
|
||||
Style::default()
|
||||
.fg(Color::Yellow)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
)]));
|
||||
}
|
||||
|
||||
let grid_start_line = lines.len();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user