diff --git a/emseries/src/series.rs b/emseries/src/series.rs index ee964e7..310b3f7 100644 --- a/emseries/src/series.rs +++ b/emseries/src/series.rs @@ -108,7 +108,7 @@ where Ok(line_) => { match serde_json::from_str::>(line_.as_ref()) .map_err(EmseriesReadError::JSONParseError) - .and_then(|record| Record::try_from(record)) + .and_then(Record::try_from) { Ok(record) => records.insert(record.id.clone(), record.clone()), Err(EmseriesReadError::RecordDeleted(id)) => records.remove(&id), diff --git a/emseries/src/types.rs b/emseries/src/types.rs index 018a99b..3d4eb2e 100644 --- a/emseries/src/types.rs +++ b/emseries/src/types.rs @@ -11,9 +11,6 @@ You should have received a copy of the GNU General Public License along with Lum */ use chrono::{DateTime, FixedOffset, NaiveDate}; -use chrono_tz::UTC; -use serde::de::DeserializeOwned; -use serde::ser::Serialize; use std::{cmp::Ordering, fmt, io, str}; use thiserror::Error; use uuid::Uuid; @@ -93,33 +90,9 @@ impl str::FromStr for Timestamp { } } -/* -impl PartialEq for Timestamp { - fn eq(&self, other: &Timestamp) -> bool { - match (self, other) { - (Timestamp::DateTime(dt1), Timestamp::DateTime(dt2)) => { - dt1.with_timezone(&UTC) == dt2.with_timezone(&UTC) - } - // It's not clear to me what would make sense when I'm comparing a date and a - // timestamp. I'm going with a naive date comparison on the idea that what I'm wanting - // here is human scale, again. - (Timestamp::DateTime(dt1), Timestamp::Date(dt2)) => dt1.date_naive() == *dt2, - (Timestamp::Date(dt1), Timestamp::DateTime(dt2)) => *dt1 == dt2.date_naive(), - (Timestamp::Date(dt1), Timestamp::Date(dt2)) => *dt1 == *dt2, - } - } -} -*/ - impl PartialOrd for Timestamp { fn partial_cmp(&self, other: &Timestamp) -> Option { - // Some(self.cmp(other)) - match (self, other) { - (Timestamp::DateTime(dt1), Timestamp::DateTime(dt2)) => dt1.partial_cmp(dt2), - (Timestamp::DateTime(dt1), Timestamp::Date(dt2)) => dt1.date_naive().partial_cmp(dt2), - (Timestamp::Date(dt1), Timestamp::DateTime(dt2)) => dt1.partial_cmp(&dt2.date_naive()), - (Timestamp::Date(dt1), Timestamp::Date(dt2)) => dt1.partial_cmp(dt2), - } + Some(self.cmp(other)) } } diff --git a/fitnesstrax/app/src/app.rs b/fitnesstrax/app/src/app.rs index 94a6e00..8dfb882 100644 --- a/fitnesstrax/app/src/app.rs +++ b/fitnesstrax/app/src/app.rs @@ -14,7 +14,6 @@ General Public License for more details. You should have received a copy of the GNU General Public License along with FitnessTrax. If not, see . */ -use crate::types::DayInterval; use chrono::NaiveDate; use emseries::{time_range, Record, RecordId, Series, Timestamp}; use ft_core::TraxRecord; @@ -52,12 +51,10 @@ impl App { .unwrap(), ); - let s = Self { + Self { runtime, database: Arc::new(RwLock::new(database)), - }; - - s + } } pub async fn records( @@ -76,7 +73,7 @@ impl App { Timestamp::Date(end), true, )) - .map(|record| record.clone()) + .cloned() .collect::>>(); Ok(records) } else { diff --git a/fitnesstrax/app/src/app_window.rs b/fitnesstrax/app/src/app_window.rs index 9b230ea..f5f2d46 100644 --- a/fitnesstrax/app/src/app_window.rs +++ b/fitnesstrax/app/src/app_window.rs @@ -81,7 +81,7 @@ impl AppWindow { .orientation(gtk::Orientation::Vertical) .build(); - let initial_view = View::Placeholder(PlaceholderView::new().upcast()); + let initial_view = View::Placeholder(PlaceholderView::default().upcast()); layout.append(&initial_view.widget()); @@ -115,9 +115,10 @@ impl AppWindow { s.navigation.connect_popped({ let s = s.clone(); - move |_, _| match *s.current_view.borrow() { - View::Historical(_) => s.load_records(), - _ => {} + move |_, _| { + if let View::Historical(_) = *s.current_view.borrow() { + s.load_records(); + } } }); @@ -191,22 +192,4 @@ impl AppWindow { } }); } - - fn on_put_record(&self, record: TraxRecord) { - glib::spawn_future_local({ - let s = self.clone(); - async move { - s.app.put_record(record).await; - } - }); - } - - fn on_update_record(&self, record: Record) { - glib::spawn_future_local({ - let s = self.clone(); - async move { - s.app.update_record(record).await; - } - }); - } } diff --git a/fitnesstrax/app/src/components/action_group.rs b/fitnesstrax/app/src/components/action_group.rs index 4197edd..914adb6 100644 --- a/fitnesstrax/app/src/components/action_group.rs +++ b/fitnesstrax/app/src/components/action_group.rs @@ -14,6 +14,8 @@ General Public License for more details. You should have received a copy of the GNU General Public License along with FitnessTrax. If not, see . */ +//! ActionGroup and related structures + use glib::Object; use gtk::{prelude::*, subclass::prelude::*}; diff --git a/fitnesstrax/app/src/components/day.rs b/fitnesstrax/app/src/components/day.rs index f0fe13a..631600e 100644 --- a/fitnesstrax/app/src/components/day.rs +++ b/fitnesstrax/app/src/components/day.rs @@ -23,7 +23,7 @@ use crate::{ use emseries::Record; use glib::Object; use gtk::{prelude::*, subclass::prelude::*}; -use std::{cell::RefCell, rc::Rc}; +use std::cell::RefCell; use super::weight::WeightEdit; @@ -60,8 +60,8 @@ glib::wrapper! { pub struct DaySummary(ObjectSubclass) @extends gtk::Box, gtk::Widget, @implements gtk::Orientable; } -impl DaySummary { - pub fn new() -> Self { +impl Default for DaySummary { + fn default() -> Self { let s: Self = Object::builder().build(); s.set_orientation(gtk::Orientation::Vertical); s.set_css_classes(&["day-summary"]); @@ -70,6 +70,12 @@ impl DaySummary { s } +} + +impl DaySummary { + pub fn new() -> Self { + Self::default() + } pub fn set_data(&self, date: chrono::NaiveDate, records: Vec>) { self.imp() @@ -83,11 +89,11 @@ impl DaySummary { if let Some(Record { data: ft_core::TraxRecord::Weight(weight_record), .. - }) = records.iter().filter(|f| f.data.is_weight()).next() + }) = records.iter().find(|f| f.data.is_weight()) { let label = gtk::Label::builder() .halign(gtk::Align::Start) - .label(&format!("{}", weight_record.weight)) + .label(weight_record.weight.to_string()) .css_classes(["day-summary__weight"]) .build(); self.append(&label); @@ -134,7 +140,7 @@ impl DayDetail { s.append( &ActionGroup::builder() - .primary_action("Edit", Box::new(move || on_edit())) + .primary_action("Edit", Box::new(on_edit)) .build(), ); diff --git a/fitnesstrax/app/src/components/edit_view.rs b/fitnesstrax/app/src/components/edit_view.rs deleted file mode 100644 index f6f96a9..0000000 --- a/fitnesstrax/app/src/components/edit_view.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* -Copyright 2023, Savanni D'Gerinel - -This file is part of FitnessTrax. - -FitnessTrax is free software: you can redistribute it and/or modify it under the terms of the GNU -General Public License as published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. - -FitnessTrax is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License along with FitnessTrax. If not, see . -*/ - -#[derive(Clone)] -pub enum EditView { - Unconfigured, - View(View), - Edit(Edit), -} diff --git a/fitnesstrax/app/src/components/mod.rs b/fitnesstrax/app/src/components/mod.rs index 75ecdd2..78e9b9b 100644 --- a/fitnesstrax/app/src/components/mod.rs +++ b/fitnesstrax/app/src/components/mod.rs @@ -20,9 +20,6 @@ pub use action_group::ActionGroup; mod day; pub use day::{DayDetail, DayEdit, DaySummary}; -mod edit_view; -pub use edit_view::EditView; - mod singleton; pub use singleton::{Singleton, SingletonImpl}; diff --git a/fitnesstrax/app/src/components/text_entry.rs b/fitnesstrax/app/src/components/text_entry.rs index 20a8cb2..12c0a6c 100644 --- a/fitnesstrax/app/src/components/text_entry.rs +++ b/fitnesstrax/app/src/components/text_entry.rs @@ -20,12 +20,16 @@ use std::{cell::RefCell, rc::Rc}; #[derive(Clone, Debug)] pub struct ParseError; +type Renderer = dyn Fn(&T) -> String; +type Parser = dyn Fn(&str) -> Result; + #[derive(Clone)] pub struct TextEntry { value: Rc>>, widget: gtk::Entry, - renderer: Rc String>>, - parser: Rc Result>>, + #[allow(unused)] + renderer: Rc>, + parser: Rc>, } impl std::fmt::Debug for TextEntry { @@ -46,16 +50,15 @@ impl TextEntry { V: Fn(&str) -> Result + 'static, { let widget = gtk::Entry::builder().placeholder_text(placeholder).build(); - match value { - Some(ref v) => widget.set_text(&renderer(&v)), - None => {} + if let Some(ref v) = value { + widget.set_text(&renderer(v)) } let s = Self { value: Rc::new(RefCell::new(value)), widget, - renderer: Rc::new(Box::new(renderer)), - parser: Rc::new(Box::new(parser)), + renderer: Rc::new(renderer), + parser: Rc::new(parser), }; s.widget.buffer().connect_text_notify({ @@ -84,19 +87,20 @@ impl TextEntry { } } + #[allow(unused)] pub fn value(&self) -> Option { let v = self.value.borrow().clone(); self.value.borrow().clone() } pub fn set_value(&self, value: Option) { - match value { - Some(ref v) => self.widget.set_text(&(self.renderer)(&v)), - None => {} + if let Some(ref v) = value { + self.widget.set_text(&(self.renderer)(v)) } *self.value.borrow_mut() = value; } + #[allow(unused)] pub fn grab_focus(&self) { self.widget.grab_focus(); } diff --git a/fitnesstrax/app/src/components/time_distance.rs b/fitnesstrax/app/src/components/time_distance.rs index 8a20c42..ac1ad9c 100644 --- a/fitnesstrax/app/src/components/time_distance.rs +++ b/fitnesstrax/app/src/components/time_distance.rs @@ -24,6 +24,7 @@ use std::cell::RefCell; #[derive(Default)] pub struct TimeDistanceViewPrivate { + #[allow(unused)] record: RefCell>, } @@ -53,7 +54,7 @@ impl TimeDistanceView { first_row.append( >k::Label::builder() .halign(gtk::Align::Start) - .label(&record.datetime.format("%H:%M").to_string()) + .label(record.datetime.format("%H:%M").to_string()) .build(), ); @@ -96,7 +97,7 @@ impl TimeDistanceView { .label( record .comments - .map(|comments| format!("{}", comments)) + .map(|comments| comments.to_string()) .unwrap_or("".to_owned()), ) .build(), diff --git a/fitnesstrax/app/src/components/weight.rs b/fitnesstrax/app/src/components/weight.rs index 48bbf7f..220b51e 100644 --- a/fitnesstrax/app/src/components/weight.rs +++ b/fitnesstrax/app/src/components/weight.rs @@ -14,12 +14,9 @@ General Public License for more details. You should have received a copy of the GNU General Public License along with FitnessTrax. If not, see . */ -use crate::components::{EditView, ParseError, Singleton, TextEntry}; -use chrono::{Local, NaiveDate}; +use crate::components::{ParseError, TextEntry}; use dimensioned::si; -use glib::{object::ObjectRef, Object}; -use gtk::{prelude::*, subclass::prelude::*}; -use std::{borrow::Borrow, cell::RefCell}; +use gtk::prelude::*; #[derive(Default)] pub struct WeightViewPrivate {} @@ -77,6 +74,7 @@ impl WeightEdit { } } + #[allow(unused)] pub fn set_value(&self, value: Option>) { self.entry.set_value(value); } diff --git a/fitnesstrax/app/src/types.rs b/fitnesstrax/app/src/types.rs index 319e845..799f2d8 100644 --- a/fitnesstrax/app/src/types.rs +++ b/fitnesstrax/app/src/types.rs @@ -21,8 +21,8 @@ impl Default for DayInterval { impl DayInterval { pub fn days(&self) -> impl Iterator { DayIterator { - current: self.start.clone(), - end: self.end.clone(), + current: self.start, + end: self.end, } } } @@ -37,7 +37,7 @@ impl Iterator for DayIterator { fn next(&mut self) -> Option { if self.current <= self.end { - let val = self.current.clone(); + let val = self.current; self.current += Duration::days(1); Some(val) } else { diff --git a/fitnesstrax/app/src/view_models/day_detail.rs b/fitnesstrax/app/src/view_models/day_detail.rs index 5e0ecbd..f823d6f 100644 --- a/fitnesstrax/app/src/view_models/day_detail.rs +++ b/fitnesstrax/app/src/view_models/day_detail.rs @@ -29,10 +29,12 @@ enum RecordState { Original(Record), New(T), Updated(Record), + #[allow(unused)] Deleted(Record), } impl RecordState { + #[allow(unused)] fn id(&self) -> Option<&RecordId> { match self { RecordState::Original(ref r) => Some(&r.id), @@ -51,6 +53,7 @@ impl RecordState { } } + #[allow(unused)] fn with_delete(self) -> Option> { match self { RecordState::Original(r) => Some(RecordState::Deleted(r)), @@ -66,7 +69,7 @@ impl Deref for RecordState { fn deref(&self) -> &Self::Target { match self { RecordState::Original(ref r) => &r.data, - RecordState::New(ref r) => &r, + RecordState::New(ref r) => r, RecordState::Updated(ref r) => &r.data, RecordState::Deleted(ref r) => &r.data, } @@ -123,21 +126,18 @@ impl DayDetailViewModel { } pub fn weight(&self) -> Option> { - match *self.weight.read().unwrap() { - Some(ref w) => Some((*w).weight), - None => None, - } + (*self.weight.read().unwrap()).as_ref().map(|w| w.weight) } pub fn set_weight(&self, new_weight: si::Kilogram) { let mut record = self.weight.write().unwrap(); let new_record = match *record { Some(ref rstate) => rstate.clone().with_value(ft_core::Weight { - date: self.date.clone(), + date: self.date, weight: new_weight, }), None => RecordState::New(ft_core::Weight { - date: self.date.clone(), + date: self.date, weight: new_weight, }), }; @@ -145,21 +145,18 @@ impl DayDetailViewModel { } pub fn steps(&self) -> Option { - match *self.steps.read().unwrap() { - Some(ref w) => Some((*w).count), - None => None, - } + (*self.steps.read().unwrap()).as_ref().map(|w| w.count) } pub fn set_steps(&self, new_count: u32) { let mut record = self.steps.write().unwrap(); let new_record = match *record { Some(ref rstate) => rstate.clone().with_value(ft_core::Steps { - date: self.date.clone(), + date: self.date, count: new_count, }), None => RecordState::New(ft_core::Steps { - date: self.date.clone(), + date: self.date, count: new_count, }), }; diff --git a/fitnesstrax/app/src/views/day_detail_view.rs b/fitnesstrax/app/src/views/day_detail_view.rs index 0b992bb..ae213fe 100644 --- a/fitnesstrax/app/src/views/day_detail_view.rs +++ b/fitnesstrax/app/src/views/day_detail_view.rs @@ -15,22 +15,12 @@ You should have received a copy of the GNU General Public License along with Fit */ use crate::{ - app::App, components::{DayDetail, DayEdit, Singleton, SingletonImpl}, view_models::DayDetailViewModel, }; -use dimensioned::si; -use emseries::{Record, RecordId}; -use ft_core::TraxRecord; use glib::Object; use gtk::{prelude::*, subclass::prelude::*}; -use std::{ - cell::RefCell, - collections::HashMap, - ops::Deref, - rc::Rc, - sync::{Arc, RwLock}, -}; +use std::cell::RefCell; #[derive(Default)] pub struct DayDetailViewPrivate { diff --git a/fitnesstrax/app/src/views/historical_view.rs b/fitnesstrax/app/src/views/historical_view.rs index 20e074d..23bccad 100644 --- a/fitnesstrax/app/src/views/historical_view.rs +++ b/fitnesstrax/app/src/views/historical_view.rs @@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License along with Fit */ use crate::{components::DaySummary, types::DayInterval}; -use chrono::{Duration, Local, NaiveDate}; +use chrono::NaiveDate; use emseries::Record; use ft_core::TraxRecord; use glib::Object; @@ -161,7 +161,7 @@ impl DayRecords { } pub fn date(&self) -> chrono::NaiveDate { - self.imp().date.borrow().clone() + *self.imp().date.borrow() } pub fn records(&self) -> Vec> { @@ -204,11 +204,11 @@ impl GroupedRecords { self } - fn items<'a>(&'a self) -> impl Iterator + 'a { + fn items(&self) -> impl Iterator + '_ { self.interval.days().map(|date| { self.data .get(&date) - .map(|rec| rec.clone()) + .cloned() .unwrap_or(DayRecords::new(date, vec![])) }) } @@ -217,6 +217,7 @@ impl GroupedRecords { #[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}; @@ -272,7 +273,12 @@ mod test { }, ]; - let groups = GroupedRecords::from(records).0; + 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); } } diff --git a/fitnesstrax/app/src/views/placeholder_view.rs b/fitnesstrax/app/src/views/placeholder_view.rs index c3f68eb..94e8e50 100644 --- a/fitnesstrax/app/src/views/placeholder_view.rs +++ b/fitnesstrax/app/src/views/placeholder_view.rs @@ -38,8 +38,8 @@ glib::wrapper! { pub struct PlaceholderView(ObjectSubclass) @extends gtk::Box, gtk::Widget; } -impl PlaceholderView { - pub fn new() -> Self { +impl Default for PlaceholderView { + fn default() -> Self { let s: Self = Object::builder().build(); s } diff --git a/fitnesstrax/app/src/views/welcome_view.rs b/fitnesstrax/app/src/views/welcome_view.rs index 1f391a3..78a21a0 100644 --- a/fitnesstrax/app/src/views/welcome_view.rs +++ b/fitnesstrax/app/src/views/welcome_view.rs @@ -14,7 +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 . */ -use crate::{app::App, components::FileChooserRow}; +use crate::components::FileChooserRow; use glib::Object; use gtk::{prelude::*, subclass::prelude::*}; use std::path::PathBuf; diff --git a/fitnesstrax/core/src/legacy.rs b/fitnesstrax/core/src/legacy.rs index 0a79713..9ab1ba3 100644 --- a/fitnesstrax/core/src/legacy.rs +++ b/fitnesstrax/core/src/legacy.rs @@ -1,23 +1,25 @@ -use crate::types; - #[cfg(test)] mod test { #[test] + #[ignore] fn read_a_legacy_set_rep_record() { unimplemented!() } #[test] + #[ignore] fn read_a_legacy_steps_record() { unimplemented!() } #[test] + #[ignore] fn read_a_legacy_time_distance_record() { unimplemented!() } #[test] + #[ignore] fn read_a_legacy_weight_record() { unimplemented!() } diff --git a/fitnesstrax/core/src/types.rs b/fitnesstrax/core/src/types.rs index f27fe18..b0959f7 100644 --- a/fitnesstrax/core/src/types.rs +++ b/fitnesstrax/core/src/types.rs @@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize}; /// SetRep represents workouts like pushups or situps, which involve doing a "set" of a number of /// actions, resting, and then doing another set. +#[allow(dead_code)] pub struct SetRep { /// I assume that a set/rep workout is only done once in a day. date: NaiveDate, @@ -24,7 +25,7 @@ pub struct Steps { impl Recordable for Steps { fn timestamp(&self) -> Timestamp { - Timestamp::Date(self.date.clone()) + Timestamp::Date(self.date) } fn tags(&self) -> Vec { @@ -66,7 +67,7 @@ pub struct Weight { impl Recordable for Weight { fn timestamp(&self) -> Timestamp { - Timestamp::Date(self.date.clone()) + Timestamp::Date(self.date) } fn tags(&self) -> Vec { @@ -111,29 +112,23 @@ impl TraxRecord { } pub fn is_weight(&self) -> bool { - match self { - TraxRecord::Weight(_) => true, - _ => false, - } + matches!(self, TraxRecord::Weight(_)) } pub fn is_steps(&self) -> bool { - match self { - TraxRecord::Steps(_) => true, - _ => false, - } + matches!(self, TraxRecord::Steps(_)) } } impl Recordable for TraxRecord { fn timestamp(&self) -> Timestamp { match self { - TraxRecord::BikeRide(rec) => Timestamp::DateTime(rec.datetime.clone()), - TraxRecord::Row(rec) => Timestamp::DateTime(rec.datetime.clone()), - TraxRecord::Run(rec) => Timestamp::DateTime(rec.datetime.clone()), + TraxRecord::BikeRide(rec) => Timestamp::DateTime(rec.datetime), + TraxRecord::Row(rec) => Timestamp::DateTime(rec.datetime), + TraxRecord::Run(rec) => Timestamp::DateTime(rec.datetime), TraxRecord::Steps(rec) => rec.timestamp(), - TraxRecord::Swim(rec) => Timestamp::DateTime(rec.datetime.clone()), - TraxRecord::Walk(rec) => Timestamp::DateTime(rec.datetime.clone()), + TraxRecord::Swim(rec) => Timestamp::DateTime(rec.datetime), + TraxRecord::Walk(rec) => Timestamp::DateTime(rec.datetime), TraxRecord::Weight(rec) => rec.timestamp(), } } @@ -162,6 +157,6 @@ mod test { let id = series.put(record.clone()).unwrap(); let record_ = series.get(&id).unwrap(); - assert_eq!(record_, record); + assert_eq!(record_.data, record); } }