feat(timebar)!: add timer and add additional information to the ui #22
cargo devel CI / cargo CI (push) Has been cancelled Details

This commit is contained in:
Christoph J. Scherr 2024-09-03 19:12:25 +02:00
parent 12efcf45a8
commit 1b07e481f2
4 changed files with 54 additions and 9 deletions

View File

@ -6,7 +6,7 @@
#![allow(clippy::cast_possible_wrap)] #![allow(clippy::cast_possible_wrap)]
#![allow(clippy::cast_sign_loss)] // it should only be positive anyway #![allow(clippy::cast_sign_loss)] // it should only be positive anyway
use chrono::{DateTime, Local, SubsecRound, Timelike}; use chrono::{Date, DateTime, Local, SubsecRound, Timelike};
use clap::Parser; use clap::Parser;
use libpt::cli::args::HELP_TEMPLATE; use libpt::cli::args::HELP_TEMPLATE;
use libpt::cli::clap::ArgGroup; use libpt::cli::clap::ArgGroup;
@ -30,7 +30,7 @@ use ui::Data;
/// Make your terminal into a big clock /// Make your terminal into a big clock
#[derive(Parser, Debug, Clone)] #[derive(Parser, Debug, Clone)]
#[command(help_template = HELP_TEMPLATE, author, version)] #[command(help_template = HELP_TEMPLATE, author, version)]
#[clap(group( ArgGroup::new("timebarlen") .args(&["minute","day", "hour", "custom", "countdown"]),))] #[clap(group( ArgGroup::new("timebarlen") .args(&["minute","day", "hour", "custom", "countdown", "timer"]),))]
#[allow(clippy::struct_excessive_bools)] // the struct is for cli parsing and we already use an #[allow(clippy::struct_excessive_bools)] // the struct is for cli parsing and we already use an
// ArgGroup // ArgGroup
pub struct Clock { pub struct Clock {
@ -70,6 +70,8 @@ pub struct Clock {
pub(crate) last_reset: Option<DateTime<Local>>, pub(crate) last_reset: Option<DateTime<Local>>,
#[clap(skip)] #[clap(skip)]
pub(crate) did_notify: bool, pub(crate) did_notify: bool,
#[clap(skip)]
pub(crate) started_at: DateTime<Local>,
} }
impl Clock { impl Clock {
@ -82,6 +84,8 @@ impl Clock {
Some(TimeBarLength::Day) Some(TimeBarLength::Day)
} else if self.hour { } else if self.hour {
Some(TimeBarLength::Hour) Some(TimeBarLength::Hour)
} else if self.timer {
Some(TimeBarLength::Timer)
} else if self.countdown.is_some() { } else if self.countdown.is_some() {
Some(TimeBarLength::Countup( Some(TimeBarLength::Countup(
self.countdown.unwrap().as_secs() as i64 self.countdown.unwrap().as_secs() as i64
@ -111,7 +115,7 @@ impl Clock {
if let Some(len) = self.timebar_len() { if let Some(len) = self.timebar_len() {
let since_last_reset = Local::now().signed_duration_since(self.last_reset.unwrap()); let since_last_reset = Local::now().signed_duration_since(self.last_reset.unwrap());
match len { match len {
TimeBarLength::Countup(_) => { TimeBarLength::Countup(_) | TimeBarLength::Timer => {
// the count up should not reset. If the time is over, just keep it at 100% // the count up should not reset. If the time is over, just keep it at 100%
} }
TimeBarLength::Custom(_) => { TimeBarLength::Custom(_) => {
@ -147,7 +151,7 @@ impl Clock {
if let Some(len) = self.timebar_len() { if let Some(len) = self.timebar_len() {
trace!("Local Time: {}", Local::now()); trace!("Local Time: {}", Local::now());
match len { match len {
TimeBarLength::Custom(_) | TimeBarLength::Countup(_) => { TimeBarLength::Custom(_) | TimeBarLength::Countup(_) | TimeBarLength::Timer => {
self.last_reset = Some(Local::now()); self.last_reset = Some(Local::now());
} }
TimeBarLength::Minute => { TimeBarLength::Minute => {
@ -204,7 +208,7 @@ impl Clock {
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let tick_rate = std::time::Duration::from_millis(100); let tick_rate = std::time::Duration::from_millis(100);
let mut last_tick = Instant::now(); let mut last_tick = Instant::now();
let mut uidata: Data = Data::default(); let mut uidata: Data = Data::new(self.timebar_len().unwrap());
self.setup()?; self.setup()?;
loop { loop {
let raw_time = chrono::Local::now().round_subsecs(0); let raw_time = chrono::Local::now().round_subsecs(0);

View File

@ -4,6 +4,7 @@ use chrono::Duration;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TimeBarLength { pub enum TimeBarLength {
Timer,
Minute, Minute,
Hour, Hour,
Custom(i64), Custom(i64),
@ -19,6 +20,7 @@ impl TimeBarLength {
Self::Minute => 60, Self::Minute => 60,
Self::Day => 24 * 60 * 60, Self::Day => 24 * 60 * 60,
Self::Hour => 60 * 60, Self::Hour => 60 * 60,
Self::Timer => 1,
Self::Custom(secs) | Self::Countup(secs) => secs, Self::Custom(secs) | Self::Countup(secs) => secs,
} }
} }
@ -38,6 +40,9 @@ impl Default for TimeBarLength {
impl Display for TimeBarLength { impl Display for TimeBarLength {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if *self == Self::Timer {
return write!(f, "");
}
let buf = match self { let buf = match self {
Self::Minute => humantime::Duration::from( Self::Minute => humantime::Duration::from(
Duration::minutes(1) Duration::minutes(1)
@ -59,6 +64,7 @@ impl Display for TimeBarLength {
.to_std() .to_std()
.expect("could not convert chrono time to std time"), .expect("could not convert chrono time to std time"),
), ),
Self::Timer => unreachable!(),
}; };
write!(f, "{buf}") write!(f, "{buf}")
} }

View File

@ -8,18 +8,37 @@ use crate::clock::timebar::TimeBarLength;
use super::Clock; use super::Clock;
pub const TIME_FORMAT: &str = "%H:%M:%S";
// TODO: make this a ringbuffer with a custom struct inside? // TODO: make this a ringbuffer with a custom struct inside?
#[derive(Debug, Clone, PartialEq, Default)] #[derive(Debug, Clone, PartialEq)]
pub struct Data { pub struct Data {
now: [DateTime<Local>; 2], now: [DateTime<Local>; 2],
fdate: [String; 2], fdate: [String; 2],
ftime: [String; 2], ftime: [String; 2],
timebar_ratio: [Option<f64>; 2], timebar_ratio: [Option<f64>; 2],
timebar_type: TimeBarLength,
started_at: DateTime<Local>,
idx: usize, idx: usize,
} }
impl Data { impl Data {
pub fn new(timebar_type: TimeBarLength) -> Self {
let mut this = Self {
now: [Default::default(); 2],
fdate: ["".to_string(), "".to_string()],
ftime: ["".to_string(), "".to_string()],
timebar_ratio: [Default::default(); 2],
started_at: Local::now(),
idx: Default::default(),
timebar_type,
};
this.started_at = this.started_at.round_subsecs(0);
this
}
pub fn update( pub fn update(
&mut self, &mut self,
now: DateTime<Local>, now: DateTime<Local>,
@ -71,6 +90,9 @@ impl Data {
#[inline] #[inline]
#[allow(clippy::missing_const_for_fn)] // no it's not const #[allow(clippy::missing_const_for_fn)] // no it's not const
pub fn timebar_ratio(&self) -> Option<f64> { pub fn timebar_ratio(&self) -> Option<f64> {
if self.timebar_type == TimeBarLength::Timer {
return Some(0.0);
}
self.timebar_ratio[self.idx] self.timebar_ratio[self.idx]
} }
} }
@ -171,8 +193,21 @@ pub fn timebarw_label<'a>(
// example with `-o` #17 // example with `-o` #17
.checked_add_signed(len.into()) .checked_add_signed(len.into())
.expect("could not calculate when the countdown finishes") .expect("could not calculate when the countdown finishes")
.format("%H:%M:%S"); .format(TIME_FORMAT);
Paragraph::new(format!("{time_now} / {len} ({until})"))
let text: String = match clock.timebar_len().unwrap() {
TimeBarLength::Timer => format!("{} + {time_now}", data.started_at.format(TIME_FORMAT)),
TimeBarLength::Countup(_) | TimeBarLength::Custom(_) => format!(
"{time_now} / {len} | {} -> {until}",
last_reset.format(TIME_FORMAT)
),
_ => format!(
"{time_now} / {len} | {} -> {until}",
last_reset.with_second(0).unwrap().format(TIME_FORMAT)
),
};
Paragraph::new(text)
.alignment(Alignment::Center) .alignment(Alignment::Center)
.block( .block(
Block::default().padding(Padding::right(if inner_rect.width > 80 { Block::default().padding(Padding::right(if inner_rect.width > 80 {

View File

@ -90,7 +90,7 @@ fn mock_tests() {
info!("0s=0.0"); info!("0s=0.0");
} }
{ {
let mut data = Data::default(); let mut data = Data::new(clock::timebar::TimeBarLength::Day);
let now = Local::now(); let now = Local::now();
data.update(now, "date".to_owned(), "time".to_owned(), Some(0.1)); data.update(now, "date".to_owned(), "time".to_owned(), Some(0.1));
assert_eq!(data.timebar_ratio(), Some(0.1)); assert_eq!(data.timebar_ratio(), Some(0.1));