style: auto-format entire codebase with cargo fmt (stable rustfmt.toml)
Some checks failed
ci/woodpecker/pr/check Pipeline failed
CI / Check (pull_request) Has been cancelled
CI / Format (pull_request) Has been cancelled
CI / Clippy (pull_request) Has been cancelled
CI / Build (macos-latest) (pull_request) Has been cancelled
CI / Build (ubuntu-latest) (pull_request) Has been cancelled
CI / Build (windows-latest) (pull_request) Has been cancelled

This commit is contained in:
Mikhail Kilin
2026-02-22 17:09:51 +03:00
parent 2442a90e23
commit 264f183510
90 changed files with 1632 additions and 1450 deletions

View File

@@ -7,9 +7,9 @@
use crate::config::Config;
use crate::formatting;
use crate::tdlib::{MessageInfo, PlaybackState, PlaybackStatus};
#[cfg(feature = "images")]
use crate::tdlib::PhotoDownloadState;
use crate::tdlib::{MessageInfo, PlaybackState, PlaybackStatus};
use crate::types::MessageId;
use crate::utils::{format_date, format_timestamp_with_tz};
use ratatui::{
@@ -36,10 +36,7 @@ fn wrap_text_with_offsets(text: &str, max_width: usize) -> Vec<WrappedLine> {
}
if all_lines.is_empty() {
all_lines.push(WrappedLine {
text: String::new(),
start_offset: 0,
});
all_lines.push(WrappedLine { text: String::new(), start_offset: 0 });
}
all_lines
@@ -48,10 +45,7 @@ fn wrap_text_with_offsets(text: &str, max_width: usize) -> Vec<WrappedLine> {
/// Разбивает один абзац (без `\n`) на строки по ширине
fn wrap_paragraph(text: &str, max_width: usize, base_offset: usize) -> Vec<WrappedLine> {
if max_width == 0 {
return vec![WrappedLine {
text: text.to_string(),
start_offset: base_offset,
}];
return vec![WrappedLine { text: text.to_string(), start_offset: base_offset }];
}
let mut result = Vec::new();
@@ -122,10 +116,7 @@ fn wrap_paragraph(text: &str, max_width: usize, base_offset: usize) -> Vec<Wrapp
}
if result.is_empty() {
result.push(WrappedLine {
text: String::new(),
start_offset: base_offset,
});
result.push(WrappedLine { text: String::new(), start_offset: base_offset });
}
result
@@ -138,7 +129,11 @@ fn wrap_paragraph(text: &str, max_width: usize, base_offset: usize) -> Vec<Wrapp
/// * `date` - timestamp сообщения
/// * `content_width` - ширина области для центрирования
/// * `is_first` - первый ли это разделитель (если нет, добавляется пустая строка сверху)
pub fn render_date_separator(date: i32, content_width: usize, is_first: bool) -> Vec<Line<'static>> {
pub fn render_date_separator(
date: i32,
content_width: usize,
is_first: bool,
) -> Vec<Line<'static>> {
let mut lines = Vec::new();
if !is_first {
@@ -276,10 +271,8 @@ pub fn render_message_bubble(
Span::styled(reply_line, Style::default().fg(Color::Cyan)),
]));
} else {
lines.push(Line::from(vec![Span::styled(
reply_line,
Style::default().fg(Color::Cyan),
)]));
lines
.push(Line::from(vec![Span::styled(reply_line, Style::default().fg(Color::Cyan))]));
}
}
@@ -301,9 +294,13 @@ pub fn render_message_bubble(
let is_last_line = i == total_wrapped - 1;
let line_len = wrapped.text.chars().count();
let line_entities =
formatting::adjust_entities_for_substring(msg.entities(), wrapped.start_offset, line_len);
let formatted_spans = formatting::format_text_with_entities(&wrapped.text, &line_entities, msg_color);
let line_entities = formatting::adjust_entities_for_substring(
msg.entities(),
wrapped.start_offset,
line_len,
);
let formatted_spans =
formatting::format_text_with_entities(&wrapped.text, &line_entities, msg_color);
if is_last_line {
let full_len = line_len + time_mark_len + marker_len;
@@ -313,14 +310,19 @@ pub fn render_message_bubble(
// Одна строка — маркер на ней
line_spans.push(Span::styled(
selection_marker,
Style::default().fg(Color::Yellow).add_modifier(Modifier::BOLD),
Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD),
));
} else if is_selected {
// Последняя строка multi-line — пробелы вместо маркера
line_spans.push(Span::raw(" ".repeat(marker_len)));
}
line_spans.extend(formatted_spans);
line_spans.push(Span::styled(format!(" {}", time_mark), Style::default().fg(Color::Gray)));
line_spans.push(Span::styled(
format!(" {}", time_mark),
Style::default().fg(Color::Gray),
));
lines.push(Line::from(line_spans));
} else {
let padding = content_width.saturating_sub(line_len + marker_len + 1);
@@ -328,7 +330,9 @@ pub fn render_message_bubble(
if i == 0 && is_selected {
line_spans.push(Span::styled(
selection_marker,
Style::default().fg(Color::Yellow).add_modifier(Modifier::BOLD),
Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD),
));
} else if is_selected {
// Средние строки multi-line — пробелы вместо маркера
@@ -350,19 +354,26 @@ pub fn render_message_bubble(
for (i, wrapped) in wrapped_lines.into_iter().enumerate() {
let line_len = wrapped.text.chars().count();
let line_entities =
formatting::adjust_entities_for_substring(msg.entities(), wrapped.start_offset, line_len);
let formatted_spans = formatting::format_text_with_entities(&wrapped.text, &line_entities, msg_color);
let line_entities = formatting::adjust_entities_for_substring(
msg.entities(),
wrapped.start_offset,
line_len,
);
let formatted_spans =
formatting::format_text_with_entities(&wrapped.text, &line_entities, msg_color);
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),
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::styled(format!(" {}", time_str), Style::default().fg(Color::Gray)));
line_spans.push(Span::raw(" "));
line_spans.extend(formatted_spans);
lines.push(Line::from(line_spans));
@@ -439,10 +450,7 @@ pub fn render_message_bubble(
_ => "",
};
let bar = render_progress_bar(ps.position, ps.duration, 20);
format!(
"{} {} {:.0}s/{:.0}s",
icon, bar, ps.position, ps.duration
)
format!("{} {} {:.0}s/{:.0}s", icon, bar, ps.position, ps.duration)
} else {
let waveform = render_waveform(&voice.waveform, 20);
format!(" {} {:.0}s", waveform, voice.duration)
@@ -456,10 +464,7 @@ pub fn render_message_bubble(
Span::styled(status_line, Style::default().fg(Color::Cyan)),
]));
} else {
lines.push(Line::from(Span::styled(
status_line,
Style::default().fg(Color::Cyan),
)));
lines.push(Line::from(Span::styled(status_line, Style::default().fg(Color::Cyan))));
}
}
}
@@ -477,10 +482,8 @@ pub fn render_message_bubble(
Span::styled(status, Style::default().fg(Color::Yellow)),
]));
} else {
lines.push(Line::from(Span::styled(
status,
Style::default().fg(Color::Yellow),
)));
lines
.push(Line::from(Span::styled(status, Style::default().fg(Color::Yellow))));
}
}
PhotoDownloadState::Error(e) => {
@@ -492,10 +495,7 @@ pub fn render_message_bubble(
Span::styled(status, Style::default().fg(Color::Red)),
]));
} else {
lines.push(Line::from(Span::styled(
status,
Style::default().fg(Color::Red),
)));
lines.push(Line::from(Span::styled(status, Style::default().fg(Color::Red))));
}
}
PhotoDownloadState::Downloaded(_) => {
@@ -540,7 +540,9 @@ pub fn render_album_bubble(
content_width: usize,
selected_msg_id: Option<MessageId>,
) -> (Vec<Line<'static>>, Vec<DeferredImageRender>) {
use crate::constants::{ALBUM_GRID_MAX_COLS, ALBUM_PHOTO_GAP, ALBUM_PHOTO_HEIGHT, ALBUM_PHOTO_WIDTH};
use crate::constants::{
ALBUM_GRID_MAX_COLS, ALBUM_PHOTO_GAP, ALBUM_PHOTO_HEIGHT, ALBUM_PHOTO_WIDTH,
};
let mut lines: Vec<Line<'static>> = Vec::new();
let mut deferred: Vec<DeferredImageRender> = Vec::new();
@@ -569,12 +571,12 @@ pub fn render_album_bubble(
// Добавляем маркер выбора на первую строку
if is_selected {
lines.push(Line::from(vec![
Span::styled(
selection_marker,
Style::default().fg(Color::Yellow).add_modifier(Modifier::BOLD),
),
]));
lines.push(Line::from(vec![Span::styled(
selection_marker,
Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD),
)]));
}
let grid_start_line = lines.len();
@@ -608,7 +610,9 @@ pub fn render_album_bubble(
let x_off = if is_outgoing {
let grid_width = cols as u16 * ALBUM_PHOTO_WIDTH
+ (cols as u16).saturating_sub(1) * ALBUM_PHOTO_GAP;
let padding = content_width.saturating_sub(grid_width as usize + 1) as u16;
let padding = content_width
.saturating_sub(grid_width as usize + 1)
as u16;
padding + col as u16 * (ALBUM_PHOTO_WIDTH + ALBUM_PHOTO_GAP)
} else {
col as u16 * (ALBUM_PHOTO_WIDTH + ALBUM_PHOTO_GAP)
@@ -617,7 +621,8 @@ pub fn render_album_bubble(
deferred.push(DeferredImageRender {
message_id: msg.id(),
photo_path: path.clone(),
line_offset: grid_start_line + row * ALBUM_PHOTO_HEIGHT as usize,
line_offset: grid_start_line
+ row * ALBUM_PHOTO_HEIGHT as usize,
x_offset: x_off,
width: ALBUM_PHOTO_WIDTH,
height: ALBUM_PHOTO_HEIGHT,
@@ -644,10 +649,7 @@ pub fn render_album_bubble(
}
PhotoDownloadState::NotDownloaded => {
if line_in_row == ALBUM_PHOTO_HEIGHT / 2 {
spans.push(Span::styled(
"📷",
Style::default().fg(Color::Gray),
));
spans.push(Span::styled("📷", Style::default().fg(Color::Gray)));
}
}
}
@@ -706,9 +708,10 @@ pub fn render_album_bubble(
Span::styled(time_text, Style::default().fg(Color::Gray)),
]));
} else {
lines.push(Line::from(vec![
Span::styled(format!(" {}", time_text), Style::default().fg(Color::Gray)),
]));
lines.push(Line::from(vec![Span::styled(
format!(" {}", time_text),
Style::default().fg(Color::Gray),
)]));
}
}