chore: add pause functionality
This commit is contained in:
		@@ -20,8 +20,8 @@ fn main() {
 | 
			
		||||
    let mut domasi: Pomodoro = Default::default();
 | 
			
		||||
 | 
			
		||||
    match get_alert() {
 | 
			
		||||
        Some(alert) => domasi.start_with_alert(alert),
 | 
			
		||||
        None => domasi.start(),
 | 
			
		||||
        Some(alert) => domasi.start(Some(alert)).unwrap(),
 | 
			
		||||
        None => domasi.start(None).unwrap(),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,9 @@
 | 
			
		||||
use super::Alert;
 | 
			
		||||
use crossterm::event::{self, Event, KeyCode, KeyModifiers};
 | 
			
		||||
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
 | 
			
		||||
use std::error::Error;
 | 
			
		||||
use std::fmt::{Display, Formatter, Result as FmtResult};
 | 
			
		||||
use std::io::{self, Write};
 | 
			
		||||
use std::thread;
 | 
			
		||||
use std::time::{Duration, Instant};
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Copy, Clone, Default)]
 | 
			
		||||
@@ -18,34 +19,49 @@ static WORK_TIME: u64 = 1500; // Default: 1500 (25min)
 | 
			
		||||
static SHORT_BREAK_TIME: u64 = 300; // Default: 300 (5min)
 | 
			
		||||
static LONG_BREAK_TIME: u64 = 600; // Default: 600 (10min)
 | 
			
		||||
 | 
			
		||||
static POLLING_RATE: Duration = Duration::from_millis(300);
 | 
			
		||||
static POLLING_RATE: Duration = Duration::from_millis(100);
 | 
			
		||||
impl Pomodoro {
 | 
			
		||||
    pub fn new() -> Self {
 | 
			
		||||
        Self::default()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn start_with_alert(&mut self, alert: Alert) {
 | 
			
		||||
    pub fn start(&mut self, maybe_alert: Option<Alert>) -> crossterm::Result<()> {
 | 
			
		||||
        enable_raw_mode()?;
 | 
			
		||||
 | 
			
		||||
        loop {
 | 
			
		||||
            if let Status::Complete = self.poll(Some(&alert)) {
 | 
			
		||||
            if let Status::Complete = self.poll(maybe_alert.as_ref()) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Self::sleep();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
            if event::poll(POLLING_RATE)? {
 | 
			
		||||
                if let Event::Key(key_event) = event::read()? {
 | 
			
		||||
                    match key_event.code {
 | 
			
		||||
                        KeyCode::Char('p') | KeyCode::Char('P') => {
 | 
			
		||||
                            self.paused.toggle();
 | 
			
		||||
 | 
			
		||||
    pub fn start(&mut self) {
 | 
			
		||||
        loop {
 | 
			
		||||
            if let Status::Complete = self.poll(None) {
 | 
			
		||||
                break;
 | 
			
		||||
                            if !self.paused.value {
 | 
			
		||||
                                // Apply the elapsed time
 | 
			
		||||
                                let duration = self.paused.duration;
 | 
			
		||||
                                match self.wait_start {
 | 
			
		||||
                                    Some(instant) => self.wait_start = Some(instant + duration),
 | 
			
		||||
                                    None => {
 | 
			
		||||
                                        unreachable!("Unable to resume from a non-existent timer.")
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
 | 
			
		||||
                                self.paused = Default::default();
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        KeyCode::Char('q') | KeyCode::Char('Q') => break,
 | 
			
		||||
                        KeyCode::Char('c') if key_event.modifiers == KeyModifiers::CONTROL => break,
 | 
			
		||||
                        _ => {}
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Self::sleep()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn sleep() {
 | 
			
		||||
        thread::sleep(POLLING_RATE);
 | 
			
		||||
        disable_raw_mode()?;
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn notify_complete(&self) -> Result<(), Box<dyn Error>> {
 | 
			
		||||
@@ -116,6 +132,7 @@ impl Pomodoro {
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                self.paused.previous = Some(now);
 | 
			
		||||
                self.display_paused();
 | 
			
		||||
            }
 | 
			
		||||
            Status::Active => self.display_time(),
 | 
			
		||||
            Status::NextState => {
 | 
			
		||||
@@ -140,7 +157,6 @@ impl Pomodoro {
 | 
			
		||||
            }
 | 
			
		||||
            Status::Complete => {
 | 
			
		||||
                println!("\rPomodoro cycle complete!");
 | 
			
		||||
 | 
			
		||||
                let _ = self.notify_complete();
 | 
			
		||||
            }
 | 
			
		||||
            Status::Inactive => {}
 | 
			
		||||
@@ -150,10 +166,18 @@ impl Pomodoro {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn display_time(&self) {
 | 
			
		||||
        if let Some(earlier) = self.wait_start {
 | 
			
		||||
            let wait = Instant::now() - earlier;
 | 
			
		||||
            let left: Clock = (Self::wait_times(self.state) - wait).into();
 | 
			
		||||
            let _ = Self::print(&format!("\r{} {}", self.state, left));
 | 
			
		||||
        if let Some(start) = self.wait_start {
 | 
			
		||||
            let remainder: Clock = (Self::wait_times(self.state) - (Instant::now() - start)).into();
 | 
			
		||||
            let _ = Self::print(&format!("\r{} {}", self.state, remainder));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn display_paused(&self) {
 | 
			
		||||
        if let Some(start) = self.wait_start {
 | 
			
		||||
            let stop_time: Clock = (Self::wait_times(self.state)
 | 
			
		||||
                - ((Instant::now() - self.paused.duration) - start))
 | 
			
		||||
                .into();
 | 
			
		||||
            let _ = Self::print(&format!("\r[PAUSED] {} {}", self.state, stop_time));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -163,7 +187,10 @@ impl Pomodoro {
 | 
			
		||||
 | 
			
		||||
        // Empty String so that we can clear line before writing
 | 
			
		||||
        // from the most-left side of the terminal again.
 | 
			
		||||
        handle.write_all(b"\r                      ")?;
 | 
			
		||||
        //
 | 
			
		||||
        // We write 24 spaces so that the entire line is always
 | 
			
		||||
        // written over
 | 
			
		||||
        handle.write_all(b"\r                        ")?;
 | 
			
		||||
        handle.write_all(text.as_bytes())?;
 | 
			
		||||
        handle.flush()?;
 | 
			
		||||
        Ok(())
 | 
			
		||||
@@ -274,6 +301,12 @@ struct PausedState {
 | 
			
		||||
    previous: Option<Instant>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl PausedState {
 | 
			
		||||
    pub fn toggle(&mut self) {
 | 
			
		||||
        self.value = !self.value;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Copy, Clone)]
 | 
			
		||||
enum Count {
 | 
			
		||||
    Increase,
 | 
			
		||||
@@ -306,10 +339,10 @@ impl Default for State {
 | 
			
		||||
impl Display for State {
 | 
			
		||||
    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
 | 
			
		||||
        match *self {
 | 
			
		||||
            State::Work => f.write_str("Working: "),
 | 
			
		||||
            State::ShortBreak => f.write_str("Resting: "),
 | 
			
		||||
            State::LongBreak => f.write_str("REALLY Resting: "),
 | 
			
		||||
            State::Inactive => f.write_str("Inactive: "),
 | 
			
		||||
            State::Work => f.write_str("Working:"),
 | 
			
		||||
            State::ShortBreak => f.write_str("Resting:"),
 | 
			
		||||
            State::LongBreak => f.write_str("REALLY Resting:"),
 | 
			
		||||
            State::Inactive => f.write_str("Inactive:"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user