Improve code quality

This commit is contained in:
2020-08-23 22:27:49 -05:00
parent 8a1f2d9081
commit 68ec6883b7
3 changed files with 100 additions and 95 deletions

View File

@@ -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 <musukarekai@gmail.com>")
.author("Rekai Musuka <rekai@musuka.dev>")
.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<PathBuf> {
let mut result: Option<PathBuf> = 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);
}

View File

@@ -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<Self> {
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)
}
}
}