From fbc4606471e0bd7722e4432d6acc38b2c920c2fe Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Mon, 6 Apr 2026 16:45:36 -0500 Subject: [PATCH] this may be the way. By making the db functions take the vector of items in the model, we can drain the model, pass an owned version of those items to the async db function(adding, updating, deleting, etc) and then return an updated list of the items back in the Result. We should probably return a tuple with the original vector of items in case the db function fails somehow. --- src/core/songs.rs | 25 +++--- src/ui/library.rs | 224 ++++++++++++++++++---------------------------- 2 files changed, 101 insertions(+), 148 deletions(-) diff --git a/src/core/songs.rs b/src/core/songs.rs index eedfc98..b474ba3 100644 --- a/src/core/songs.rs +++ b/src/core/songs.rs @@ -1,5 +1,6 @@ use std::{ borrow::Cow, collections::HashMap, option::Option, path::PathBuf, + sync::Arc, }; use cosmic::{ @@ -745,7 +746,7 @@ impl Model { pub async fn append_song( &mut self, song: Song, - db: PoolConnection, + db: &SqlitePool, ) -> Result<()> { self.add_item(song)?; todo!() @@ -753,7 +754,7 @@ impl Model { pub async fn new_song( &mut self, - db: PoolConnection, + db: Arc, ) -> Result { let mut song = Song::default(); @@ -790,7 +791,7 @@ impl Model { song.font_size, background ) - .execute(&mut db.detach()) + .execute(&*db) .await .into_diagnostic()?; song.id = i32::try_from(res.last_insert_rowid()).expect( @@ -803,7 +804,7 @@ impl Model { pub async fn update_song( &mut self, song: Song, - db: PoolConnection, + db: &SqlitePool, ) -> Result<()> { let id = song.id; self.update_item(song.clone(), |song| song.id == id)?; @@ -898,7 +899,7 @@ impl Model { style, weight ) - .execute(&mut db.detach()) + .execute(db) .await .into_diagnostic()?; @@ -910,11 +911,11 @@ impl Model { pub async fn remove_song( &mut self, id: i32, - db: PoolConnection, + db: &SqlitePool, ) -> Result<()> { self.remove_item(|current_song| id == current_song.id)?; query!("DELETE FROM songs WHERE id = $1", id) - .execute(&mut db.detach()) + .execute(db) .await .into_diagnostic() .map(|_| ()) @@ -970,8 +971,9 @@ pub async fn remove_from_db( } pub async fn add_song_to_db( - db: PoolConnection, -) -> Result { + mut songs: Vec, + db: Arc, +) -> Result> { let mut song = Song::default(); let verse_order = { @@ -1007,13 +1009,14 @@ pub async fn add_song_to_db( song.font_size, background ) - .execute(&mut db.detach()) + .execute(&*db) .await .into_diagnostic()?; song.id = i32::try_from(res.last_insert_rowid()).expect( "Fairly confident that this number won't get that high", ); - Ok(song) + songs.push(song); + Ok(songs) } pub async fn update_song_in_db( diff --git a/src/ui/library.rs b/src/ui/library.rs index 1261803..bb66445 100644 --- a/src/ui/library.rs +++ b/src/ui/library.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, sync::Arc}; use cosmic::{ Element, Task, @@ -50,7 +50,7 @@ pub struct Library { selected_items: Option>, hovered_item: Option<(LibraryKind, i32)>, editing_item: Option<(LibraryKind, i32)>, - db: SqlitePool, + db: Arc, menu_keys: std::collections::HashMap, context_menu: Option, modifiers_pressed: Option, @@ -104,7 +104,8 @@ pub enum Message { OpenContext(i32), None, AddFiles(Vec), - AddSong(PoolConnection), + ReaddSongs(Vec), + AddSong, AddImages(Option>), AddVideos(Option>), AddPresentations(Option>), @@ -130,7 +131,7 @@ impl<'a> Library { selected_items: None, hovered_item: None, editing_item: None, - db, + db: db.into(), menu_keys: HashMap::new(), context_menu: None, modifiers_pressed: None, @@ -142,29 +143,30 @@ impl<'a> Library { self.song_library.get_item(index) } + async fn test(&mut self) -> Result { + self.song_library.new_song(Arc::clone(&self.db)).await + } + #[allow(clippy::cast_possible_wrap)] #[allow(clippy::cast_possible_truncation)] #[allow(clippy::too_many_lines)] #[allow(clippy::match_same_arms)] - pub fn update(&'a mut self, message: Message) -> Action { + pub fn update(&mut self, message: Message) -> Action { match message { Message::None => (), Message::DeleteItem => { return self.delete_items(); } - Message::AddSong(db) => { + Message::ReaddSongs(songs) => { + self.song_library.items = songs; + } + Message::AddSong => { + let songs = + self.song_library.items.drain(..).collect(); return Action::Task(Task::perform( - self.song_library.new_song(db), + add_song_to_db(songs, Arc::clone(&self.db)), move |res| match res { - Ok(song) => { - let index = - (self.song_library.items.len() - 1) - as i32; - Message::OpenItem(Some(( - LibraryKind::Song, - index, - ))) - } + Ok(songs) => Message::ReaddSongs(songs), Err(e) => { error!("adding error: {e}"); Message::None @@ -177,12 +179,7 @@ impl<'a> Library { self.library_open.unwrap_or(LibraryKind::Song); match kind { LibraryKind::Song => { - let task = Task::future(self.db.acquire()) - .map_err(|e| { - miette::miette!("Database error: {e}") - }) - .map(|db| Message::AddSong(db)); - return Action::Task(task); + return self.update(Message::AddSong); } LibraryKind::Video => { return Action::Task(Task::perform( @@ -479,20 +476,13 @@ impl<'a> Library { return Action::None; } - return Action::Task( - Task::future(self.db.acquire()) - .map_err(|e| { - miette::miette!("Database error: {e}") - }) - .and_then(move |db| { - Task::perform( - self.song_library - .update_song(song, db), - |r| r.map(|_| Message::SongChanged), - ) - }) - .map(|r| r.unwrap_or(Message::None)), - ); + return Action::Task(Task::perform( + self.song_library.update_song(song, &self.db), + |r| { + r.map(|_| Message::SongChanged) + .unwrap_or(Message::None) + }, + )); } Message::SongChanged => { // self.song_library.update_item(song, index); @@ -509,20 +499,13 @@ impl<'a> Library { return Action::None; } - return Action::Task( - Task::future(self.db.acquire()) - .map_err(|e| { - miette::miette!("Database error: {e}") - }) - .and_then(move |conn| { - Task::perform( - self.image_library - .update_image(image, conn), - |r| r.map(|_| Message::ImageChanged), - ) - }) - .map(|r| r.unwrap_or(Message::None)), - ); + return Action::Task(Task::perform( + self.image_library.update_image(image, &self.db), + |r| { + r.map(|_| Message::ImageChanged) + .unwrap_or(Message::None) + }, + )); } Message::ImageChanged => (), Message::UpdateVideo(video) => { @@ -536,20 +519,13 @@ impl<'a> Library { return Action::None; } - return Action::Task( - Task::future(self.db.acquire()) - .map_err(|e| { - miette::miette!("Database error: {e}") - }) - .and_then(move |conn| { - Task::perform( - self.video_library - .update_video(video, conn), - |r| r.map(|_| Message::VideoChanged), - ) - }) - .map(|r| r.unwrap_or(Message::None)), - ); + return Action::Task(Task::perform( + self.video_library.update_video(video, &self.db), + |r| { + r.map(|_| Message::VideoChanged) + .unwrap_or(Message::None) + }, + )); } Message::VideoChanged => debug!("vid shoulda changed"), Message::UpdatePresentation(presentation) => { @@ -562,25 +538,15 @@ impl<'a> Library { error!("Not editing a presentation item"); return Action::None; } - let mut update_fn = move |conn| { - self.presentation_library - .update_presentation(presentation, conn) - }; - return Action::Task( - Task::future(self.db.acquire()) - .map_err(|e| { - miette::miette!("Database error: {e}") - }) - .and_then(move |conn| { - Task::perform(update_fn(conn), |r| { - r.map(|_| { - Message::PresentationChanged - }) - }) - }) - .map(|r| r.unwrap_or(Message::None)), - ); + return Action::Task(Task::perform( + self.presentation_library + .update_presentation(presentation, &self.db), + |r| { + r.map(|_| Message::PresentationChanged) + .unwrap_or(Message::None) + }, + )); } Message::PresentationChanged => (), Message::Error(_) => (), @@ -1264,21 +1230,17 @@ impl<'a> Library { if let Some(song) = self.song_library.get_item(*index) { - Task::future(self.db.acquire()).and_then( - move |db| { - Task::perform( - self.song_library - .remove_song(song.id, db), - |r| { - if let Err(e) = r { - error!(?e); - } - Message::None - }, - ) - .map(|m| Ok(m)) + Task::perform( + self.song_library + .remove_song(song.id, &self.db), + |r| { + if let Err(e) = r { + error!(?e); + } + Message::None }, ) + .map(|m| Ok(m)) } else { Task::none() } @@ -1287,21 +1249,17 @@ impl<'a> Library { if let Some(video) = self.video_library.get_item(*index) { - Task::future(self.db.acquire()).and_then( - move |db| { - Task::perform( - self.video_library - .remove_video(video.id, db), - |r| { - if let Err(e) = r { - error!(?e); - } - Message::None - }, - ) - .map(|m| Ok(m)) + Task::perform( + self.video_library + .remove_video(video.id, &self.db), + |r| { + if let Err(e) = r { + error!(?e); + } + Message::None }, ) + .map(|m| Ok(m)) } else { Task::none() } @@ -1314,21 +1272,17 @@ impl<'a> Library { image.id, image.title, "let's remove this image", ); - Task::future(self.db.acquire()).and_then( - move |db| { - Task::perform( - self.image_library - .remove_image(image.id, db), - |r| { - if let Err(e) = r { - error!(?e); - } - Message::None - }, - ) - .map(|m| Ok(m)) + Task::perform( + self.image_library + .remove_image(image.id, &self.db), + |r| { + if let Err(e) = r { + error!(?e); + } + Message::None }, ) + .map(|m| Ok(m)) } else { Task::none() } @@ -1337,24 +1291,20 @@ impl<'a> Library { if let Some(presentation) = self.presentation_library.get_item(*index) { - Task::future(self.db.acquire()).and_then( - move |db| { - Task::perform( - self.presentation_library - .remove_presentation( - presentation.id, - db, - ), - |r| { - if let Err(e) = r { - error!(?e); - } - Message::None - }, - ) - .map(|m| Ok(m)) + Task::perform( + self.presentation_library + .remove_presentation( + presentation.id, + &self.db, + ), + |r| { + if let Err(e) = r { + error!(?e); + } + Message::None }, ) + .map(|m| Ok(m)) } else { Task::none() }