diff --git a/src/core/images.rs b/src/core/images.rs index 254b61f..661f29e 100644 --- a/src/core/images.rs +++ b/src/core/images.rs @@ -1,11 +1,13 @@ use super::model::Model; -use miette::{Result, miette, IntoDiagnostic}; +use miette::{miette, IntoDiagnostic, Result}; use serde::{Deserialize, Serialize}; use sqlx::{query_as, SqliteConnection}; use std::path::PathBuf; use tracing::error; -#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +#[derive( + Clone, Debug, Default, PartialEq, Serialize, Deserialize, +)] pub struct Image { pub id: i32, pub title: String, @@ -26,12 +28,17 @@ impl Model { let _ = self.add_item(image); } } - Err(e) => error!("There was an error in converting images: {e}"), + Err(e) => { + error!("There was an error in converting images: {e}") + } }; } } -pub async fn get_image_from_db(database_id: i32, db: &mut SqliteConnection) -> Result { +pub async fn get_image_from_db( + database_id: i32, + db: &mut SqliteConnection, +) -> Result { Ok(query_as!(Image, r#"SELECT title as "title!", file_path as "path!", id as "id: i32" from images where id = ?"#, database_id).fetch_one(db).await.into_diagnostic()?) } @@ -52,7 +59,7 @@ mod test { pub async fn test_db_and_model() { let mut image_model: Model = Model { items: vec![], - db: crate::core::model::get_db().await + db: crate::core::model::get_db().await, }; image_model.load_from_db().await; dbg!(&image_model.items); @@ -70,16 +77,26 @@ mod test { let image = test_image("A new image".into()); let mut image_model: Model = Model { items: vec![], - db: crate::core::model::get_db().await + db: crate::core::model::get_db().await, }; let result = image_model.add_item(image.clone()); let new_image = test_image("A newer image".into()); match result { Ok(_) => { - assert_eq!(&image, image_model.find(|i| i.id == 0).unwrap()); - assert_ne!(&new_image, image_model.find(|i| i.id == 0).unwrap()); + assert_eq!( + &image, + image_model.find(|i| i.id == 0).unwrap() + ); + assert_ne!( + &new_image, + image_model.find(|i| i.id == 0).unwrap() + ); } - Err(e) => assert!(false, "There was an error adding the image: {:?}", e), + Err(e) => assert!( + false, + "There was an error adding the image: {:?}", + e + ), } } } diff --git a/src/core/kinds.rs b/src/core/kinds.rs index e3330fe..40ed100 100644 --- a/src/core/kinds.rs +++ b/src/core/kinds.rs @@ -4,7 +4,9 @@ use serde::{Deserialize, Serialize}; use super::presentations::PresKind; -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, +)] pub enum ServiceItemKind { #[default] Song, @@ -22,7 +24,9 @@ impl std::fmt::Display for ServiceItemKind { Self::Video => "video".to_owned(), Self::Presentation(PresKind::Html) => "html".to_owned(), Self::Presentation(PresKind::Pdf) => "pdf".to_owned(), - Self::Presentation(PresKind::Generic) => "presentation".to_owned(), + Self::Presentation(PresKind::Generic) => { + "presentation".to_owned() + } Self::Content => "content".to_owned(), }; write!(f, "{s}") @@ -36,7 +40,9 @@ impl TryFrom for ServiceItemKind { "song" => Ok(Self::Song), "image" => Ok(Self::Image), "video" => Ok(Self::Video), - "presentation" => Ok(Self::Presentation(PresKind::Generic)), + "presentation" => { + Ok(Self::Presentation(PresKind::Generic)) + } "html" => Ok(Self::Presentation(PresKind::Html)), "pdf" => Ok(Self::Presentation(PresKind::Pdf)), "content" => Ok(Self::Content), @@ -51,7 +57,9 @@ impl From for String { ServiceItemKind::Song => "song".to_owned(), ServiceItemKind::Video => "video".to_owned(), ServiceItemKind::Image => "image".to_owned(), - ServiceItemKind::Presentation(_) => "presentation".to_owned(), + ServiceItemKind::Presentation(_) => { + "presentation".to_owned() + } ServiceItemKind::Content => "content".to_owned(), } } @@ -65,7 +73,10 @@ pub enum ParseError { impl Error for ParseError {} impl Display for ParseError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt( + &self, + f: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { let message = match self { Self::UnknownType => "The type does not exist. It needs to be one of 'song', 'video', 'image', 'presentation', or 'content'", }; diff --git a/src/core/lisp.rs b/src/core/lisp.rs index efbb30f..719e9b1 100644 --- a/src/core/lisp.rs +++ b/src/core/lisp.rs @@ -142,9 +142,11 @@ mod test { #[test] fn test_list() { - let lisp = read_to_string("./test_presentation.lisp").expect("oops"); + let lisp = + read_to_string("./test_presentation.lisp").expect("oops"); println!("{lisp}"); - let mut parser = Parser::from_str_custom(&lisp, Options::elisp()); + let mut parser = + Parser::from_str_custom(&lisp, Options::elisp()); for atom in parser.value_iter() { match atom { Ok(atom) => { diff --git a/src/core/mod.rs b/src/core/mod.rs index 6501999..2fd4e11 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1,9 +1,9 @@ pub mod images; pub mod kinds; pub mod lisp; +pub mod model; pub mod presentations; pub mod service_items; pub mod slide; pub mod songs; pub mod videos; -pub mod model; diff --git a/src/core/model.rs b/src/core/model.rs index 482deec..979a3f7 100644 --- a/src/core/model.rs +++ b/src/core/model.rs @@ -71,9 +71,7 @@ pub async fn get_db() -> SqliteConnection { data.push("library-db.sqlite3"); let mut db_url = String::from("sqlite://"); db_url.push_str(data.to_str().unwrap()); - SqliteConnection::connect(&db_url) - .await - .expect("problems") + SqliteConnection::connect(&db_url).await.expect("problems") } pub trait Modeling { diff --git a/src/core/presentations.rs b/src/core/presentations.rs index 04022a4..8cbbc0e 100644 --- a/src/core/presentations.rs +++ b/src/core/presentations.rs @@ -1,12 +1,16 @@ -use miette::{miette, Result, IntoDiagnostic}; +use miette::{miette, IntoDiagnostic, Result}; use serde::{Deserialize, Serialize}; -use sqlx::{prelude::FromRow, query, sqlite::SqliteRow, Row, SqliteConnection}; +use sqlx::{ + prelude::FromRow, query, sqlite::SqliteRow, Row, SqliteConnection, +}; use std::path::PathBuf; use tracing::error; use super::model::Model; -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, +)] pub enum PresKind { Html, #[default] @@ -14,7 +18,9 @@ pub enum PresKind { Generic, } -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, +)] pub struct Presentation { pub id: i32, pub title: String, @@ -75,7 +81,9 @@ impl Model { }); } } - Err(e) => error!("There was an error in converting presentations: {e}"), + Err(e) => error!( + "There was an error in converting presentations: {e}" + ), } } } @@ -114,10 +122,12 @@ mod test { async fn test_db_and_model() { let mut presentation_model: Model = Model { items: vec![], - db: crate::core::model::get_db().await + db: crate::core::model::get_db().await, }; presentation_model.load_from_db().await; - if let Some(presentation) = presentation_model.find(|p| p.id == 54) { + if let Some(presentation) = + presentation_model.find(|p| p.id == 54) + { let test_presentation = test_presentation(); assert_eq!(&test_presentation, presentation); } else { diff --git a/src/core/service_items.rs b/src/core/service_items.rs index 55519a6..98a4fff 100644 --- a/src/core/service_items.rs +++ b/src/core/service_items.rs @@ -52,7 +52,9 @@ impl From<&Image> for ServiceItem { impl From<&Presentation> for ServiceItem { fn from(presentation: &Presentation) -> Self { Self { - kind: ServiceItemKind::Presentation(presentation.kind.clone()), + kind: ServiceItemKind::Presentation( + presentation.kind.clone(), + ), database_id: presentation.id, ..Default::default() } @@ -60,7 +62,10 @@ impl From<&Presentation> for ServiceItem { } impl ServiceItemModel { - fn add_item(&mut self, item: impl Into) -> Result<()> { + fn add_item( + &mut self, + item: impl Into, + ) -> Result<()> { let service_item: ServiceItem = item.into(); self.items.push(service_item); Ok(()) @@ -103,7 +108,10 @@ mod test { let mut service_model = ServiceItemModel::default(); match service_model.add_item(&song) { Ok(_) => { - assert_eq!(ServiceItemKind::Song, service_model.items[0].kind); + assert_eq!( + ServiceItemKind::Song, + service_model.items[0].kind + ); assert_eq!( ServiceItemKind::Presentation(PresKind::Html), pres_item.kind diff --git a/src/core/slide.rs b/src/core/slide.rs index ae2ca4d..1b6c522 100644 --- a/src/core/slide.rs +++ b/src/core/slide.rs @@ -15,7 +15,9 @@ use crate::core::lisp::Symbol; use super::lisp::get_lists; -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize, +)] pub enum TextAlignment { TopLeft, TopCenter, @@ -39,7 +41,9 @@ impl From for TextAlignment { } } -#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, +)] pub struct Background { pub path: PathBuf, pub kind: BackgroundKind, @@ -113,16 +117,23 @@ pub enum ParseError { impl std::error::Error for ParseError {} impl Display for ParseError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt( + &self, + f: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { let message = match self { - Self::NonBackgroundFile => "The file is not a recognized image or video type", + Self::NonBackgroundFile => { + "The file is not a recognized image or video type" + } Self::DoesNotExist => "This file doesn't exist", }; write!(f, "Error: {message}") } } -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize, +)] pub enum BackgroundKind { #[default] Image, @@ -139,7 +150,9 @@ impl From for BackgroundKind { } } -#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +#[derive( + Clone, Debug, Default, PartialEq, Serialize, Deserialize, +)] pub struct Slide { id: i32, background: Background, @@ -170,7 +183,9 @@ impl Slide { } } -#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +#[derive( + Clone, Debug, Default, PartialEq, Serialize, Deserialize, +)] pub struct SlideBuilder { background: Option, text: Option, @@ -187,7 +202,10 @@ impl SlideBuilder { Self::default() } - pub(crate) fn background(mut self, background: PathBuf) -> Result { + pub(crate) fn background( + mut self, + background: PathBuf, + ) -> Result { let background = Background::try_from(background)?; let _ = self.background.insert(background); Ok(self) @@ -208,7 +226,10 @@ impl SlideBuilder { self } - pub(crate) fn text_alignment(mut self, text_alignment: TextAlignment) -> Self { + pub(crate) fn text_alignment( + mut self, + text_alignment: TextAlignment, + ) -> Self { let _ = self.text_alignment.insert(text_alignment); self } @@ -218,12 +239,18 @@ impl SlideBuilder { self } - pub(crate) fn video_start_time(mut self, video_start_time: f32) -> Self { + pub(crate) fn video_start_time( + mut self, + video_start_time: f32, + ) -> Self { let _ = self.video_start_time.insert(video_start_time); self } - pub(crate) fn video_end_time(mut self, video_end_time: f32) -> Self { + pub(crate) fn video_end_time( + mut self, + video_end_time: f32, + ) -> Self { let _ = self.video_end_time.insert(video_end_time); self } @@ -281,7 +308,11 @@ impl Image { } } -fn build_image_bg(atom: &Value, image_map: &mut HashMap, map_index: usize) { +fn build_image_bg( + atom: &Value, + image_map: &mut HashMap, + map_index: usize, +) { // This needs to be the cons that contains (image . ...) // the image is a symbol and the rest are keywords and other maps if atom.is_symbol() { @@ -289,7 +320,9 @@ fn build_image_bg(atom: &Value, image_map: &mut HashMap, map_ind return; } - for atom in atom.list_iter().unwrap().map(|a| a.as_cons().unwrap()) { + for atom in + atom.list_iter().unwrap().map(|a| a.as_cons().unwrap()) + { if atom.car() == &Value::Symbol("image".into()) { build_image_bg(atom.cdr(), image_map, map_index); } else { @@ -345,7 +378,11 @@ fn build_slides( dbg!(¤t_symbol); match value { Value::Cons(v) => { - slide_builder = build_slides(&v, current_symbol.clone(), slide_builder); + slide_builder = build_slides( + &v, + current_symbol.clone(), + slide_builder, + ); } Value::Nil => { dbg!(Value::Nil); @@ -361,7 +398,8 @@ fn build_slides( } Value::Symbol(symbol) => { dbg!(symbol); - current_symbol = Symbol::from_str(symbol).unwrap_or_default(); + current_symbol = + Symbol::from_str(symbol).unwrap_or_default(); } Value::Keyword(keyword) => { dbg!(keyword); @@ -399,16 +437,19 @@ mod test { #[test] fn test_lexp_serialize() { - let lisp = read_to_string("./test_presentation.lisp").expect("oops"); + let lisp = + read_to_string("./test_presentation.lisp").expect("oops"); println!("{lisp}"); - let mut parser = Parser::from_str_custom(&lisp, Options::elisp()); + let mut parser = + Parser::from_str_custom(&lisp, Options::elisp()); for atom in parser.value_iter() { match atom { Ok(atom) => { let symbol = Symbol::None; let slide_builder = SlideBuilder::new(); - atom.as_cons() - .map(|c| build_slides(c, symbol, slide_builder)); + atom.as_cons().map(|c| { + build_slides(c, symbol, slide_builder) + }); } Err(e) => { dbg!(e); @@ -432,7 +473,8 @@ mod test { #[test] fn test_ron_deserialize() { - let slide = read_to_string("./test_presentation.ron").expect("Problem getting file read"); + let slide = read_to_string("./test_presentation.ron") + .expect("Problem getting file read"); match ron::from_str::>(&slide) { Ok(s) => { dbg!(s); diff --git a/src/core/songs.rs b/src/core/songs.rs index b3720d6..9228645 100644 --- a/src/core/songs.rs +++ b/src/core/songs.rs @@ -3,15 +3,20 @@ use std::{collections::HashMap, path::PathBuf}; use cosmic::{executor, iced::Executor}; use miette::{miette, IntoDiagnostic, Result}; use serde::{Deserialize, Serialize}; -use sqlx::{query, query_as, sqlite::SqliteRow, FromRow, Row, SqliteConnection}; +use sqlx::{ + query, query_as, sqlite::SqliteRow, FromRow, Row, + SqliteConnection, +}; use tracing::{debug, error}; use super::{ - model::{Model}, + model::Model, slide::{Background, TextAlignment}, }; -#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, +)] pub struct Song { pub id: i32, pub title: String, @@ -27,9 +32,11 @@ pub struct Song { } const VERSE_KEYWORDS: [&str; 24] = [ - "Verse 1", "Verse 2", "Verse 3", "Verse 4", "Verse 5", "Verse 6", "Verse 7", "Verse 8", - "Chorus 1", "Chorus 2", "Chorus 3", "Chorus 4", "Bridge 1", "Bridge 2", "Bridge 3", "Bridge 4", - "Intro 1", "Intro 2", "Ending 1", "Ending 2", "Other 1", "Other 2", "Other 3", "Other 4", + "Verse 1", "Verse 2", "Verse 3", "Verse 4", "Verse 5", "Verse 6", + "Verse 7", "Verse 8", "Chorus 1", "Chorus 2", "Chorus 3", + "Chorus 4", "Bridge 1", "Bridge 2", "Bridge 3", "Bridge 4", + "Intro 1", "Intro 2", "Ending 1", "Ending 2", "Other 1", + "Other 2", "Other 3", "Other 4", ]; impl FromRow<'_, SqliteRow> for Song { @@ -54,7 +61,6 @@ impl FromRow<'_, SqliteRow> for Song { Ok(background) => Some(background), Err(_) => None, } - }, text_alignment: Some({ let horizontal_alignment: String = row.try_get(3)?; @@ -67,8 +73,12 @@ impl FromRow<'_, SqliteRow> for Song { ("left", "center") => TextAlignment::MiddleLeft, ("left", "bottom") => TextAlignment::BottomLeft, ("center", "top") => TextAlignment::TopCenter, - ("center", "center") => TextAlignment::MiddleCenter, - ("center", "bottom") => TextAlignment::BottomCenter, + ("center", "center") => { + TextAlignment::MiddleCenter + } + ("center", "bottom") => { + TextAlignment::BottomCenter + } ("right", "top") => TextAlignment::TopRight, ("right", "center") => TextAlignment::MiddleRight, ("right", "bottom") => TextAlignment::BottomRight, @@ -81,7 +91,10 @@ impl FromRow<'_, SqliteRow> for Song { } } -pub async fn get_song_from_db(index: i32, db: &mut SqliteConnection) -> Result { +pub async fn get_song_from_db( + index: i32, + db: &mut SqliteConnection, +) -> Result { let row = query(r#"SELECT verse_order as "verse_order!", font_size as "font_size!: i32", background_type as "background_type!", horizontal_text_alignment as "horizontal_text_alignment!", vertical_text_alignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs where id = $1"#).bind(index).fetch_one(db).await.into_diagnostic()?; Ok(Song::from_row(&row).into_diagnostic()?) } @@ -96,14 +109,16 @@ impl Model { match Song::from_row(&song) { Ok(song) => { let _ = self.add_item(song); - }, - Err(e) => error!("Could not convert song: {e}"), + } + Err(e) => { + error!("Could not convert song: {e}") + } }; - }; - }, + } + } Err(e) => { error!("There was an error in converting songs: {e}"); - }, + } } } } @@ -115,7 +130,11 @@ impl Song { return Err(miette!("There is no lyrics here")); } else if self.verse_order.is_none() { return Err(miette!("There is no verse_order here")); - } else if self.verse_order.clone().is_some_and(|v| v.is_empty()) { + } else if self + .verse_order + .clone() + .is_some_and(|v| v.is_empty()) + { return Err(miette!("There is no verse_order here")); } if let Some(raw_lyrics) = self.lyrics.clone() { @@ -145,16 +164,21 @@ impl Song { let mut verse_name = ""; debug!(verse = verse); for word in VERSE_KEYWORDS { - let end_verse = verse.get(1..2).unwrap_or_default(); - let beg_verse = verse.get(0..1).unwrap_or_default(); - if word.starts_with(beg_verse) && word.ends_with(end_verse) { + let end_verse = + verse.get(1..2).unwrap_or_default(); + let beg_verse = + verse.get(0..1).unwrap_or_default(); + if word.starts_with(beg_verse) + && word.ends_with(end_verse) + { verse_name = word; continue; } } if let Some(lyric) = lyric_map.get(verse_name) { if lyric.contains("\n\n") { - let split_lyrics: Vec<&str> = lyric.split("\n\n").collect(); + let split_lyrics: Vec<&str> = + lyric.split("\n\n").collect(); for lyric in split_lyrics { if lyric.is_empty() { continue; @@ -246,11 +270,12 @@ From the day You saved my soul" .to_string(), ); - song.verse_order = "O1 V1 C1 C2 O2 V2 C3 C2 O2 B1 C2 C2 E1 O2" - .to_string() - .split(' ') - .map(|s| Some(s.to_string())) - .collect(); + song.verse_order = + "O1 V1 C1 C2 O2 V2 C3 C2 O2 B1 C2 C2 E1 O2" + .to_string() + .split(' ') + .map(|s| Some(s.to_string())) + .collect(); let lyrics = song.get_lyrics(); match lyrics { Ok(lyrics) => { @@ -265,7 +290,7 @@ You saved my soul" async fn model() -> Model { let song_model: Model = Model { items: vec![], - db: crate::core::model::get_db().await + db: crate::core::model::get_db().await, }; song_model } @@ -302,7 +327,10 @@ You saved my soul" song_model.load_from_db().await; match song_model.update_item(song, 2) { - Ok(()) => assert_eq!(&cloned_song, song_model.find(|s| s.id == 7).unwrap()), + Ok(()) => assert_eq!( + &cloned_song, + song_model.find(|s| s.id == 7).unwrap() + ), Err(e) => assert!(false, "{e}"), } } diff --git a/src/core/videos.rs b/src/core/videos.rs index 991d414..57e9806 100644 --- a/src/core/videos.rs +++ b/src/core/videos.rs @@ -1,12 +1,14 @@ use super::model::Model; use cosmic::{executor, iced::Executor}; -use miette::{Result, miette, IntoDiagnostic}; +use miette::{miette, IntoDiagnostic, Result}; use serde::{Deserialize, Serialize}; use sqlx::{query_as, SqliteConnection}; use std::path::PathBuf; use tracing::error; -#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +#[derive( + Clone, Debug, Default, PartialEq, Serialize, Deserialize, +)] pub struct Video { pub id: i32, pub title: String, @@ -25,12 +27,17 @@ impl Model