Refactoring

This commit is contained in:
Marco De Araujo 2026-01-21 12:34:50 -04:00
parent d8b4843415
commit 17662107b0
2 changed files with 28 additions and 60 deletions

View file

@ -1,9 +1,11 @@
use std::time::Duration;
use anyhow::Result; use anyhow::Result;
use reqwest::blocking::Client; use reqwest::blocking::Client;
use crate::{ use crate::{
api::endpoints::UptimeKumaEndpoints, api::endpoints::UptimeKumaEndpoints,
data::{self, heartbeat::HeartbeatResponse, status_page::model::StatusPageResponse}, data::{self, heartbeat::HeartbeatResponse, status_page::model::StatusPageResponse}, i18n::t,
}; };
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -13,8 +15,9 @@ pub struct UptimeKumaClient {
impl UptimeKumaClient { impl UptimeKumaClient {
pub fn new() -> Self { pub fn new() -> Self {
let client = Client::builder().connect_timeout(Duration::from_secs(10)).timeout(Duration::from_secs(30)).build().unwrap_or_else(|_| panic!("{}", t("http-build-error")));
Self { Self {
client: Client::new(), client,
} }
} }

View file

@ -1,12 +1,10 @@
use crate::api::{UptimeKumaClient, UptimeKumaEndpoints}; use crate::api::{UptimeKumaClient, UptimeKumaEndpoints};
use crate::core; use crate::core;
use crate::data::{heartbeat::HeartbeatResponse, status_page::model::StatusPageResponse};
use crate::i18n::{t, t_with_args}; use crate::i18n::{t, t_with_args};
use crate::ui::{ use crate::ui::{
components::{render_footer, render_header, render_monitor_list}, components::{render_footer, render_header, render_monitor_list},
dashboard::model::DashboardViewState, dashboard::model::DashboardViewState,
}; };
use anyhow::Result;
use crossterm::{ use crossterm::{
event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind}, event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind},
execute, execute,
@ -24,8 +22,6 @@ use ratatui::{
use std::{ use std::{
collections::HashMap, collections::HashMap,
io, io,
sync::mpsc,
thread,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
@ -33,11 +29,6 @@ const INITIAL_INTERVAL: u32 = 300;
const MAIN_LAYOUT_WITH_SCROLLBAR: [Constraint; 2] = [Constraint::Min(1), Constraint::Length(1)]; const MAIN_LAYOUT_WITH_SCROLLBAR: [Constraint; 2] = [Constraint::Min(1), Constraint::Length(1)];
const MAIN_LAYOUT_WITHOUT_SCROLLBAR: [Constraint; 1] = [Constraint::Min(1)]; const MAIN_LAYOUT_WITHOUT_SCROLLBAR: [Constraint; 1] = [Constraint::Min(1)];
enum FetchResult {
Heartbeat(Result<HeartbeatResponse>),
StatusPage(Result<StatusPageResponse>),
}
pub struct App { pub struct App {
state: DashboardViewState, state: DashboardViewState,
terminal: Terminal<CrosstermBackend<io::Stdout>>, terminal: Terminal<CrosstermBackend<io::Stdout>>,
@ -49,6 +40,26 @@ pub struct App {
} }
impl App { impl App {
pub fn new(endpoints: UptimeKumaEndpoints) -> io::Result<Self> {
let backend = CrosstermBackend::new(io::stdout());
let mut terminal = Terminal::new(backend)?;
terminal.hide_cursor()?;
let state = DashboardViewState::new();
let initial_interval = Duration::from_secs(INITIAL_INTERVAL as u64);
Ok(Self {
state,
terminal,
should_quit: false,
last_update: Instant::now(),
update_interval: initial_interval,
endpoints,
client: UptimeKumaClient::new(),
})
}
fn setup_terminal(&mut self) -> io::Result<()> { fn setup_terminal(&mut self) -> io::Result<()> {
enable_raw_mode()?; enable_raw_mode()?;
execute!(io::stdout(), EnterAlternateScreen, EnableMouseCapture)?; execute!(io::stdout(), EnterAlternateScreen, EnableMouseCapture)?;
@ -248,57 +259,11 @@ impl App {
Ok(()) Ok(())
} }
pub fn new(endpoints: UptimeKumaEndpoints) -> io::Result<Self> {
let backend = CrosstermBackend::new(io::stdout());
let mut terminal = Terminal::new(backend)?;
terminal.hide_cursor()?;
let state = DashboardViewState::new();
let initial_interval = Duration::from_secs(INITIAL_INTERVAL as u64);
Ok(Self {
state,
terminal,
should_quit: false,
last_update: Instant::now(),
update_interval: initial_interval,
endpoints,
client: UptimeKumaClient::new(),
})
}
fn fetch_and_update_data(&mut self) -> anyhow::Result<()> { fn fetch_and_update_data(&mut self) -> anyhow::Result<()> {
let (tx, rx) = mpsc::channel(); let heartbeat_result = self.client.fetch_heartbeat(&self.endpoints)?;
let status_page_result = self.client.fetch_status_page(&self.endpoints)?;
let heartbeat_client = self.client.clone(); let unified_data = core::unify_data(&status_page_result, &heartbeat_result);
let heartbeat_endpoints = self.endpoints.clone();
let tx_clone = tx.clone();
thread::spawn(move || {
let result = heartbeat_client.fetch_heartbeat(&heartbeat_endpoints);
tx.send(FetchResult::Heartbeat(result)).unwrap();
});
let status_page_client = self.client.clone();
let status_page_endpoints = self.endpoints.clone();
thread::spawn(move || {
let result = status_page_client.fetch_status_page(&status_page_endpoints);
tx_clone.send(FetchResult::StatusPage(result)).unwrap();
});
let mut heartbeat_result = None;
let mut status_page_result = None;
for _ in 0..2 {
match rx.recv()? {
FetchResult::Heartbeat(result) => heartbeat_result = Some(result?),
FetchResult::StatusPage(result) => status_page_result = Some(result?),
}
}
let heartbeat_data = heartbeat_result.unwrap();
let status_page_data = status_page_result.unwrap();
let unified_data = core::unify_data(&status_page_data, &heartbeat_data);
self.state = DashboardViewState::from_unified_data(unified_data); self.state = DashboardViewState::from_unified_data(unified_data);
Ok(()) Ok(())
} }