feat: make text big and add key binds for toggle/reset

This commit is contained in:
Stevan Freeborn
2026-07-22 22:15:59 -05:00
parent 011639d0d1
commit 2b0366bb0c
+61 -5
View File
@@ -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);
}
}