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