diff --git a/Cargo.lock b/Cargo.lock index 5623edf..2b4788d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,9 +56,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "base64" @@ -123,9 +123,9 @@ checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" [[package]] name = "cc" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518" +checksum = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381" [[package]] name = "cexpr" @@ -452,9 +452,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.74" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10" +checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" [[package]] name = "libdbus-sys" @@ -821,7 +821,7 @@ checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48" dependencies = [ "proc-macro2", "quote 1.0.7", - "syn 1.0.38", + "syn 1.0.39", ] [[package]] @@ -921,9 +921,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.38" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4" +checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9" dependencies = [ "proc-macro2", "quote 1.0.7", @@ -965,7 +965,7 @@ checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" dependencies = [ "proc-macro2", "quote 1.0.7", - "syn 1.0.38", + "syn 1.0.39", ] [[package]] diff --git a/src/main.rs b/src/main.rs index 347aab9..40b1922 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ use crossterm::{ event::{poll, read, Event, KeyCode, KeyEvent, KeyModifiers}, terminal::{disable_raw_mode, enable_raw_mode}, }; -use domasi::pomodoro::{Alert, Clock, Status}; +use domasi::pomodoro::{Alert, Remaining, Status}; use domasi::{Config, Pomodoro}; use std::fs; use std::io::{self, Write}; @@ -12,9 +12,9 @@ use std::path::{Path, PathBuf}; use std::thread; fn main() { - let matches = App::new("Domasi") + let matches = App::new("domasi") .version("0.1.0") - .author("paoda ") + .author("Rekai Musuka ") .about("Yet another pomodoro timer.") .arg( Arg::with_name("create-config") @@ -91,7 +91,10 @@ pub fn start(args: &ArgMatches) { thread::spawn(move || loop { if let Ok(status) = rx.recv() { loop { - let (remain, text) = Clock::get_formatted_string(status); + let (text, remain) = match Remaining::from_status(status) { + Some(seconds) => (seconds.to_string(), seconds.remaining_secs()), + None => ("??? Status: ??:??".to_string(), 0), + }; let out = io::stdout(); let mut handle = out.lock(); @@ -103,7 +106,7 @@ pub fn start(args: &ArgMatches) { break; } - thread::sleep(Clock::get_polling_interval()); + thread::sleep(Remaining::polling_interval()); } } }); @@ -153,38 +156,28 @@ pub fn start(args: &ArgMatches) { } fn get_audio_file(items: std::fs::ReadDir) -> Option { - let mut result: Option = None; - for maybe_entry in items { - match maybe_entry { - Ok(entry) => match entry.path().extension() { - Some(ext) => match ext.to_str() { - Some("mp3") | Some("wav") | Some("ogg") | Some("flac") => { - result = Some(entry.path()); - break; - } - _ => continue, - }, - None => continue, - }, - Err(_err) => continue, + if let Ok(entry) = maybe_entry { + if let Some(ext) = entry.path().extension() { + if let Some("mp3") | Some("wav") | Some("ogg") | Some("flac") = ext.to_str() { + return Some(entry.path()); + } + } } } - result + None } fn setup_user_input() -> crossterm::Result<()> { enable_raw_mode()?; - get_user_input()?; - disable_raw_mode() } fn get_user_input() -> crossterm::Result<()> { loop { - if poll(Clock::get_polling_interval())? { + if poll(Remaining::polling_interval())? { if let Event::Key(event) = read()? { handle_key_event(event); } diff --git a/src/pomodoro.rs b/src/pomodoro.rs index 301f412..50bd5ef 100644 --- a/src/pomodoro.rs +++ b/src/pomodoro.rs @@ -1,6 +1,7 @@ use super::Config; use crossbeam::channel::Sender; use rodio::{Decoder, Device, Source}; +use std::fmt::{Display, Formatter, Result as FmtResult}; use std::fs::File; use std::io::BufReader; use std::path::Path; @@ -32,6 +33,7 @@ impl<'a> Alert<'a> { self } } + #[derive(Copy, Clone, Debug)] pub enum State { Work, @@ -75,7 +77,7 @@ impl<'a> Pomodoro { alert.play(); } - Self::notify(&self.state); + let _ = Self::notify(&self.state); match self.state { State::Work => { @@ -138,32 +140,24 @@ impl Pomodoro { tx.send(status).unwrap(); } - fn notify(state: &State) { + fn notify(state: &State) -> Result<(), anyhow::Error> { let mut toast = notify_rust::Notification::new(); - match state { - State::Work => { - toast - .summary("Time to Work!") - .body("Remember to stay focused!") - .show() - .unwrap(); - } - State::ShortBreak | State::LongBreak => { - toast - .summary("Break Time!") - .body("Enjoy your well deserved rest!") - .show() - .unwrap(); - } - State::Inactive => { - toast - .summary("Pomodoro Cycle Complete.") - .body("Now waiting for user input....") - .show() - .unwrap(); - } - } + State::Work => toast + .summary("Time to Work!") + .body("Remember to stay focused!") + .show()?, + State::ShortBreak | State::LongBreak => toast + .summary("Break Time!") + .body("Enjoy your well deserved rest!") + .show()?, + State::Inactive => toast + .summary("Pomodoro Cycle Complete.") + .body("Now waiting for user input....") + .show()?, + }; + + Ok(()) } } @@ -174,54 +168,72 @@ pub struct Status { pub state: State, } -pub struct Clock; +pub struct Remaining { + state: State, + remaining: u64, + seconds: u64, + hours: u64, + minutes: u64, +} -impl Clock { - pub fn get_formatted_string(status: Status) -> (u64, String) { +impl Remaining { + pub fn from_status(status: Status) -> Option { let now = Instant::now(); - let elapsed = now.checked_duration_since(status.start); + let maybe_elapsed = now.checked_duration_since(status.start); - match elapsed { + match maybe_elapsed { Some(duration) => { let remaining = status.length.as_secs() - duration.as_secs(); - let seconds = remaining; - let hours = seconds / 3600; - let minutes = (seconds - (hours * 3600)) / 60; - let seconds = seconds - (hours * 3600) - (minutes * 60); + let hours = remaining / 3600; + let minutes = (remaining - (hours * 3600)) / 60; + let seconds = remaining - (hours * 3600) - (minutes * 60); - let mut clock = "\r".to_string(); - - clock.push_str(&format!("{}", status.state)); - - if hours > 0 { - // We don't want o bother with the hours part if there is none - if hours < 10 { - clock.push_str(&format!("0{}:", hours)); - } else { - clock.push_str(&format!("{}:", hours)); - } - } - - if minutes < 10 { - clock.push_str(&format!("0{}:", minutes)); - } else { - clock.push_str(&format!("{}:", minutes)); - } - - if seconds < 10 { - clock.push_str(&format!("0{}", seconds)); - } else { - clock.push_str(&format!("{}", seconds)); - } - - (remaining, clock) + Some(Self { + state: status.state, + remaining, + hours, + minutes, + seconds, + }) } - None => (0, "??:??:??".to_string()), // This will break the loop + None => None, } } - pub fn get_polling_interval() -> Duration { + pub fn remaining_secs(&self) -> u64 { + self.remaining + } + + pub fn polling_interval() -> Duration { Duration::from_millis(500) } } + +impl Display for Remaining { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + f.write_str("\r")?; + write!(f, "{}", self.state)?; + + if self.hours > 0 { + // No need to print the hours if there are none. + if self.hours < 10 { + write!(f, "0{}:", self.hours)?; + } else { + write!(f, "{}:", self.hours)?; + } + } + + if self.minutes < 10 { + write!(f, "0{}:", self.minutes)?; + } else { + write!(f, "{}:", self.minutes)?; + } + + if self.seconds < 10 { + write!(f, "0{}", self.seconds) + } else { + write!(f, "{}", self.seconds) + } + } +}