Improve code quality
This commit is contained in:
		
							
								
								
									
										39
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								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 <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);
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										136
									
								
								src/pomodoro.rs
									
									
									
									
									
								
							
							
						
						
									
										136
									
								
								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<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)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user