diff --git a/src/core/images.rs b/src/core/images.rs index e0d78bf..4aa6440 100644 --- a/src/core/images.rs +++ b/src/core/images.rs @@ -7,13 +7,17 @@ use super::{ service_items::ServiceTrait, }; use crisp::types::{Keyword, Symbol, Value}; -use miette::{IntoDiagnostic, Result}; +use miette::{IntoDiagnostic, Result, miette}; use serde::{Deserialize, Serialize}; use sqlx::{ Sqlite, SqliteConnection, SqlitePool, pool::PoolConnection, query, query_as, }; -use std::path::{Path, PathBuf}; +use std::{ + mem::replace, + path::{Path, PathBuf}, + sync::Arc, +}; use tracing::{debug, error}; #[derive( @@ -254,70 +258,84 @@ impl Model { } pub async fn remove_from_db( - db: PoolConnection, + db: Arc, + mut images: Vec, id: i32, -) -> Result<()> { +) -> Result> { query!("DELETE FROM images WHERE id = $1", id) - .execute(&mut db.detach()) + .execute(&*db) .await .into_diagnostic() - .map(|_| ()) + .map(|_| ())?; + let index = images + .iter() + .position(|current_image| current_image.id == id) + .ok_or_else(|| miette!("Could not find image in model"))?; + images.remove(index); + Ok(images) } -pub async fn add_image_to_db( - image: Image, - db: PoolConnection, -) -> Result<()> { - let path = image - .path - .to_str() - .map(std::string::ToString::to_string) - .unwrap_or_default(); - let mut db = db.detach(); - query!( +pub async fn add_to_db( + new_images: Vec, + mut current_images: Vec, + db: Arc, +) -> Result> { + for image in new_images { + let path = image + .path + .to_str() + .map(std::string::ToString::to_string) + .unwrap_or_default(); + + query!( r#"INSERT INTO images (title, file_path) VALUES ($1, $2)"#, image.title, path, ) - .execute(&mut db) + .execute(&*db) .await .into_diagnostic()?; - Ok(()) + + current_images.push(image); + } + Ok(current_images) } -pub async fn update_image_in_db( +pub async fn update_in_db( image: Image, - db: PoolConnection, -) -> Result<()> { + mut images: Vec, + db: Arc, +) -> Result> { let path = image .path .to_str() .map(std::string::ToString::to_string) .unwrap_or_default(); - let mut db = db.detach(); - debug!(?image, "should be been updated"); - let result = query!( + + query!( r#"UPDATE images SET title = $2, file_path = $3 WHERE id = $1"#, image.id, image.title, path, ) - .execute(&mut db) - .await.into_diagnostic(); + .execute(&*db) + .await.into_diagnostic()?; - match result { - Ok(_) => { - debug!("should have been updated"); - Ok(()) - } - Err(e) => { - error! {?e}; - Err(e) - } - } + let current_image = images + .iter() + .position(|current_image| current_image.id == image.id) + .ok_or_else(|| miette!("Could not find image in model")) + .map(|index| { + images + .get_mut(index) + .expect("We should have this image already") + })?; + + replace(current_image, image); + Ok(images) } -pub async fn get_image_from_db( +pub async fn get_from_db( database_id: i32, db: &mut SqliteConnection, ) -> Result { diff --git a/src/core/presentations.rs b/src/core/presentations.rs index f02b53b..eaefd08 100644 --- a/src/core/presentations.rs +++ b/src/core/presentations.rs @@ -1,13 +1,17 @@ use cosmic::widget::image::Handle; use crisp::types::{Keyword, Symbol, Value}; -use miette::{IntoDiagnostic, Result}; +use miette::{IntoDiagnostic, Result, miette}; use mupdf::{Colorspace, Document, Matrix}; use serde::{Deserialize, Serialize}; use sqlx::{ Row, Sqlite, SqliteConnection, SqlitePool, pool::PoolConnection, prelude::FromRow, query, sqlite::SqliteRow, }; -use std::path::{Path, PathBuf}; +use std::{ + mem::replace, + path::{Path, PathBuf}, + sync::Arc, +}; use tracing::{debug, error}; use crate::{Background, Slide, SlideBuilder, TextAlignment}; @@ -406,61 +410,77 @@ impl Model { } pub async fn remove_from_db( - db: PoolConnection, + db: Arc, + mut presentations: Vec, id: i32, -) -> Result<()> { +) -> Result> { query!("DELETE FROM presentations WHERE id = $1", id) - .execute(&mut db.detach()) + .execute(&*db) .await .into_diagnostic() - .map(|_| ()) + .map(|_| ())?; + + let index = presentations + .iter() + .position(|current_presentation| { + current_presentation.id == id + }) + .ok_or_else(|| { + miette!("Could not find presentation in model") + })?; + presentations.remove(index); + Ok(presentations) } -pub async fn add_presentation_to_db( +pub async fn add_to_db( + new_presentations: Vec, + mut current_presentations: Vec, + db: Arc, +) -> Result> { + for presentation in new_presentations { + let path = presentation + .path + .to_str() + .map(std::string::ToString::to_string) + .unwrap_or_default(); + let html = presentation.kind == PresKind::Html; + let (starting_index, ending_index) = if let PresKind::Pdf { + starting_index, + ending_index, + } = presentation.kind + { + (starting_index, ending_index) + } else { + (0, 0) + }; + query!( + r#"INSERT INTO presentations (title, file_path, html, starting_index, ending_index) VALUES ($1, $2, $3, $4, $5)"#, + presentation.title, + path, + html, + starting_index, + ending_index + ) + .execute(&*db) + .await + .into_diagnostic()?; + + current_presentations.push(presentation); + } + Ok(current_presentations) +} + +pub async fn update_in_db( presentation: Presentation, - db: PoolConnection, -) -> Result<()> { + mut presentations: Vec, + db: Arc, +) -> Result> { let path = presentation .path .to_str() .map(std::string::ToString::to_string) .unwrap_or_default(); let html = presentation.kind == PresKind::Html; - let mut db = db.detach(); - let (starting_index, ending_index) = if let PresKind::Pdf { - starting_index, - ending_index, - } = presentation.kind - { - (starting_index, ending_index) - } else { - (0, 0) - }; - query!( - r#"INSERT INTO presentations (title, file_path, html, starting_index, ending_index) VALUES ($1, $2, $3, $4, $5)"#, - presentation.title, - path, - html, - starting_index, - ending_index - ) - .execute(&mut db) - .await - .into_diagnostic()?; - Ok(()) -} - -pub async fn update_presentation_in_db( - presentation: Presentation, - db: PoolConnection, -) -> Result<()> { - let path = presentation - .path - .to_str() - .map(std::string::ToString::to_string) - .unwrap_or_default(); - let html = presentation.kind == PresKind::Html; - let mut db = db.detach(); let (starting_index, ending_index) = if let PresKind::Pdf { starting_index: s_index, ending_index: e_index, @@ -472,53 +492,8 @@ pub async fn update_presentation_in_db( (0, 0) }; debug!(starting_index, ending_index); - let id = presentation.id; - if let Err(e) = - query!("SELECT id FROM presentations where id = $1", id) - .fetch_one(&mut db) - .await - { - if let Ok(ids) = query!("SELECT id FROM presentations") - .fetch_all(&mut db) - .await - { - let Some(mut max) = ids.iter().map(|r| r.id).max() else { - return Err(miette::miette!("cannot find max id")); - }; - debug!( - ?e, - "Presentation not found adding a new presentation" - ); - max += 1; - let result = query!( - r#"INSERT into presentations VALUES($1, $2, $3, $4, $5, $6)"#, - max, - presentation.title, - path, - html, - starting_index, - ending_index, - ) - .execute(&mut db) - .await - .into_diagnostic(); - return match result { - Ok(_) => { - debug!("presentation should have been added"); - Ok(()) - } - Err(e) => { - error! {?e}; - Err(e) - } - }; - } - return Err(miette::miette!("cannot find ids")); - } - - debug!(?presentation, "should be been updated"); - let result = query!( + query!( r#"UPDATE presentations SET title = $2, file_path = $3, html = $4, starting_index = $5, ending_index = $6 WHERE id = $1"#, presentation.id, presentation.title, @@ -527,19 +502,25 @@ pub async fn update_presentation_in_db( starting_index, ending_index ) - .execute(&mut db) - .await.into_diagnostic(); + .execute(&*db) + .await.into_diagnostic()?; - match result { - Ok(_) => { - debug!("should have been updated"); - Ok(()) - } - Err(e) => { - error! {?e}; - Err(e) - } - } + let current_presentation = presentations + .iter() + .position(|current_presentation| { + current_presentation.id == presentation.id + }) + .ok_or_else(|| { + miette!("Could not find presentation in model") + }) + .map(|index| { + presentations + .get_mut(index) + .expect("We should have this presentation already") + })?; + + replace(current_presentation, presentation); + Ok(presentations) } pub async fn get_presentation_from_db( diff --git a/src/core/songs.rs b/src/core/songs.rs index 8237708..85e4bc5 100644 --- a/src/core/songs.rs +++ b/src/core/songs.rs @@ -1,6 +1,6 @@ use std::{ - borrow::Cow, collections::HashMap, option::Option, path::PathBuf, - sync::Arc, + borrow::Cow, collections::HashMap, mem::replace, option::Option, + path::PathBuf, sync::Arc, }; use cosmic::{ @@ -1027,26 +1027,28 @@ pub async fn add_to_db( Ok(songs) } -pub async fn update_song_in_db( - item: Song, - songs: Vec, +pub async fn update_in_db( + song: Song, + mut songs: Vec, db: Arc, -) -> Result<()> { +) -> Result> { // self.update_item(item.clone(), index)?; // debug!(?item); let verse_order = - ron::ser::to_string(&item.verses).into_diagnostic()?; + ron::ser::to_string(&song.verses).into_diagnostic()?; - let audio = item + let audio = song .audio + .clone() .map(|a| a.to_str().unwrap_or_default().to_string()); - let background = item + let background = song .background + .clone() .map(|b| b.path.to_str().unwrap_or_default().to_string()); - let lyrics = item.verse_map.map(|map| { + let lyrics = song.verse_map.clone().map(|map| { map.iter() .map(|(name, lyric)| { let lyric = lyric.trim_end_matches('\n').to_string(); @@ -1057,7 +1059,7 @@ pub async fn update_song_in_db( let lyrics = ron::ser::to_string(&lyrics).into_diagnostic()?; let (vertical_alignment, horizontal_alignment) = - item.text_alignment.map_or_else( + song.text_alignment.map_or_else( || ("center", "center"), |ta| match ta { TextAlignment::TopLeft => ("top", "left"), @@ -1072,20 +1074,20 @@ pub async fn update_song_in_db( }, ); - let stroke_size = item.stroke_size.unwrap_or_default(); - let shadow_size = item.shadow_size.unwrap_or_default(); + let stroke_size = song.stroke_size.unwrap_or_default(); + let shadow_size = song.shadow_size.unwrap_or_default(); let (shadow_offset_x, shadow_offset_y) = - item.shadow_offset.unwrap_or_default(); + song.shadow_offset.unwrap_or_default(); let stroke_color = - ron::ser::to_string(&item.stroke_color).into_diagnostic()?; + ron::ser::to_string(&song.stroke_color).into_diagnostic()?; let shadow_color = - ron::ser::to_string(&item.shadow_color).into_diagnostic()?; + ron::ser::to_string(&song.shadow_color).into_diagnostic()?; let style = - ron::ser::to_string(&item.font_style).into_diagnostic()?; + ron::ser::to_string(&song.font_style).into_diagnostic()?; let weight = - ron::ser::to_string(&item.font_weight).into_diagnostic()?; + ron::ser::to_string(&song.font_weight).into_diagnostic()?; // debug!( // ?stroke_size, @@ -1098,15 +1100,15 @@ pub async fn update_song_in_db( let result = query!( r#"UPDATE songs SET title = $2, lyrics = $3, author = $4, ccli = $5, verse_order = $6, audio = $7, font = $8, font_size = $9, background = $10, horizontal_text_alignment = $11, vertical_text_alignment = $12, stroke_color = $13, shadow_color = $14, stroke_size = $15, shadow_size = $16, shadow_offset_x = $17, shadow_offset_y = $18, style = $19, weight = $20 WHERE id = $1"#, - item.id, - item.title, + song.id, + song.title, lyrics, - item.author, - item.ccli, + song.author, + song.ccli, verse_order, audio, - item.font, - item.font_size, + song.font, + song.font_size, background, horizontal_alignment, vertical_alignment, @@ -1124,8 +1126,18 @@ pub async fn update_song_in_db( .into_diagnostic()?; debug!(rows_affected = ?result.rows_affected()); + let index = songs + .iter() + .position(|current_song| current_song.id == song.id) + .ok_or_else(|| miette!("Could not find song in model"))?; - Ok(()) + replace( + songs + .get_mut(index) + .expect("We have found the song so this shouldn't fail"), + song, + ); + Ok(songs) } impl Song { diff --git a/src/core/videos.rs b/src/core/videos.rs index e91b93b..76c8acd 100644 --- a/src/core/videos.rs +++ b/src/core/videos.rs @@ -8,13 +8,17 @@ use super::{ slide::Slide, }; use crisp::types::{Keyword, Symbol, Value}; -use miette::{IntoDiagnostic, Result}; +use miette::{IntoDiagnostic, Result, miette}; use serde::{Deserialize, Serialize}; use sqlx::{ Sqlite, SqliteConnection, SqlitePool, pool::PoolConnection, query, query_as, }; -use std::path::{Path, PathBuf}; +use std::{ + mem::replace, + path::{Path, PathBuf}, + sync::Arc, +}; use tracing::{debug, error}; #[derive( @@ -254,52 +258,65 @@ impl Model