From 96317f569233a73e57e04558d301bfb4a32c5508 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Thu, 1 Feb 2024 10:08:18 -0500 Subject: [PATCH] Finish removing the previous record grouping Now that the DayDetailViewModel knows to retrieve its own records, the grouping functions, and passing groups of records around, no longer make sens. --- fitnesstrax/app/src/app_window.rs | 12 +- fitnesstrax/app/src/views/historical_view.rs | 172 +++---------------- 2 files changed, 25 insertions(+), 159 deletions(-) diff --git a/fitnesstrax/app/src/app_window.rs b/fitnesstrax/app/src/app_window.rs index c473062..a747262 100644 --- a/fitnesstrax/app/src/app_window.rs +++ b/fitnesstrax/app/src/app_window.rs @@ -16,6 +16,7 @@ You should have received a copy of the GNU General Public License along with Fit use crate::{ app::App, + types::DayInterval, view_models::DayDetailViewModel, views::{DayDetailView, HistoricalView, PlaceholderView, View, WelcomeView}, }; @@ -133,10 +134,10 @@ impl AppWindow { self.swap_main(view); } - fn show_historical_view(&self, records: Vec>) { - let view = View::Historical(HistoricalView::new(self.app.clone(), records, { + fn show_historical_view(&self, interval: DayInterval) { + let view = View::Historical(HistoricalView::new(self.app.clone(), interval, { let s = self.clone(); - Rc::new(move |date, _records| { + Rc::new(move |date| { let s = s.clone(); glib::spawn_future_local(async move { let layout = gtk::Box::new(gtk::Orientation::Vertical, 0); @@ -160,10 +161,7 @@ impl AppWindow { async move { let end = Local::now().date_naive(); let start = end - Duration::days(7); - match s.app.records(start, end).await { - Ok(records) => s.show_historical_view(records), - Err(_) => s.show_welcome_view(), - } + s.show_historical_view(DayInterval { start, end }); } }); } diff --git a/fitnesstrax/app/src/views/historical_view.rs b/fitnesstrax/app/src/views/historical_view.rs index 537481e..315ac00 100644 --- a/fitnesstrax/app/src/views/historical_view.rs +++ b/fitnesstrax/app/src/views/historical_view.rs @@ -62,11 +62,11 @@ impl ObjectSubclass for HistoricalViewPrivate { let app = app.clone(); let list_item = list_item.clone(); glib::spawn_future_local(async move { - let records = list_item + let date = list_item .downcast_ref::() .expect("should be a ListItem") .item() - .and_downcast::() + .and_downcast::() .expect("should be a DaySummary"); let summary = list_item @@ -77,7 +77,7 @@ impl ObjectSubclass for HistoricalViewPrivate { .expect("should be a DaySummary"); if let Some(app) = app.borrow().clone() { - let view_model = DayDetailViewModel::new(records.date(), app.clone()).await; + let view_model = DayDetailViewModel::new(date.date(), app.clone()).await; summary.set_data(view_model); } }); @@ -97,13 +97,9 @@ glib::wrapper! { } impl HistoricalView { - pub fn new( - app: App, - records: Vec>, - on_select_day: Rc, - ) -> Self + pub fn new(app: App, interval: DayInterval, on_select_day: Rc) -> Self where - SelectFn: Fn(chrono::NaiveDate, Vec>) + 'static, + SelectFn: Fn(chrono::NaiveDate) + 'static, { let s: Self = Object::builder().build(); s.set_orientation(gtk::Orientation::Vertical); @@ -111,11 +107,8 @@ impl HistoricalView { *s.imp().app.borrow_mut() = Some(app); - let grouped_records = - GroupedRecords::new((*s.imp().time_window.borrow()).clone()).with_data(records); - - let mut model = gio::ListStore::new::(); - model.extend(grouped_records.items()); + let mut model = gio::ListStore::new::(); + model.extend(interval.days().map(Date::new)); s.imp() .list_view .set_model(Some(>k::NoSelection::new(Some(model)))); @@ -127,8 +120,8 @@ impl HistoricalView { // actually want to do here is to open a modal dialog that shows all of the details of // the day and which allows the user to edit items within that dialog. let item = s.model().unwrap().item(idx).unwrap(); - let records = item.downcast_ref::().unwrap(); - on_select_day(records.date(), records.records()); + let date = item.downcast_ref::().unwrap(); + on_select_day(date.date()); } }); @@ -137,12 +130,9 @@ impl HistoricalView { s } - pub fn set_records(&self, records: Vec>) { - println!("set_records: {:?}", records); - let grouped_records = - GroupedRecords::new((self.imp().time_window.borrow()).clone()).with_data(records); - let mut model = gio::ListStore::new::(); - model.extend(grouped_records.items()); + pub fn set_intervals(&self, interval: DayInterval) { + let mut model = gio::ListStore::new::(); + model.extend(interval.days().map(Date::new)); self.imp() .list_view .set_model(Some(>k::NoSelection::new(Some(model)))); @@ -154,152 +144,30 @@ impl HistoricalView { } #[derive(Default)] -pub struct DayRecordsPrivate { +pub struct DatePrivate { date: RefCell, - records: RefCell>>, } #[glib::object_subclass] -impl ObjectSubclass for DayRecordsPrivate { - const NAME: &'static str = "DayRecords"; - type Type = DayRecords; +impl ObjectSubclass for DatePrivate { + const NAME: &'static str = "Date"; + type Type = Date; } -impl ObjectImpl for DayRecordsPrivate {} +impl ObjectImpl for DatePrivate {} glib::wrapper! { - pub struct DayRecords(ObjectSubclass); + pub struct Date(ObjectSubclass); } -impl DayRecords { - pub fn new(date: chrono::NaiveDate, records: Vec>) -> Self { +impl Date { + pub fn new(date: chrono::NaiveDate) -> Self { let s: Self = Object::builder().build(); - *s.imp().date.borrow_mut() = date; - *s.imp().records.borrow_mut() = records; - s } pub fn date(&self) -> chrono::NaiveDate { *self.imp().date.borrow() } - - pub fn records(&self) -> Vec> { - self.imp().records.borrow().clone() - } - - pub fn add_record(&self, record: Record) { - self.imp().records.borrow_mut().push(record); - } -} - -// This isn't feeling quite right. DayRecords is a glib object, but I'm not sure that I want to -// really be passing that around. It seems not generic enough. I feel like this whole grouped -// records thing can be made more generic. -struct GroupedRecords { - interval: DayInterval, - data: HashMap, -} - -impl GroupedRecords { - fn new(interval: DayInterval) -> Self { - let mut s = Self { - interval: interval.clone(), - data: HashMap::new(), - }; - interval.days().for_each(|date| { - let _ = s.data.insert(date, DayRecords::new(date, vec![])); - }); - s - } - - fn with_data(mut self, records: Vec>) -> Self { - records.into_iter().for_each(|record| { - self.data - .entry(record.date()) - .and_modify(|entry: &mut DayRecords| (*entry).add_record(record.clone())) - .or_insert(DayRecords::new(record.date(), vec![record])); - }); - - self - } - - fn items(&self) -> impl Iterator + '_ { - self.interval.days().map(|date| { - self.data - .get(&date) - .cloned() - .unwrap_or(DayRecords::new(date, vec![])) - }) - } -} - -#[cfg(test)] -mod test { - use super::GroupedRecords; - use crate::types::DayInterval; - use chrono::{FixedOffset, NaiveDate, TimeZone}; - use dimensioned::si::{KG, M, S}; - use emseries::{Record, RecordId}; - use ft_core::{Steps, TimeDistance, TraxRecord, Weight}; - - #[test] - fn groups_records() { - let records = vec![ - Record { - id: RecordId::default(), - data: TraxRecord::Steps(Steps { - date: NaiveDate::from_ymd_opt(2023, 10, 13).unwrap(), - count: 1500, - }), - }, - Record { - id: RecordId::default(), - data: TraxRecord::Weight(Weight { - date: NaiveDate::from_ymd_opt(2023, 10, 13).unwrap(), - weight: 85. * KG, - }), - }, - Record { - id: RecordId::default(), - data: TraxRecord::Weight(Weight { - date: NaiveDate::from_ymd_opt(2023, 10, 14).unwrap(), - weight: 86. * KG, - }), - }, - Record { - id: RecordId::default(), - data: TraxRecord::BikeRide(TimeDistance { - datetime: FixedOffset::west_opt(10 * 60 * 60) - .unwrap() - .with_ymd_and_hms(2019, 6, 15, 12, 0, 0) - .unwrap(), - distance: Some(1000. * M), - duration: Some(150. * S), - comments: Some("Test Comments".to_owned()), - }), - }, - Record { - id: RecordId::default(), - data: TraxRecord::BikeRide(TimeDistance { - datetime: FixedOffset::west_opt(10 * 60 * 60) - .unwrap() - .with_ymd_and_hms(2019, 6, 15, 23, 0, 0) - .unwrap(), - distance: Some(1000. * M), - duration: Some(150. * S), - comments: Some("Test Comments".to_owned()), - }), - }, - ]; - - let groups = GroupedRecords::new(DayInterval { - start: NaiveDate::from_ymd_opt(2023, 10, 14).unwrap(), - end: NaiveDate::from_ymd_opt(2023, 10, 14).unwrap(), - }) - .with_data(records) - .data; - assert_eq!(groups.len(), 3); - } }