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 e0d04d3797
4 changed files with 54 additions and 9 deletions

View File

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

View File

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

View File

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

View File

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