diff --git a/src/app.rs b/src/app.rs index 478138e..a625b16 100644 --- a/src/app.rs +++ b/src/app.rs @@ -68,6 +68,23 @@ pub(crate) struct App { stopwatch: Option, } +/// Trait for widgets that can be paused +pub(crate) trait Pause { + fn is_paused(&self) -> bool; + + fn pause(&mut self); + + fn resume(&mut self); + + fn toggle_paused(&mut self) { + if self.is_paused() { + self.resume() + } else { + self.pause() + } + } +} + impl App { pub fn init_app(&mut self) { let style = Style::default().fg(self.color); @@ -127,31 +144,19 @@ impl App { pub fn on_key(&mut self, key: KeyCode) { if let Some(_w) = self.clock.as_mut() { } else if let Some(w) = self.timer.as_mut() { - match key { - KeyCode::Char(' ') => { - if w.is_paused() { - w.resume(); - } else { - w.pause(); - } - } - _ => {} - } + handle_key(w, key); } else if let Some(w) = self.stopwatch.as_mut() { - match key { - KeyCode::Char(' ') => { - if w.is_paused() { - w.resume(); - } else { - w.pause(); - } - } - _ => {} - } + handle_key(w, key); } } } +fn handle_key(widget: &mut T, key: KeyCode) { + if let KeyCode::Char(' ') = key { + widget.toggle_paused() + } +} + fn parse_duration(s: &str) -> Result { let reg = Regex::new(r"^(\d+)([smhdSMHD])$").unwrap(); let cap = reg diff --git a/src/app/modes/stopwatch.rs b/src/app/modes/stopwatch.rs index 0e38988..e3cc9e8 100644 --- a/src/app/modes/stopwatch.rs +++ b/src/app/modes/stopwatch.rs @@ -2,6 +2,8 @@ use chrono::{DateTime, Duration, Local}; use clock_tui::bricks_text::BricksText; use tui::{buffer::Buffer, layout::Rect, style::Style, widgets::Widget}; +use crate::app::Pause; + use super::{format_duration, render_centered, DurationFormat}; pub struct Stopwatch { @@ -21,24 +23,6 @@ impl Stopwatch { } } - pub(crate) fn is_paused(&self) -> bool { - self.started_at.is_none() - } - - pub(crate) fn pause(&mut self) { - if let Some(start_at) = self.started_at { - let now = Local::now(); - self.duration = self.duration + now.signed_duration_since(start_at); - self.started_at = None; - } - } - - pub(crate) fn resume(&mut self) { - if self.started_at.is_none() { - self.started_at = Some(Local::now()); - } - } - pub(crate) fn total_time(&self) -> Duration { if let Some(start_at) = self.started_at { let now = Local::now(); @@ -61,3 +45,23 @@ impl Widget for &Stopwatch { render_centered(area, buf, &text, None, footer); } } + +impl Pause for Stopwatch { + fn is_paused(&self) -> bool { + self.started_at.is_none() + } + + fn pause(&mut self) { + if let Some(start_at) = self.started_at { + let now = Local::now(); + self.duration = self.duration + now.signed_duration_since(start_at); + self.started_at = None; + } + } + + fn resume(&mut self) { + if self.started_at.is_none() { + self.started_at = Some(Local::now()); + } + } +} diff --git a/src/app/modes/timer.rs b/src/app/modes/timer.rs index c0fa727..b2a8f08 100644 --- a/src/app/modes/timer.rs +++ b/src/app/modes/timer.rs @@ -4,6 +4,8 @@ use chrono::{DateTime, Duration, Local}; use clock_tui::bricks_text::BricksText; use tui::{buffer::Buffer, layout::Rect, style::Style, widgets::Widget}; +use crate::app::Pause; + use super::{format_duration, render_centered, DurationFormat}; pub struct Timer { @@ -35,27 +37,6 @@ impl Timer { } } - pub(crate) fn is_paused(&self) -> bool { - self.ended_at.is_none() - } - - pub(crate) fn pause(&mut self) { - if let Some(end_at) = self.ended_at { - if end_at <= Local::now() { - self.duration = Duration::zero(); - } else { - self.duration = end_at - Local::now(); - self.ended_at = None; - } - } - } - - pub(crate) fn resume(&mut self) { - if self.ended_at.is_none() { - self.ended_at = Some(Local::now() + self.duration); - } - } - pub(crate) fn remaining_time(&self) -> Duration { if let Some(end_at) = self.ended_at { let now = Local::now(); @@ -112,3 +93,26 @@ impl Widget for &Timer { render_centered(area, buf, &text, None, footer); } } + +impl Pause for Timer { + fn is_paused(&self) -> bool { + self.ended_at.is_none() + } + + fn pause(&mut self) { + if let Some(end_at) = self.ended_at { + if end_at <= Local::now() { + self.duration = Duration::zero(); + } else { + self.duration = end_at - Local::now(); + self.ended_at = None; + } + } + } + + fn resume(&mut self) { + if self.ended_at.is_none() { + self.ended_at = Some(Local::now() + self.duration); + } + } +}