From 9fc9d2b758872782977fbb837accb31b9c3a5649 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Mon, 29 Jan 2024 08:26:41 -0500 Subject: [PATCH] Create Duration and Distance structures to handle rendering These structures handle parsing and rendering of a Duration and a Distance, allowing that knowledge to be centralized and reused. Then I'm using those structures in a variety of places in order to ensure that the information gets rendered consistently. --- fitnesstrax/app/src/components/day.rs | 9 ++++--- .../app/src/components/time_distance.rs | 27 +++++++++---------- fitnesstrax/app/src/view_models/day_detail.rs | 11 +++++--- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/fitnesstrax/app/src/components/day.rs b/fitnesstrax/app/src/components/day.rs index 575e733..bef67bf 100644 --- a/fitnesstrax/app/src/components/day.rs +++ b/fitnesstrax/app/src/components/day.rs @@ -20,7 +20,7 @@ use crate::{ components::{ steps_editor, time_distance_summary, weight_field, ActionGroup, Steps, WeightLabel, }, - types::WeightFormatter, + types::{DistanceFormatter, DurationFormatter, WeightFormatter}, view_models::DayDetailViewModel, }; use emseries::{Record, RecordId}; @@ -106,7 +106,10 @@ impl DaySummary { self.append(&row); let biking_summary = view_model.time_distance_summary(TimeDistanceActivity::BikeRide); - if let Some(label) = time_distance_summary(biking_summary.0, biking_summary.1) { + if let Some(label) = time_distance_summary( + DistanceFormatter::from(biking_summary.0), + DurationFormatter::from(biking_summary.1), + ) { self.append(&label); } } @@ -397,7 +400,7 @@ where biking_button.connect_clicked({ let view_model = view_model.clone(); move |_| { - let workout = view_model.new_time_distance(TimeDistanceActivity::Walking); + let workout = view_model.new_time_distance(TimeDistanceActivity::BikeRide); add_row(workout.map(TraxRecord::TimeDistance)); } }); diff --git a/fitnesstrax/app/src/components/time_distance.rs b/fitnesstrax/app/src/components/time_distance.rs index ee770fb..02bfe27 100644 --- a/fitnesstrax/app/src/components/time_distance.rs +++ b/fitnesstrax/app/src/components/time_distance.rs @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with Fit // use dimensioned::si; use crate::{ components::{distance_field, duration_field, time_field}, - types::{DistanceFormatter, DurationFormatter, TimeFormatter}, + types::{DistanceFormatter, DurationFormatter, FormatOption, TimeFormatter}, }; use dimensioned::si; use ft_core::{TimeDistance, TimeDistanceActivity}; @@ -28,20 +28,17 @@ use gtk::{prelude::*, subclass::prelude::*}; use std::{cell::RefCell, rc::Rc}; pub fn time_distance_summary( - distance: si::Meter, - duration: si::Second, + distance: DistanceFormatter, + duration: DurationFormatter, ) -> Option { - let text = match (distance > si::M, duration > si::S) { + let text = match (*distance > si::M, *duration > si::S) { (true, true) => Some(format!( - "{} kilometers of biking in {} minutes", - distance.value_unsafe / 1000., - duration.value_unsafe / 60. + "{} of biking in {}", + distance.format(FormatOption::Full), + duration.format(FormatOption::Full) )), - (true, false) => Some(format!( - "{} kilometers of biking", - distance.value_unsafe / 1000. - )), - (false, true) => Some(format!("{} seconds of biking", duration.value_unsafe / 60.)), + (true, false) => Some(format!("{} of biking", distance.format(FormatOption::Full))), + (false, true) => Some(format!("{} of biking", duration.format(FormatOption::Full))), (false, false) => None, }; @@ -75,7 +72,7 @@ pub fn time_distance_detail(record: ft_core::TimeDistance) -> gtk::Box { .label( record .distance - .map(|dist| format!("{}", dist)) + .map(|dist| DistanceFormatter::from(dist).format(FormatOption::Abbreviated)) .unwrap_or("".to_owned()), ) .build(), @@ -87,7 +84,9 @@ pub fn time_distance_detail(record: ft_core::TimeDistance) -> gtk::Box { .label( record .duration - .map(|duration| format!("{}", duration)) + .map(|duration| { + DurationFormatter::from(duration).format(FormatOption::Abbreviated) + }) .unwrap_or("".to_owned()), ) .build(), diff --git a/fitnesstrax/app/src/view_models/day_detail.rs b/fitnesstrax/app/src/view_models/day_detail.rs index 730be85..7e17388 100644 --- a/fitnesstrax/app/src/view_models/day_detail.rs +++ b/fitnesstrax/app/src/view_models/day_detail.rs @@ -14,10 +14,7 @@ General Public License for more details. You should have received a copy of the GNU General Public License along with FitnessTrax. If not, see . */ -#[allow(unused_imports)] -use crate::app::{ReadError, RecordProvider, WriteError}; -#[allow(unused_imports)] -use chrono::NaiveDate; +use crate::app::{ReadError, RecordProvider}; use dimensioned::si; use emseries::{Record, RecordId, Recordable}; use ft_core::{TimeDistance, TimeDistanceActivity, TraxRecord}; @@ -27,6 +24,12 @@ use std::{ sync::{Arc, RwLock}, }; +// These are actually a used imports. Clippy isn't detecting their use, probably because of complexity around the async trait macros. +#[allow(unused_imports)] +use crate::app::WriteError; +#[allow(unused_imports)] +use chrono::NaiveDate; + #[derive(Clone, Debug)] enum RecordState { Original(Record),