diff --git a/src/locales/en-US/main.ftl b/src/locales/en-US/main.ftl index 5de5334..f01d87d 100644 --- a/src/locales/en-US/main.ftl +++ b/src/locales/en-US/main.ftl @@ -25,3 +25,4 @@ uptime = Uptime history = History auto-update-enabled = Auto-update enabled ({interval} min) update-failed = Update failed: {error} +key-to-exit = Press 'q' to exit diff --git a/src/locales/pt-BR/main.ftl b/src/locales/pt-BR/main.ftl index 0ecaf91..df72828 100644 --- a/src/locales/pt-BR/main.ftl +++ b/src/locales/pt-BR/main.ftl @@ -25,3 +25,4 @@ now = Agora history = Historico auto-update-enabled = Auto-atualização ativada ({interval} min) update-failed = Falha na atualização: {error} +key-to-exit = Pressione 'q' para sair diff --git a/src/ui/app.rs b/src/ui/app.rs index 45bc2b1..18fa818 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -2,9 +2,8 @@ use crate::api::{UptimeKumaClient, UptimeKumaEndpoints}; use crate::core; use crate::data::{heartbeat::HeartbeatResponse, status_page::model::StatusPageResponse}; use crate::i18n::{t, t_with_args}; -use crate::ui::components::render_footer; use crate::ui::{ - components::{render_header, render_monitor_list}, + components::{render_footer, render_header, render_monitor_list}, dashboard::model::DashboardViewState, }; use anyhow::Result; @@ -23,10 +22,10 @@ use ratatui::{ }; use std::{ - io, - thread, - sync::mpsc, collections::HashMap, + io, + sync::mpsc, + thread, time::{Duration, Instant}, }; @@ -138,12 +137,21 @@ impl App { } else { render_monitor_list(frame, chunks[1], &self.state); } - render_footer(frame, chunks[2]); + + let seconds_until_update = self + .update_interval + .checked_sub(self.last_update.elapsed()) + .map(|d| d.as_secs() as u64) + .unwrap_or(30); + + render_footer(frame, chunks[2], seconds_until_update); }); } fn handle_events(&mut self) -> io::Result<()> { - if event::poll(Duration::from_millis(50))? { + let timeout = Duration::from_secs(1); + + if event::poll(timeout)? { if let Event::Key(key) = event::read()? { if key.kind == KeyEventKind::Release { return Ok(()); diff --git a/src/ui/components/footer.rs b/src/ui/components/footer.rs index cac4bfa..806002b 100644 --- a/src/ui/components/footer.rs +++ b/src/ui/components/footer.rs @@ -2,28 +2,43 @@ use ratatui::{ Frame, layout::{Alignment, Rect}, style::{Color, Modifier, Style}, - text::Span, + text::{Line, Span}, widgets::{Block, Borders, Paragraph}, }; +use crate::i18n::t; use chrono::Local; -pub fn render_footer(frame: &mut Frame, area: Rect) { +pub fn render_footer(frame: &mut Frame, area: Rect, seconds_until_update: u64) { let now = Local::now(); let datatime_str = now.format("%Y-%m-%d %H:%M:%S").to_string(); + let countdown_str = format!("↻ {}s", seconds_until_update); - let footer = Paragraph::new(Span::styled( - datatime_str, - Style::default() - .fg(Color::Gray) - .add_modifier(Modifier::BOLD), - )) - .block( - Block::default() - .borders(Borders::ALL) - .border_style(Style::default().fg(Color::Blue)), - ) - .alignment(Alignment::Center); + let text = Line::from(vec![ + Span::styled( + datatime_str, + Style::default() + .fg(Color::Gray) + .add_modifier(Modifier::BOLD), + ), + Span::raw(" | "), + Span::styled( + countdown_str, + Style::default() + .fg(Color::Yellow) + .add_modifier(Modifier::BOLD), + ), + Span::raw(" | "), + Span::styled(t("key-to-exit"), Style::default().fg(Color::Gray)), + ]); + + let footer = Paragraph::new(text) + .block( + Block::default() + .borders(Borders::ALL) + .border_style(Style::default().fg(Color::Blue)), + ) + .alignment(Alignment::Center); frame.render_widget(footer, area); } diff --git a/src/ui/components/header.rs b/src/ui/components/header.rs index c9b7b5b..057f324 100644 --- a/src/ui/components/header.rs +++ b/src/ui/components/header.rs @@ -3,7 +3,7 @@ use crate::ui::dashboard::model::DashboardViewState; use ratatui::{ Frame, layout::{Alignment, Rect}, - style::{Color, Style, Stylize}, + style::{Color, Style}, text::{Line, Span}, widgets::{Block, Borders, Paragraph}, };