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 mut lines = Vec::new();
|
||||||
let is_selected = selected_msg_id == Some(msg.id());
|
let is_selected = selected_msg_id == Some(msg.id());
|
||||||
|
|
||||||
// Маркер выбора
|
// Маркер выбора (всегда резервируем место для ▶, чтобы текст не сдвигался)
|
||||||
let selection_marker = if is_selected { "▶ " } else { "" };
|
let selection_marker = if is_selected { "▶ " } else { " " };
|
||||||
let marker_len = selection_marker.chars().count();
|
let marker_len = 2;
|
||||||
|
|
||||||
// Цвет сообщения
|
// Цвет сообщения
|
||||||
let msg_color = if is_selected {
|
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 full_len = line_len + time_mark_len + marker_len;
|
||||||
let padding = content_width.saturating_sub(full_len + 1);
|
let padding = content_width.saturating_sub(full_len + 1);
|
||||||
let mut line_spans = vec![Span::raw(" ".repeat(padding))];
|
let mut line_spans = vec![Span::raw(" ".repeat(padding))];
|
||||||
if is_selected && i == 0 {
|
if i == 0 {
|
||||||
// Одна строка — маркер на ней
|
// Первая (или единственная) строка — маркер
|
||||||
line_spans.push(Span::styled(
|
line_spans.push(Span::styled(
|
||||||
selection_marker,
|
selection_marker,
|
||||||
Style::default()
|
Style::default()
|
||||||
.fg(Color::Yellow)
|
.fg(Color::Yellow)
|
||||||
.add_modifier(Modifier::BOLD),
|
.add_modifier(Modifier::BOLD),
|
||||||
));
|
));
|
||||||
} else if is_selected {
|
} else {
|
||||||
// Последняя строка multi-line — пробелы вместо маркера
|
// Остальные строки multi-line — пробелы вместо маркера
|
||||||
line_spans.push(Span::raw(" ".repeat(marker_len)));
|
line_spans.push(Span::raw(" ".repeat(marker_len)));
|
||||||
}
|
}
|
||||||
line_spans.extend(formatted_spans);
|
line_spans.extend(formatted_spans);
|
||||||
@@ -327,14 +327,14 @@ pub fn render_message_bubble(
|
|||||||
} else {
|
} else {
|
||||||
let padding = content_width.saturating_sub(line_len + marker_len + 1);
|
let padding = content_width.saturating_sub(line_len + marker_len + 1);
|
||||||
let mut line_spans = vec![Span::raw(" ".repeat(padding))];
|
let mut line_spans = vec![Span::raw(" ".repeat(padding))];
|
||||||
if i == 0 && is_selected {
|
if i == 0 {
|
||||||
line_spans.push(Span::styled(
|
line_spans.push(Span::styled(
|
||||||
selection_marker,
|
selection_marker,
|
||||||
Style::default()
|
Style::default()
|
||||||
.fg(Color::Yellow)
|
.fg(Color::Yellow)
|
||||||
.add_modifier(Modifier::BOLD),
|
.add_modifier(Modifier::BOLD),
|
||||||
));
|
));
|
||||||
} else if is_selected {
|
} else {
|
||||||
// Средние строки multi-line — пробелы вместо маркера
|
// Средние строки multi-line — пробелы вместо маркера
|
||||||
line_spans.push(Span::raw(" ".repeat(marker_len)));
|
line_spans.push(Span::raw(" ".repeat(marker_len)));
|
||||||
}
|
}
|
||||||
@@ -364,14 +364,12 @@ pub fn render_message_bubble(
|
|||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
let mut line_spans = vec![];
|
let mut line_spans = vec![];
|
||||||
if is_selected {
|
line_spans.push(Span::styled(
|
||||||
line_spans.push(Span::styled(
|
selection_marker,
|
||||||
selection_marker,
|
Style::default()
|
||||||
Style::default()
|
.fg(Color::Yellow)
|
||||||
.fg(Color::Yellow)
|
.add_modifier(Modifier::BOLD),
|
||||||
.add_modifier(Modifier::BOLD),
|
));
|
||||||
));
|
|
||||||
}
|
|
||||||
line_spans
|
line_spans
|
||||||
.push(Span::styled(format!(" {}", time_str), Style::default().fg(Color::Gray)));
|
.push(Span::styled(format!(" {}", time_str), Style::default().fg(Color::Gray)));
|
||||||
line_spans.push(Span::raw(" "));
|
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_selected = messages.iter().any(|m| selected_msg_id == Some(m.id()));
|
||||||
let is_outgoing = messages.first().is_some_and(|m| m.is_outgoing());
|
let is_outgoing = messages.first().is_some_and(|m| m.is_outgoing());
|
||||||
|
|
||||||
// Selection marker
|
// Selection marker (всегда резервируем место)
|
||||||
let selection_marker = if is_selected { "▶ " } else { "" };
|
let selection_marker = if is_selected { "▶ " } else { " " };
|
||||||
|
|
||||||
// Фильтруем фото
|
// Фильтруем фото
|
||||||
let photos: Vec<&MessageInfo> = messages.iter().filter(|m| m.has_photo()).collect();
|
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 cols = photo_count.min(ALBUM_GRID_MAX_COLS);
|
||||||
let rows = photo_count.div_ceil(cols);
|
let rows = photo_count.div_ceil(cols);
|
||||||
|
|
||||||
// Добавляем маркер выбора на первую строку
|
// Добавляем маркер выбора на первую строку (всегда — для постоянного отступа)
|
||||||
if is_selected {
|
lines.push(Line::from(vec![Span::styled(
|
||||||
lines.push(Line::from(vec![Span::styled(
|
selection_marker,
|
||||||
selection_marker,
|
Style::default()
|
||||||
Style::default()
|
.fg(Color::Yellow)
|
||||||
.fg(Color::Yellow)
|
.add_modifier(Modifier::BOLD),
|
||||||
.add_modifier(Modifier::BOLD),
|
)]));
|
||||||
)]));
|
|
||||||
}
|
|
||||||
|
|
||||||
let grid_start_line = lines.len();
|
let grid_start_line = lines.len();
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│Mom ──────────────── │
|
│Mom ──────────────── │
|
||||||
│ (14:33) What do you think about this? │
|
│ (14:33) What do you think about this? │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│Alice ──────────────── │
|
│Alice ──────────────── │
|
||||||
│ (14:33) 📷 [Фото] │
|
│ (14:33) 📷 [Фото] │
|
||||||
│ (14:33) Caption for album │
|
│ (14:33) Caption for album │
|
||||||
│ (14:33) 📷 [Фото] │
|
│ (14:33) 📷 [Фото] │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│Alice ──────────────── │
|
│Alice ──────────────── │
|
||||||
│ (14:33) 📷 [Фото] │
|
│ (14:33) 📷 [Фото] │
|
||||||
│▶ (14:33) 📷 [Фото] │
|
│▶ (14:33) 📷 [Фото] │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│Alice ──────────────── │
|
│Alice ──────────────── │
|
||||||
│ (14:33) Regular message before │
|
│ (14:33) Regular message before │
|
||||||
│ (14:33) 📷 [Фото] │
|
│ (14:33) 📷 [Фото] │
|
||||||
│ (14:33) Album caption │
|
│ (14:33) Album caption │
|
||||||
│ (14:33) Regular message after │
|
│ (14:33) Regular message after │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│User ──────────────── │
|
│User ──────────────── │
|
||||||
│ (14:33) Message from the past │
|
│ (14:33) Message from the past │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│User ──────────────── │
|
│User ──────────────── │
|
||||||
│ (14:33 ✎) Edited text │
|
│ (14:33 ✎) Edited text │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ expression: output
|
|||||||
│ │
|
│ │
|
||||||
│User ──────────────── │
|
│User ──────────────── │
|
||||||
│↪ Переслано от Alice │
|
│↪ Переслано от Alice │
|
||||||
│ (14:33) Forwarded content │
|
│ (14:33) Forwarded content │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│User ──────────────── │
|
│User ──────────────── │
|
||||||
│ (14:33) This is a very long message that should wrap across multiple lines │
|
│ (14:33) This is a very long message that should wrap across multiple lines │
|
||||||
│ when rendered in the terminal UI. Let's make it even longer to │
|
│ when rendered in the terminal UI. Let's make it even longer to │
|
||||||
│ ensure we test the wrapping behavior properly. │
|
│ ensure we test the wrapping behavior properly. │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│User ──────────────── │
|
│User ──────────────── │
|
||||||
│ (14:33) **bold** *italic* `code` │
|
│ (14:33) **bold** *italic* `code` │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│User ──────────────── │
|
│User ──────────────── │
|
||||||
│ (14:33) Check [this](https://example.com) and @username │
|
│ (14:33) Check [this](https://example.com) and @username │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│User ──────────────── │
|
│User ──────────────── │
|
||||||
│ (14:33) Spoiler: ||hidden text|| │
|
│ (14:33) Spoiler: ||hidden text|| │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│User ──────────────── │
|
│User ──────────────── │
|
||||||
│ (14:33) [Фото] │
|
│ (14:33) [Фото] │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│User ──────────────── │
|
│User ──────────────── │
|
||||||
│ (14:33) Popular message │
|
│ (14:33) Popular message │
|
||||||
│[👍 ] 5 👎 3 │
|
│[👍 ] 5 👎 3 │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ expression: output
|
|||||||
│ │
|
│ │
|
||||||
│User ──────────────── │
|
│User ──────────────── │
|
||||||
│┌ Mom: Original message text │
|
│┌ Mom: Original message text │
|
||||||
│ (14:33) This is a reply │
|
│ (14:33) This is a reply │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│User ──────────────── │
|
│User ──────────────── │
|
||||||
│ (14:33) Selected message │
|
│ (14:33) Selected message │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│Alice ──────────────── │
|
│Alice ──────────────── │
|
||||||
│ (14:33) First message │
|
│ (14:33) First message │
|
||||||
│ (14:33) Second message │
|
│ (14:33) Second message │
|
||||||
│ │
|
│ │
|
||||||
│Bob ──────────────── │
|
│Bob ──────────────── │
|
||||||
│ (14:33) Third message │
|
│ (14:33) Third message │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│Mom ──────────────── │
|
│Mom ──────────────── │
|
||||||
│ (14:33) Hello there! │
|
│ (14:33) Hello there! │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│User ──────────────── │
|
│User ──────────────── │
|
||||||
│ (14:33) Great! │
|
│ (14:33) Great! │
|
||||||
│[👍 ] │
|
│[👍 ] │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│User ──────────────── │
|
│User ──────────────── │
|
||||||
│ (14:33) React to this │
|
│ (14:33) React to this │
|
||||||
│ │
|
│ │
|
||||||
│ ┌ Выбери реакцию ────────────────────────────────┐ │
|
│ ┌ Выбери реакцию ────────────────────────────────┐ │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│User ──────────────── │
|
│User ──────────────── │
|
||||||
│ (14:33) React to this │
|
│ (14:33) React to this │
|
||||||
│ │
|
│ │
|
||||||
│ ┌ Выбери реакцию ────────────────────────────────┐ │
|
│ ┌ Выбери реакцию ────────────────────────────────┐ │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ expression: output
|
|||||||
│ ──────── 02.01.2022 ──────── │
|
│ ──────── 02.01.2022 ──────── │
|
||||||
│ │
|
│ │
|
||||||
│User ──────────────── │
|
│User ──────────────── │
|
||||||
│ (14:33) Regular message │
|
│ (14:33) Regular message │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
│ │
|
│ │
|
||||||
|
|||||||
Reference in New Issue
Block a user