added auto update & changed config path

This commit is contained in:
Uber Veng
2026-05-21 22:59:02 +07:00
parent 1599cfcafa
commit f2349c9f15
7 changed files with 435 additions and 7 deletions

113
src/ui.rs
View File

@@ -1,6 +1,6 @@
use crate::ansi;
use crate::executor;
use crate::app::{App, MessageLevel, Popup};
use crate::app::{App, MessageLevel, Popup, UpdatingStatus};
use ratatui::{
layout::{Alignment, Constraint, Direction, Layout, Rect},
style::{Color, Modifier, Style},
@@ -69,7 +69,12 @@ fn render_description(f: &mut Frame, app: &App, area: Rect) {
fn render_popup(f: &mut Frame, popup: &mut Popup) {
let area = f.area();
let popup_area = centered_rect(80, 90, area);
// Use a smaller area for update-related popups
let popup_area = match popup {
Popup::UpdateConfirm { .. } | Popup::Updating { .. } => centered_rect(50, 40, area),
_ => centered_rect(80, 90, area),
};
f.render_widget(Clear, popup_area);
@@ -235,6 +240,110 @@ fn render_popup(f: &mut Frame, popup: &mut Popup) {
f.render_widget(paragraph, popup_area);
}
Popup::UpdateConfirm { info } => {
let mut lines = vec![
Line::from(""),
Line::from(Span::raw(format!(
" {}{}",
info.current_version, info.new_version
))),
];
if info.size > 0 {
let mb = info.size as f64 / 1_048_576.0;
lines.push(Line::from(Span::raw(format!(" Размер: {:.1} МБ", mb))));
}
lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
" [Y] Обновить [N / Esc] Пропустить",
Style::default().fg(Color::Yellow),
)));
let block = Block::default()
.borders(Borders::ALL)
.title(" Доступно обновление ")
.border_style(Style::default().fg(Color::Cyan));
let paragraph = Paragraph::new(lines)
.block(block)
.wrap(Wrap { trim: true });
f.render_widget(paragraph, popup_area);
}
Popup::Updating {
info,
downloaded,
status,
} => {
let (title, border_color) = match status {
UpdatingStatus::Downloading => (" Загрузка обновления… ", Color::Cyan),
UpdatingStatus::Applying => (" Применение обновления… ", Color::Yellow),
UpdatingStatus::Done => (" Обновление завершено ", Color::Green),
UpdatingStatus::Failed(_) => (" Ошибка обновления ", Color::Red),
};
let bar_width = popup_area.width.saturating_sub(4) as usize;
let progress_line = if info.size > 0 {
let percent = ((*downloaded as f64 / info.size as f64) * 100.0)
.min(100.0) as usize;
let filled = (percent * bar_width) / 100;
format!(
"[{}{}] {}%",
"".repeat(filled),
"".repeat(bar_width.saturating_sub(filled)),
percent
)
} else {
// Indeterminate: animate based on downloaded bytes
let pos = ((*downloaded / 4096) as usize) % bar_width.max(1);
let thumb = 4.min(bar_width);
let mut bar = vec!['░'; bar_width];
for i in pos..((pos + thumb).min(bar_width)) {
bar[i] = '█';
}
format!("[{}]", bar.iter().collect::<String>())
};
let status_text = match status {
UpdatingStatus::Downloading => {
if info.size > 0 {
let mb_done = *downloaded as f64 / 1_048_576.0;
let mb_total = info.size as f64 / 1_048_576.0;
format!(" {:.1} / {:.1} МБ", mb_done, mb_total)
} else {
let kb = *downloaded / 1024;
format!(" {} КБ загружено", kb)
}
}
UpdatingStatus::Applying => " Применяется…".to_string(),
UpdatingStatus::Done => " Обновление успешно установлено. Перезапуск…".to_string(),
UpdatingStatus::Failed(msg) => format!(" Ошибка: {}", msg),
};
let mut lines = vec![
Line::from(""),
Line::from(Span::raw(progress_line)),
Line::from(""),
Line::from(Span::raw(status_text)),
];
if matches!(status, UpdatingStatus::Failed(_)) {
lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
" [Esc] Закрыть",
Style::default().fg(Color::Yellow),
)));
}
let block = Block::default()
.borders(Borders::ALL)
.title(title)
.border_style(Style::default().fg(border_color));
let paragraph = Paragraph::new(lines)
.block(block)
.wrap(Wrap { trim: true });
f.render_widget(paragraph, popup_area);
}
_ => {}
}
}