refactor(data): add UiData struct and remove the hacky fix that broke

This commit is contained in:
Christoph J. Scherr 2024-07-10 12:39:25 +02:00 committed by PlexSheep
parent c1d57e32c1
commit 468c48d327
1 changed files with 61 additions and 13 deletions

View File

@ -65,6 +65,52 @@ pub struct Clock {
last_reset: Option<DateTime<Local>>, last_reset: Option<DateTime<Local>>,
} }
#[derive(Debug, Clone, PartialEq, Default)]
pub(crate) struct UiData {
fdate: [String; 2],
ftime: [String; 2],
timebar_ratio: [Option<f64>; 2],
data_idx: usize,
}
impl UiData {
pub fn update(&mut self, fdate: String, ftime: String, timebar_ratio: Option<f64>) {
self.data_idx ^= 1;
self.fdate[self.data_idx] = fdate;
self.ftime[self.data_idx] = ftime;
self.timebar_ratio[self.data_idx] = timebar_ratio;
}
/// did the data change with the last update?
#[must_use]
#[inline]
pub fn changed(&self) -> bool {
!(self.fdate[0] == self.fdate[1]
&& self.ftime[0] == self.fdate[1]
&& self.timebar_ratio[0] == self.timebar_ratio[1])
}
#[must_use]
#[inline]
pub(crate) fn fdate(&self) -> &str {
&self.fdate[self.data_idx]
}
#[must_use]
#[inline]
pub(crate) fn ftime(&self) -> &str {
&self.ftime[self.data_idx]
}
#[must_use]
#[inline]
#[allow(clippy::missing_const_for_fn)] // no it's not const
pub(crate) fn timebar_ratio(&self) -> Option<f64> {
self.timebar_ratio[self.data_idx]
}
}
impl Clock { impl Clock {
#[must_use] #[must_use]
#[allow(clippy::missing_const_for_fn)] #[allow(clippy::missing_const_for_fn)]
@ -168,6 +214,7 @@ impl Clock {
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let tick_rate = Duration::from_millis(100); let tick_rate = Duration::from_millis(100);
let mut last_tick = Instant::now(); let mut last_tick = Instant::now();
let mut uidata: UiData = UiData::default();
self.setup()?; self.setup()?;
loop { loop {
let raw_time = chrono::Local::now().round_subsecs(0); let raw_time = chrono::Local::now().round_subsecs(0);
@ -177,10 +224,11 @@ impl Clock {
.split_whitespace() .split_whitespace()
.map(str::to_string) .map(str::to_string)
.collect(); .collect();
let fdate: String = splits[0].clone();
let ftime: String = splits[1].clone(); uidata.update(splits[0].clone(), splits[1].clone(), self.timebar_ratio());
let timebar_ratio = self.timebar_ratio(); if uidata.changed() {
self.ui(terminal, ftime, fdate, timebar_ratio)?; self.ui(terminal, &uidata)?;
}
let timeout = tick_rate.saturating_sub(last_tick.elapsed()); let timeout = tick_rate.saturating_sub(last_tick.elapsed());
if poll(timeout)? { if poll(timeout)? {
if let Event::Key(key) = event::read()? { if let Event::Key(key) = event::read()? {
@ -205,9 +253,7 @@ impl Clock {
fn ui( fn ui(
&self, &self,
terminal: &mut Terminal<CrosstermBackend<Stdout>>, terminal: &mut Terminal<CrosstermBackend<Stdout>>,
ftime: String, data: &UiData,
fdate: String,
timebar_ratio: Option<f64>,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
terminal.draw(|frame| { terminal.draw(|frame| {
let root = frame.size(); let root = frame.size();
@ -226,11 +272,11 @@ impl Clock {
let parts = Self::partition(a); let parts = Self::partition(a);
let clockw = tui_big_text::BigText::builder() let clockw = tui_big_text::BigText::builder()
.style(Style::new().red()) .style(Style::new().red())
.lines(vec![ftime.into()]) .lines(vec![data.ftime().into()])
.alignment(Alignment::Center) .alignment(Alignment::Center)
.build() .build()
.expect("could not render time widget"); .expect("could not render time widget");
let datew = Paragraph::new(fdate) let datew = Paragraph::new(data.fdate())
.blue() .blue()
.alignment(Alignment::Left) .alignment(Alignment::Left)
.block(Block::new().padding(Padding::new( .block(Block::new().padding(Padding::new(
@ -251,19 +297,21 @@ impl Clock {
0, 0,
0, 0,
))) )))
.ratio(timebar_ratio.unwrap()); .ratio(data.timebar_ratio().unwrap());
debug!("time bar ration: {}", self.timebar_ratio().unwrap()); debug!("time bar ration: {}", self.timebar_ratio().unwrap());
Some(tmp) Some(tmp)
} else { } else {
None None
}; };
debug!("rendering the configured widgets"); debug!("rendering the configured widgets");
#[cfg(debug_assertions)]
let prerender = Instant::now();
frame.render_widget(clockw, parts[0]); frame.render_widget(clockw, parts[0]);
sleep(500); // HACK: through black magic, this works around the problem that the time bar is trace!("{:?} after render clockw", prerender.elapsed());
// not rendered at the same time as the clock, and yes, it needs to be
// 500ms for some reason, and yes it makes starting the app slower
frame.render_widget(&timebarw, parts[2]); frame.render_widget(&timebarw, parts[2]);
trace!("{:?} after render timebarw", prerender.elapsed());
frame.render_widget(datew, parts[1]); frame.render_widget(datew, parts[1]);
trace!("{:?} to render all widgets", prerender.elapsed());
debug!("done rendering"); debug!("done rendering");
})?; })?;
Ok(()) Ok(())