From 2b0366bb0c235c7106053f20f39f4b5732b39eb4 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Wed, 22 Jul 2026 22:15:59 -0500 Subject: [PATCH] feat: make text big and add key binds for toggle/reset --- src/main.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index b29f008..cd60acb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,10 +10,12 @@ use crossterm::{ event::{self, Event, KeyCode, KeyModifiers}, terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode}, }; + +use figlet_rs::Toilet; use ratatui::{ Terminal, backend::CrosstermBackend, - layout::Alignment, + layout::{Alignment, Constraint, Direction, Layout}, style::{Color, Style}, widgets::Paragraph, }; @@ -87,17 +89,27 @@ impl Termato { } } } + + fn reset(&mut self) { + self.is_running = false; + self.state = TimerState::Work; + self.prior_state = TimerState::Work; + self.duration_in_secs = self.work_mins * SECONDS_PER_MIN; + self.time_remaining_in_sec = self.duration_in_secs; + } } fn main() -> Result<(), io::Error> { enable_raw_mode()?; stdout().execute(EnterAlternateScreen)?; + let backend = CrosstermBackend::new(stdout()); let mut terminal = Terminal::new(backend)?; - + let font = Toilet::smblock().unwrap(); let mut termato = Termato::new(1, 1); let (tx, rx) = mpsc::channel(); + thread::spawn(move || { loop { thread::sleep(Duration::from_secs(1)); @@ -110,15 +122,39 @@ fn main() -> Result<(), io::Error> { loop { terminal.draw(|f| { let size = f.area(); + let minutes = termato.time_remaining_in_sec / SECONDS_PER_MIN; let seconds = termato.time_remaining_in_sec % SECONDS_PER_MIN; let time_str = format!("{:02}:{:02}", minutes, seconds); + + let time_color = match termato.state { + TimerState::Work => Color::Red, + TimerState::Break => Color::Green, + TimerState::Paused => Color::Yellow, + }; - let paragraph = Paragraph::new(time_str) - .style(Style::default().fg(Color::White)) + let big_time_text = if let Some(fig) = font.convert(&time_str) { + fig.to_string() + } else { + time_str + }; + + let text_height = big_time_text.lines().count() as u16; + + let vertical_layout = Layout::default() + .direction(Direction::Vertical) + .constraints([ + Constraint::Min(0), + Constraint::Length(text_height), + Constraint::Min(0), + ]) + .split(size); + + let timer_paragraph = Paragraph::new(big_time_text) + .style(Style::default().fg(time_color)) .alignment(Alignment::Center); - f.render_widget(paragraph, size); + f.render_widget(timer_paragraph, vertical_layout[1]); })?; if event::poll(Duration::from_millis(100))? @@ -129,6 +165,8 @@ fn main() -> Result<(), io::Error> { KeyCode::Char('q') | KeyCode::Char('Q') => break, KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => break, KeyCode::Char(' ') => termato.toggle_running(), + KeyCode::Char('s') | KeyCode::Char('S') => termato.toggle_mode(), + KeyCode::Char('r') | KeyCode::Char('R') => termato.reset(), _ => {} } } @@ -255,4 +293,22 @@ mod tests { assert_eq!(termato.prior_state, TimerState::Work); assert!(termato.is_running) } + + #[test] + fn termato_rest_when_called_it_should_reset_the_apps_state() { + let mut termato = Termato::new(1, 1); + termato.is_running = true; + termato.state = TimerState::Break; + termato.prior_state = TimerState::Break; + termato.duration_in_secs = 1; + termato.time_remaining_in_sec = 1; + + termato.reset(); + + assert!(!termato.is_running); + assert_eq!(termato.state, TimerState::Work); + assert_eq!(termato.prior_state, TimerState::Work); + assert_eq!(termato.duration_in_secs, 60); + assert_eq!(termato.time_remaining_in_sec, 60); + } }