From bea97b55f3f0f31bac12dd15de453281fe51290f Mon Sep 17 00:00:00 2001 From: Julian Mutter Date: Wed, 7 Feb 2024 20:05:20 +0100 Subject: [PATCH] Make relm4 app async and update last_opened in db --- src/database.rs | 25 +++++++++++++++-- src/main.rs | 11 ++++++-- src/ui/app.rs | 62 ++++++++++++++++++++++++++++++----------- src/ui/mod.rs | 1 + src/ui/sheet_listing.rs | 1 - src/ui/sheet_model.rs | 18 +++++++----- 6 files changed, 88 insertions(+), 30 deletions(-) diff --git a/src/database.rs b/src/database.rs index efd16c5..0868d91 100644 --- a/src/database.rs +++ b/src/database.rs @@ -59,6 +59,15 @@ impl Database { .await .map(|_| ()) } + pub async fn update_sheet_last_opened(&self, sheet: &Sheet) -> sqlx::Result<()> { + sqlx::query("UPDATE sheets SET last_opened = $1 WHERE id = $2") + .bind(sheet.last_opened.timestamp()) + .bind(sheet.id) + .execute(&self.connection) + .await + .map(|_| ()) + // TODO: check for success + } pub async fn fetch_all_sheets(&self) -> sqlx::Result> { sqlx::query_as::<_, Sheet>("SELECT * FROM sheets") @@ -82,15 +91,25 @@ impl Database { .map(|result| result.last_insert_rowid()) } - pub async fn update_orphan_file_path(&self, file: &OrphanFile) -> sqlx::Result<()> { + pub async fn update_orphan_file_path(&self, orphan: &OrphanFile) -> sqlx::Result<()> { sqlx::query("UPDATE orphan_files SET path = $1 WHERE id = $2") - .bind(file.path.to_str().unwrap().to_string()) - .bind(file.id) + .bind(orphan.path.to_str().unwrap().to_string()) + .bind(orphan.id) .execute(&self.connection) .await .map(|_| ()) } + pub async fn update_orphan_last_opened(&self, orphan: &OrphanFile) -> sqlx::Result<()> { + sqlx::query("UPDATE orphan_files SET last_opened = $1 WHERE id = $2") + .bind(orphan.last_opened.timestamp()) + .bind(orphan.id) + .execute(&self.connection) + .await + .map(|_| ()) + // TODO: check for success + } + pub async fn fetch_all_orphan_files(&self) -> sqlx::Result> { sqlx::query_as::<_, OrphanFile>("SELECT * FROM orphan_files") .fetch_all(&self.connection) diff --git a/src/main.rs b/src/main.rs index 99890aa..5fb701a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -59,17 +59,22 @@ async fn main() { let mut sheets = validation_result.validated_sheets; sheets.append(&mut validation_result.updated_sheets); - let sheets_and_orphans = SheetsAndOrphans { sheets, orphans }; + let app_init_data = AppInitData { + sheets, + orphans, + database, + }; let app = RelmApp::new("de.frajul.sheet-organizer"); // Pass empty command line args to allow my own parsing app.with_args(Vec::new()) - .run::(sheets_and_orphans); + .run_async::(app_init_data); } -pub struct SheetsAndOrphans { +pub struct AppInitData { sheets: Vec, orphans: Vec, + database: Database, } pub struct FileValidationResult { diff --git a/src/ui/app.rs b/src/ui/app.rs index 0f94be8..efa2048 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -1,9 +1,15 @@ +use chrono::Utc; use gtk::prelude::*; -use relm4::prelude::*; +use relm4::{ + component::{AsyncComponent, AsyncComponentParts}, + prelude::*, + AsyncComponentSender, +}; use crate::{ + database::Database, ui::{mcdu::McduOutput, sheet_model::SheetModelType}, - SheetsAndOrphans, + AppInitData, }; use super::{ @@ -12,6 +18,7 @@ use super::{ }; pub struct AppModel { + database: Database, mcdu: Controller, sheets_and_files_listing: Controller, new_files_listing: Controller, @@ -24,11 +31,12 @@ pub enum AppInput { SheetsAndFilesSheetPressed(SheetModelType), } -#[relm4::component(pub)] -impl SimpleComponent for AppModel { +#[relm4::component(pub, async)] +impl AsyncComponent for AppModel { type Input = AppInput; type Output = (); - type Init = SheetsAndOrphans; + type Init = AppInitData; + type CommandOutput = (); view! { #[root] @@ -66,11 +74,11 @@ impl SimpleComponent for AppModel { } } - fn init( - sheets_and_orphans: Self::Init, - window: &Self::Root, - sender: ComponentSender, - ) -> relm4::ComponentParts { + async fn init( + init_data: Self::Init, + window: Self::Root, + sender: AsyncComponentSender, + ) -> AsyncComponentParts { relm4_icons::initialize_icons(); let mcdu = McduModel::builder() @@ -79,7 +87,7 @@ impl SimpleComponent for AppModel { McduOutput::SearchStarted(query) => AppInput::SearchStarted(query), }); - let new_files: Vec = sheets_and_orphans + let new_files: Vec = init_data .orphans .iter() .map(|orphan| SheetModelType::Orphan { @@ -87,12 +95,12 @@ impl SimpleComponent for AppModel { }) .collect(); - let new_files_clone_iter = sheets_and_orphans + let new_files_clone_iter = init_data .orphans .into_iter() .map(|orphan| SheetModelType::Orphan { orphan }); - let sheets_and_files: Vec = sheets_and_orphans + let sheets_and_files: Vec = init_data .sheets .into_iter() .map(|sheet| SheetModelType::Sheet { sheet }) @@ -111,6 +119,7 @@ impl SimpleComponent for AppModel { }); let model = AppModel { + database: init_data.database, mcdu, sheets_and_files_listing, new_files_listing, @@ -118,10 +127,15 @@ impl SimpleComponent for AppModel { let widgets = view_output!(); - ComponentParts { model, widgets } + AsyncComponentParts { model, widgets } } - fn update(&mut self, message: Self::Input, _sender: ComponentSender) { + async fn update( + &mut self, + message: Self::Input, + sender: AsyncComponentSender, + _root: &Self::Root, + ) { // AppInput::SheetPressed(sheet) => opener::open(sheet).unwrap(), match message { AppInput::SearchStarted(query) => { @@ -133,7 +147,23 @@ impl SimpleComponent for AppModel { // TODO } AppInput::SheetsAndFilesSheetPressed(sheet_model_type) => { - opener::open(sheet_model_type.get_path()).unwrap() + opener::open(sheet_model_type.get_path()).unwrap(); + match sheet_model_type { + SheetModelType::Orphan { mut orphan } => { + orphan.last_opened = Utc::now(); + self.database + .update_orphan_last_opened(&orphan) + .await + .unwrap(); + } + SheetModelType::Sheet { mut sheet } => { + sheet.last_opened = Utc::now(); + self.database + .update_sheet_last_opened(&sheet) + .await + .unwrap(); + } + }; } } } diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 5f3a11e..78d10f9 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,4 +1,5 @@ pub mod app; +pub mod database_worker; pub mod mcdu; pub mod sheet_listing; pub mod sheet_model; diff --git a/src/ui/sheet_listing.rs b/src/ui/sheet_listing.rs index 8a3fab6..566a4c4 100644 --- a/src/ui/sheet_listing.rs +++ b/src/ui/sheet_listing.rs @@ -66,7 +66,6 @@ impl SimpleComponent for SheetListingModel { } SheetListingInput::ListBoxRowClicked(index) => { let x = self.sheets.get(index as usize).unwrap(); - debug!("clicked: {}!!!!!", x.label); sender .output(SheetModelSelected { sheet_model_type: x.sheet_model_type.clone(), diff --git a/src/ui/sheet_model.rs b/src/ui/sheet_model.rs index 09201f4..37c9c5e 100644 --- a/src/ui/sheet_model.rs +++ b/src/ui/sheet_model.rs @@ -64,13 +64,17 @@ impl FactoryComponent for SheetModel { fn init_model(value: Self::Init, _index: &DynamicIndex, _sender: FactorySender) -> Self { let label = match &value { SheetModelType::Sheet { sheet } => sheet.name.to_string(), - SheetModelType::Orphan { orphan } => orphan - .path - .file_name() - .unwrap() - .to_str() - .unwrap() - .to_string(), + SheetModelType::Orphan { orphan } => { + orphan + .path + .file_name() + .unwrap() + .to_str() + .unwrap() + .to_string() + + " " + + &orphan.last_opened.to_string() + } }; SheetModel {