diff --git a/src/ui/app.rs b/src/ui/app.rs index 3d88ef2..7469422 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -1,8 +1,10 @@ use crate::api::{UptimeKumaClient, UptimeKumaEndpoints}; use crate::core; use crate::i18n::t; -use crate::ui::components::{render_header, render_monitor_list}; -use crate::ui::dashboard::model::DashboardViewState; +use crate::ui::{ + components::{render_header, render_monitor_list}, + dashboard::model::DashboardViewState, +}; use crossterm::{ event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind}, execute, diff --git a/src/ui/components/monitor_list.rs b/src/ui/components/monitor_list.rs index 6ffb52b..b70f1f7 100644 --- a/src/ui/components/monitor_list.rs +++ b/src/ui/components/monitor_list.rs @@ -1,17 +1,16 @@ use crate::i18n::t; -use crate::ui::dashboard::MonitorStatus; use crate::ui::dashboard::model::DashboardViewState; -use ratatui::style::Modifier; -use ratatui::widgets::{List, ListItem, ListState}; +use crate::ui::dashboard::{MonitorStatus, MonitorViewState}; use ratatui::{ Frame, - layout::Rect, - style::{Color, Style}, + layout::{Constraint, Direction, Layout, Rect}, + style::{Color, Modifier, Style}, text::{Line, Span}, - widgets::{Block, Borders}, + widgets::{Block, Borders, List, ListItem, ListState}, }; const STATUS_LINE_LENGTH: usize = 20; +const MAX_NAME_LENGTH: usize = 30; pub fn render_monitor_list( frame: &mut Frame, @@ -27,41 +26,7 @@ pub fn render_monitor_list( let items: Vec = state .monitors .iter() - .map(|monitor| { - let status_icon = get_status_emoji(&monitor.status); - let status_color = get_status_color(&monitor.status); - let status_line = create_status_line_spans(&monitor.status_history); - - let mut spans = vec![ - Span::styled( - format!("{} ", status_icon), - Style::default() - .fg(status_color) - .add_modifier(Modifier::BOLD), - ), - Span::styled( - &monitor.name, - Style::default() - .fg(Color::White) - .add_modifier(Modifier::BOLD), - ), - Span::styled( - format!(" | {}ms", monitor.response_time), - Style::default().fg(Color::Cyan), - ), - Span::styled( - format!(" | {}%", monitor.uptime_24h), - Style::default().fg(Color::Magenta), - ), - Span::raw(" | "), - ]; - - spans.extend(status_line); - - let line = Line::from(spans); - let lines = vec![line]; - ListItem::new(lines) - }) + .map(|monitor| create_monitor_item(monitor)) .collect(); let list = List::new(items) @@ -80,14 +45,6 @@ fn create_status_line_spans(status_history: &[MonitorStatus]) -> Vec &str { MonitorStatus::Unknown => "❓", } } + +fn create_monitor_item(monitor: &MonitorViewState) -> ListItem { + let status_icon = get_status_emoji(&monitor.status); + let status_color = get_status_color(&monitor.status); + let status_line = create_status_line_spans(&monitor.status_history); + + let item_layout = Layout::default() + .direction(Direction::Horizontal) + .constraints([ + Constraint::Length(3), + Constraint::Length(MAX_NAME_LENGTH as u16), + Constraint::Length(10), + Constraint::Length(10), + Constraint::Length(STATUS_LINE_LENGTH as u16), + ]) + .split(Rect { + x: 0, + y: 0, + width: 1000, + height: 1, + }); + + let status_span = Span::styled( + format!("{} ", status_icon), + Style::default() + .fg(status_color) + .add_modifier(Modifier::BOLD), + ); + + let mut name_text = monitor.name.clone(); + if name_text.len() > MAX_NAME_LENGTH { + name_text = format!("{}...", &name_text[..MAX_NAME_LENGTH - 3]); + } + + let name_span = Span::styled( + name_text, + Style::default() + .fg(Color::White) + .add_modifier(Modifier::BOLD), + ); + + let response_span = Span::styled( + format!("{:>7}ms", monitor.response_time), + Style::default().fg(Color::Cyan), + ); + + let uptime_span = Span::styled( + format!("{:>7}%", monitor.uptime_24h), + Style::default().fg(Color::Magenta), + ); + + let status_spans = create_status_line_spans(&monitor.status_history); + let status_line_start_period = Span::styled( + "(1h)", + Style::default() + .fg(Color::Gray) + .add_modifier(Modifier::ITALIC), + ); + let status_line_end_period = Span::styled( + t("now"), + Style::default() + .fg(Color::Gray) + .add_modifier(Modifier::ITALIC), + ); + let mut lines = Vec::new(); + let main_line = Line::from(vec![ + status_span, + name_span, + Span::raw(" | "), + response_span, + Span::raw(" | "), + uptime_span, + Span::raw(" | "), + status_line_start_period, + ]); + lines.push(main_line); + + let status_line = Line::from(status_spans); + lines.push(status_line); + ListItem::new(lines) +}