Create a swappable UI component #160

Merged
savanni merged 7 commits from fitnesstrax/swappable into main 2024-01-18 12:56:56 +00:00
6 changed files with 29 additions and 9 deletions
Showing only changes of commit 1c2c4982a1 - Show all commits

1
Cargo.lock generated
View File

@ -1031,6 +1031,7 @@ dependencies = [
"glib-build-tools 0.18.0", "glib-build-tools 0.18.0",
"gtk4", "gtk4",
"libadwaita", "libadwaita",
"thiserror",
"tokio", "tokio",
] ]

View File

@ -16,6 +16,7 @@ ft-core = { path = "../core" }
gio = { version = "0.18" } gio = { version = "0.18" }
glib = { version = "0.18" } glib = { version = "0.18" }
gtk = { version = "0.7", package = "gtk4", features = [ "v4_10" ] } gtk = { version = "0.7", package = "gtk4", features = [ "v4_10" ] }
thiserror = { version = "1.0" }
tokio = { version = "1.34", features = [ "full" ] } tokio = { version = "1.34", features = [ "full" ] }
[build-dependencies] [build-dependencies]

View File

@ -22,11 +22,16 @@ use std::{
path::PathBuf, path::PathBuf,
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
use thiserror::Error;
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
#[derive(Debug, Error)]
pub enum AppError { pub enum AppError {
#[error("no database loaded")]
NoDatabase, NoDatabase,
#[error("failed to open the database")]
FailedToOpenDatabase, FailedToOpenDatabase,
#[error("unhandled error")]
Unhandled, Unhandled,
} }

View File

@ -281,7 +281,6 @@ impl DayEdit {
let s = s.clone(); let s = s.clone();
let records = records.clone(); let records = records.clone();
move || { move || {
println!("saving to database");
let weight_record = records.iter().find_map(|record| match record { let weight_record = records.iter().find_map(|record| match record {
Record { Record {
id, id,

View File

@ -73,7 +73,6 @@ impl<T: Clone + std::fmt::Debug + 'static> TextEntry<T> {
} }
match (self.parser)(buffer.text().as_str()) { match (self.parser)(buffer.text().as_str()) {
Ok(v) => { Ok(v) => {
println!("setting the value: {}", (self.renderer)(&v));
*self.value.borrow_mut() = Some(v); *self.value.borrow_mut() = Some(v);
self.widget.remove_css_class("error"); self.widget.remove_css_class("error");
} }
@ -86,7 +85,6 @@ impl<T: Clone + std::fmt::Debug + 'static> TextEntry<T> {
pub fn value(&self) -> Option<T> { pub fn value(&self) -> Option<T> {
let v = self.value.borrow().clone(); let v = self.value.borrow().clone();
println!("retrieving the value: {:?}", v.map(|v| (self.renderer)(&v)));
self.value.borrow().clone() self.value.borrow().clone()
} }

View File

@ -109,40 +109,56 @@ impl DayDetailView {
let s = self.clone(); let s = self.clone();
let app = self.imp().app.clone(); let app = self.imp().app.clone();
Box::new(move |record| { Box::new(move |record| {
let s = s.clone();
let app = app.clone(); let app = app.clone();
glib::spawn_future_local({ glib::spawn_future_local({
async move { async move {
match &*app.borrow() { match &*app.borrow() {
Some(app) => { Some(app) => {
let _ = app.put_record(record).await; let id = app
.put_record(record.clone())
.await
.expect("successful write");
s.imp()
.records
.borrow_mut()
.push(Record { id, data: record });
} }
None => {} None => {}
} }
s.view();
} }
}); });
s.view();
}) })
} }
fn on_update_record(&self) -> Box<dyn Fn(Record<ft_core::TraxRecord>)> { fn on_update_record(&self) -> Box<dyn Fn(Record<ft_core::TraxRecord>)> {
let s = self.clone(); let s = self.clone();
let app = self.imp().app.clone(); let app = self.imp().app.clone();
Box::new(move |record| { Box::new(move |updated_record| {
let app = app.clone(); let app = app.clone();
let mut records = s.imp().records.borrow_mut();
let idx = records.iter().position(|r| r.id == updated_record.id);
match idx {
Some(i) => records[i] = updated_record.clone(),
None => records.push(updated_record.clone()),
}
glib::spawn_future_local({ glib::spawn_future_local({
let s = s.clone();
async move { async move {
println!("record: {:?}", record);
match &*app.borrow() { match &*app.borrow() {
Some(app) => { Some(app) => {
let _ = app.update_record(record).await; let _ = app.update_record(updated_record).await;
} }
None => { None => {
println!("no app!"); println!("no app!");
} }
} }
s.view();
} }
}); });
s.view();
}) })
} }
} }