diff --git a/src/core/file.rs b/src/core/file.rs index 7531640..c35a9f9 100644 --- a/src/core/file.rs +++ b/src/core/file.rs @@ -13,6 +13,7 @@ use tar::Builder; use tracing::error; use zstd::Encoder; +#[allow(clippy::too_many_lines)] pub fn save( list: Vec, path: impl AsRef, @@ -23,7 +24,7 @@ pub fn save( fs::remove_file(path).into_diagnostic()?; } let save_file = File::create(path).into_diagnostic()?; - let ron = process_service_items(&list)?; + let ron = process_service_items(&list); let encoder = Encoder::new(save_file, 3) .expect("file encoder shouldn't fail") @@ -58,7 +59,7 @@ pub fn save( } } match tar.append_file("serviceitems.ron", &mut f) { - Ok(_) => { + Ok(()) => { dbg!( "should have added serviceitems.ron to the file" ); @@ -125,7 +126,7 @@ pub fn save( } match tar.finish() { - Ok(_) => (), + Ok(()) => (), Err(e) => { error!(?e); dbg!(&e); @@ -135,11 +136,11 @@ pub fn save( fs::remove_dir_all(temp_dir).into_diagnostic() } -fn process_service_items(items: &Vec) -> Result { - Ok(items +fn process_service_items(items: &[ServiceItem]) -> String { + items .iter() .filter_map(|item| ron::ser::to_string(item).ok()) - .collect()) + .collect() } #[cfg(test)] diff --git a/src/core/images.rs b/src/core/images.rs index 2fb9d75..3667c49 100644 --- a/src/core/images.rs +++ b/src/core/images.rs @@ -72,11 +72,10 @@ impl Content for Image { fn subtext(&self) -> String { if self.path.exists() { - self.path - .file_name() - .map_or("Missing image".into(), |f| { - f.to_string_lossy().to_string() - }) + self.path.file_name().map_or_else( + || "Missing image".into(), + |f| f.to_string_lossy().to_string(), + ) } else { "Missing image".into() } @@ -89,6 +88,7 @@ impl From for Image { } } +#[allow(clippy::option_if_let_else)] impl From<&Value> for Image { fn from(value: &Value) -> Self { match value { diff --git a/src/core/kinds.rs b/src/core/kinds.rs index 00d9917..af1e383 100644 --- a/src/core/kinds.rs +++ b/src/core/kinds.rs @@ -28,9 +28,11 @@ impl TryFrom for ServiceItemKind { let ext = path .extension() .and_then(|ext| ext.to_str()) - .ok_or(miette::miette!( - "There isn't an extension on this file" - ))?; + .ok_or_else(|| { + miette::miette!( + "There isn't an extension on this file" + ) + })?; match ext { "png" | "jpg" | "jpeg" => { Ok(Self::Image(Image::from(path))) diff --git a/src/core/model.rs b/src/core/model.rs index 25affdc..03615b4 100644 --- a/src/core/model.rs +++ b/src/core/model.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, mem::replace, path::PathBuf}; +use std::{borrow::Cow, fs, mem::replace, path::PathBuf}; use cosmic::iced::clipboard::mime::{AllowedMimeTypes, AsMimeTypes}; use miette::{IntoDiagnostic, Result, miette}; @@ -84,26 +84,36 @@ impl Model { } pub fn update_item(&mut self, item: T, index: i32) -> Result<()> { - if let Some(current_item) = self.items.get_mut(index as usize) - { - let _old_item = replace(current_item, item); - Ok(()) - } else { - Err(miette!( - "Item doesn't exist in model. Id was {}", - index - )) - } + self.items + .get_mut( + usize::try_from(index) + .expect("Shouldn't be negative"), + ) + .map_or_else( + || { + Err(miette!( + "Item doesn't exist in model. Id was {index}" + )) + }, + |current_item| { + let _old_item = replace(current_item, item); + Ok(()) + }, + ) } pub fn remove_item(&mut self, index: i32) -> Result<()> { - self.items.remove(index as usize); + self.items.remove( + usize::try_from(index).expect("Shouldn't be negative"), + ); Ok(()) } #[must_use] pub fn get_item(&self, index: i32) -> Option<&T> { - self.items.get(index as usize) + self.items.get( + usize::try_from(index).expect("shouldn't be negative"), + ) } pub fn find

(&self, f: P) -> Option<&T> @@ -114,7 +124,10 @@ impl Model { } pub fn insert_item(&mut self, item: T, index: i32) -> Result<()> { - self.items.insert(index as usize, item); + self.items.insert( + usize::try_from(index).expect("Shouldn't be negative"), + item, + ); Ok(()) } } @@ -131,11 +144,13 @@ impl Model { // } pub async fn get_db() -> SqliteConnection { - let mut data = dirs::data_local_dir().unwrap(); + let mut data = dirs::data_local_dir() + .expect("Should be able to find a data dir"); data.push("lumina"); + let _ = fs::create_dir_all(&data); data.push("library-db.sqlite3"); let mut db_url = String::from("sqlite://"); - db_url.push_str(data.to_str().unwrap()); + db_url.push_str(data.to_str().expect("Should be there")); SqliteConnection::connect(&db_url).await.expect("problems") } diff --git a/src/core/presentations.rs b/src/core/presentations.rs index d58043a..bee3f9e 100644 --- a/src/core/presentations.rs +++ b/src/core/presentations.rs @@ -65,27 +65,24 @@ impl From for Presentation { .to_str() .unwrap_or_default() { - "pdf" => { - if let Ok(document) = Document::open(&value.as_path()) - { - if let Ok(count) = document.page_count() { - PresKind::Pdf { - starting_index: 0, - ending_index: count - 1, - } - } else { + "pdf" => Document::open(&value.as_path()).map_or( + PresKind::Pdf { + starting_index: 0, + ending_index: 0, + }, + |document| { + document.page_count().map_or( PresKind::Pdf { starting_index: 0, ending_index: 0, - } - } - } else { - PresKind::Pdf { - starting_index: 0, - ending_index: 0, - } - } - } + }, + |count| PresKind::Pdf { + starting_index: 0, + ending_index: count - 1, + }, + ) + }, + ), "html" => PresKind::Html, _ => PresKind::Generic, }; @@ -129,11 +126,10 @@ impl Content for Presentation { fn subtext(&self) -> String { if self.path.exists() { - self.path - .file_name() - .map_or("Missing presentation".into(), |f| { - f.to_string_lossy().to_string() - }) + self.path.file_name().map_or_else( + || "Missing presentation".into(), + |f| f.to_string_lossy().to_string(), + ) } else { "Missing presentation".into() } @@ -146,6 +142,7 @@ impl From for Presentation { } } +#[allow(clippy::option_if_let_else)] impl From<&Value> for Presentation { fn from(value: &Value) -> Self { match value { @@ -206,15 +203,14 @@ impl ServiceTrait for Presentation { let pages: Vec = pages .enumerate() .filter_map(|(index, page)| { - if (index as i32) < starting_index { - return None; - } else if (index as i32) > ending_index { + let index = i32::try_from(index) + .expect("Shouldn't be that high"); + + if index < starting_index || index > ending_index { return None; } - let Some(page) = page.ok() else { - return None; - }; + let page = page.ok()?; let matrix = Matrix::IDENTITY; let colorspace = Colorspace::device_rgb(); let Ok(pixmap) = page @@ -248,7 +244,10 @@ impl ServiceTrait for Presentation { .video_loop(false) .video_start_time(0.0) .video_end_time(0.0) - .pdf_index(index as u32) + .pdf_index( + u32::try_from(index) + .expect("Shouldn't get that high"), + ) .pdf_page(page) .build()?; slides.push(slide); @@ -334,32 +333,38 @@ impl Model { presentation.ending_index, ) { PresKind::Pdf { - starting_index: starting_index as i32, - ending_index: ending_index as i32, + starting_index: i32::try_from( + starting_index, + ) + .expect("Shouldn't get that high"), + ending_index: i32::try_from( + ending_index, + ) + .expect("Shouldn't get that high"), } } else { let path = PathBuf::from(presentation.path); - if let Ok(document) = - Document::open(path.as_path()) - { - if let Ok(count) = - document.page_count() - { - let ending_index = count - 1; - PresKind::Pdf { - starting_index: 0, - ending_index, - } - } else { - PresKind::Pdf { - starting_index: 0, - ending_index: 0, - } - } - } else { - PresKind::Generic - } + + Document::open(path.as_path()).map_or( + PresKind::Generic, + |document| { + document.page_count().map_or( + PresKind::Pdf { + starting_index: 0, + ending_index: 0, + }, + |count| { + let ending_index = + count - 1; + PresKind::Pdf { + starting_index: 0, + ending_index, + } + }, + ) + }, + ) }, }); } @@ -416,16 +421,16 @@ pub async fn update_presentation_in_db( .unwrap_or_default(); let html = presentation.kind == PresKind::Html; let mut db = db.detach(); - let mut starting_index = 0; - let mut ending_index = 0; - if let PresKind::Pdf { + let (starting_index, ending_index) = if let PresKind::Pdf { starting_index: s_index, ending_index: e_index, - } = presentation.get_kind() + } = + presentation.get_kind() { - starting_index = *s_index; - ending_index = *e_index; - } + (*s_index, *e_index) + } else { + (0, 0) + }; let id = presentation.id; if let Err(e) = query!("SELECT id FROM presentations where id = $1", id) diff --git a/src/core/service_items.rs b/src/core/service_items.rs index 2d13a27..fb341fa 100644 --- a/src/core/service_items.rs +++ b/src/core/service_items.rs @@ -32,7 +32,7 @@ impl Eq for ServiceItem {} impl PartialOrd for ServiceItem { fn partial_cmp(&self, other: &Self) -> Option { - self.id.partial_cmp(&other.id) + Some(self.cmp(other)) } } @@ -89,9 +89,11 @@ impl TryFrom for ServiceItem { let ext = path .extension() .and_then(|ext| ext.to_str()) - .ok_or(miette::miette!( - "There isn't an extension on this file" - ))?; + .ok_or_else(|| { + miette::miette!( + "There isn't an extension on this file" + ) + })?; match ext { "png" | "jpg" | "jpeg" => { Ok(Self::from(&Image::from(path))) @@ -157,6 +159,8 @@ impl From for ServiceItem { } } +#[allow(clippy::option_if_let_else)] +#[allow(clippy::match_like_matches_macro)] impl From<&Value> for ServiceItem { fn from(value: &Value) -> Self { match value { @@ -280,64 +284,61 @@ impl From> for Service { impl From<&Song> for ServiceItem { fn from(song: &Song) -> Self { - if let Ok(slides) = song.to_slides() { - Self { + song.to_slides().map_or_else( + |_| Self { + kind: ServiceItemKind::Song(song.clone()), + database_id: song.id, + title: song.title.clone(), + ..Default::default() + }, + |slides| Self { kind: ServiceItemKind::Song(song.clone()), database_id: song.id, title: song.title.clone(), slides, ..Default::default() - } - } else { - Self { - kind: ServiceItemKind::Song(song.clone()), - database_id: song.id, - title: song.title.clone(), - ..Default::default() - } - } + }, + ) } } impl From<&Video> for ServiceItem { fn from(video: &Video) -> Self { - if let Ok(slides) = video.to_slides() { - Self { + video.to_slides().map_or_else( + |_| Self { + kind: ServiceItemKind::Video(video.clone()), + database_id: video.id, + title: video.title.clone(), + ..Default::default() + }, + |slides| Self { kind: ServiceItemKind::Video(video.clone()), database_id: video.id, title: video.title.clone(), slides, ..Default::default() - } - } else { - Self { - kind: ServiceItemKind::Video(video.clone()), - database_id: video.id, - title: video.title.clone(), - ..Default::default() - } - } + }, + ) } } impl From<&Image> for ServiceItem { fn from(image: &Image) -> Self { - if let Ok(slides) = image.to_slides() { - Self { + image.to_slides().map_or_else( + |_| Self { + kind: ServiceItemKind::Image(image.clone()), + database_id: image.id, + title: image.title.clone(), + ..Default::default() + }, + |slides| Self { kind: ServiceItemKind::Image(image.clone()), database_id: image.id, title: image.title.clone(), slides, ..Default::default() - } - } else { - Self { - kind: ServiceItemKind::Image(image.clone()), - database_id: image.id, - title: image.title.clone(), - ..Default::default() - } - } + }, + ) } } @@ -370,13 +371,9 @@ impl From<&Presentation> for ServiceItem { #[allow(unused)] impl Service { - fn add_item( - &mut self, - item: impl Into, - ) -> Result<()> { + fn add_item(&mut self, item: impl Into) { let service_item: ServiceItem = item.into(); self.items.push(service_item); - Ok(()) } pub fn to_slides(&self) -> Result> { @@ -392,7 +389,7 @@ impl Service { .collect::>(); let mut final_slides = vec![]; for (index, mut slide) in slides.into_iter().enumerate() { - slide.set_index(index as i32); + slide.set_index(i32::try_from(index).into_diagnostic()?); final_slides.push(slide); } Ok(final_slides) @@ -455,19 +452,15 @@ mod test { let pres = test_presentation(); let pres_item = ServiceItem::from(&pres); let mut service_model = Service::default(); - match service_model.add_item(&song) { - Ok(_) => { - assert_eq!( - ServiceItemKind::Song(song), - service_model.items[0].kind - ); - assert_eq!( - ServiceItemKind::Presentation(pres), - pres_item.kind - ); - assert_eq!(service_item, service_model.items[0]); - } - Err(e) => panic!("Problem adding item: {:?}", e), - } + service_model.add_item(&song); + assert_eq!( + ServiceItemKind::Song(song), + service_model.items[0].kind + ); + assert_eq!( + ServiceItemKind::Presentation(pres), + pres_item.kind + ); + assert_eq!(service_item, service_model.items[0]); } } diff --git a/src/core/slide.rs b/src/core/slide.rs index 04df0c7..721c7fb 100644 --- a/src/core/slide.rs +++ b/src/core/slide.rs @@ -136,12 +136,15 @@ impl TryFrom for Background { type Error = ParseError; fn try_from(path: PathBuf) -> Result { let path = if path.starts_with("~") { - let path = path.to_str().unwrap().to_string(); + let path = path + .to_str() + .expect("Should have a string") + .to_string(); let path = path.trim_start_matches("file://"); let home = dirs::home_dir() - .unwrap() + .expect("We should have a home directory") .to_str() - .unwrap() + .expect("Gah") .to_string(); let path = path.replace('~', &home); PathBuf::from(path) @@ -189,16 +192,18 @@ impl TryFrom<&str> for Background { fn try_from(value: &str) -> Result { let value = value.trim_start_matches("file://"); if value.starts_with('~') { - if let Some(home) = dirs::home_dir() { - if let Some(home) = home.to_str() { - let value = value.replace('~', home); - Self::try_from(PathBuf::from(value)) - } else { - Self::try_from(PathBuf::from(value)) - } - } else { - Self::try_from(PathBuf::from(value)) - } + dirs::home_dir().map_or_else( + || Self::try_from(PathBuf::from(value)), + |home| { + home.to_str().map_or_else( + || Self::try_from(PathBuf::from(value)), + |home| { + let value = value.replace('~', home); + Self::try_from(PathBuf::from(value)) + }, + ) + }, + ) } else if value.starts_with("./") { Err(ParseError::CannotCanonicalize) } else { @@ -262,95 +267,116 @@ impl From<&Slide> for Value { } impl Slide { + #[must_use] pub fn set_text(mut self, text: impl AsRef) -> Self { self.text = text.as_ref().into(); self } + #[must_use] pub fn with_text_svg(mut self, text_svg: TextSvg) -> Self { self.text_svg = Some(text_svg); self } + #[must_use] pub fn set_font(mut self, font: impl AsRef) -> Self { self.font = Some(font.as_ref().into()); self } + #[must_use] pub const fn set_font_size(mut self, font_size: i32) -> Self { self.font_size = font_size; self } + #[must_use] pub fn set_audio(mut self, audio: Option) -> Self { self.audio = audio; self } + #[must_use] pub const fn set_pdf_index(mut self, pdf_index: u32) -> Self { self.pdf_index = pdf_index; self } + #[must_use] pub const fn set_stroke(mut self, stroke: Stroke) -> Self { self.stroke = Some(stroke); self } + #[must_use] pub const fn set_shadow(mut self, shadow: Shadow) -> Self { self.shadow = Some(shadow); self } + #[must_use] pub const fn set_text_color(mut self, color: Color) -> Self { self.text_color = Some(color); self } + #[must_use] pub const fn background(&self) -> &Background { &self.background } + #[must_use] pub fn text(&self) -> String { self.text.clone() } + #[must_use] pub const fn text_alignment(&self) -> TextAlignment { self.text_alignment } + #[must_use] pub const fn font_size(&self) -> i32 { self.font_size } + #[must_use] pub fn font(&self) -> Option { self.font.clone() } + #[must_use] pub const fn video_loop(&self) -> bool { self.video_loop } + #[must_use] pub fn audio(&self) -> Option { self.audio.clone() } + #[must_use] pub fn pdf_page(&self) -> Option { self.pdf_page.clone() } + #[must_use] pub fn text_color(&self) -> Option { self.text_color.clone() } + #[must_use] pub fn stroke(&self) -> Option { self.stroke.clone() } + #[must_use] pub fn shadow(&self) -> Option { self.shadow.clone() } + #[must_use] pub const fn pdf_index(&self) -> u32 { self.pdf_index } @@ -405,7 +431,8 @@ impl From<&Value> for Slide { } } -fn lisp_to_slide(lisp: &Vec) -> Slide { +#[allow(clippy::option_if_let_else)] +fn lisp_to_slide(lisp: &[Value]) -> Slide { const DEFAULT_BACKGROUND_LOCATION: usize = 1; const DEFAULT_TEXT_LOCATION: usize = 0; @@ -469,6 +496,7 @@ fn lisp_to_slide(lisp: &Vec) -> Slide { } } +#[allow(clippy::option_if_let_else)] fn lisp_to_font_size(lisp: &Value) -> i32 { match lisp { Value::List(list) => { @@ -501,6 +529,7 @@ fn lisp_to_text(lisp: &Value) -> impl Into { // Need to return a Result here so that we can propogate // errors and then handle them appropriately +#[allow(clippy::option_if_let_else)] pub fn lisp_to_background(lisp: &Value) -> Background { match lisp { Value::List(list) => { diff --git a/src/core/song_search.rs b/src/core/song_search.rs index db090c8..723ef15 100644 --- a/src/core/song_search.rs +++ b/src/core/song_search.rs @@ -35,10 +35,7 @@ pub async fn search_online_song_links( Ok(document .select(&best_matches_selector) - .filter_map(|best_section| { - Some(best_section.select(&lyric_selector)) - }) - .flatten() + .flat_map(|best_section| best_section.select(&lyric_selector)) .map(|a| { a.value().attr("href").unwrap_or("").trim().to_string() }) @@ -52,13 +49,17 @@ pub async fn search_online_song_links( .collect()) } +// leaving this lint unfixed because I don't know if we will need this +// id value or not in the future and I'd like to keep the code understanding +// of what this variable might be. +#[allow(clippy::no_effect_underscore_binding)] pub async fn link_to_online_song( links: Vec + std::fmt::Display>, ) -> Result> { let mut songs = vec![]; for link in links { let parts = link - .to_string() + .as_ref() .split('/') .map(std::string::ToString::to_string) .collect::>(); diff --git a/src/core/songs.rs b/src/core/songs.rs index ffe73a8..0086c59 100644 --- a/src/core/songs.rs +++ b/src/core/songs.rs @@ -85,8 +85,8 @@ pub enum VerseName { impl VerseName { #[must_use] - pub fn from_string(name: String) -> Self { - match name.as_str() { + pub fn from_string(name: &str) -> Self { + match name { "Verse" => Self::Verse { number: 1 }, "Pre-Chorus" => Self::PreChorus { number: 1 }, "Chorus" => Self::Chorus { number: 1 }, @@ -96,7 +96,7 @@ impl VerseName { "Outro" => Self::Outro { number: 1 }, "Instrumental" => Self::Instrumental { number: 1 }, "Other" => Self::Other { number: 1 }, - "Blank" => Self::Blank, + // Blank is included in wildcard _ => Self::Blank, } } @@ -260,7 +260,9 @@ impl Content for Song { } fn subtext(&self) -> String { - self.author.clone().unwrap_or("Author missing".into()) + self.author + .clone() + .unwrap_or_else(|| "Author missing".into()) } } @@ -278,7 +280,9 @@ impl ServiceTrait for Song { let lyrics: Vec = self .verses .as_ref() - .ok_or(miette!("There are no verses assigned yet."))? + .ok_or_else(|| { + miette!("There are no verses assigned yet.") + })? .iter() .filter_map(|verse| self.get_lyric(verse)) .flat_map(|lyric| { @@ -299,13 +303,12 @@ impl ServiceTrait for Song { .clone() .unwrap_or_else(|| "Calibri".into()), ) - .style( - self.font_style.clone().unwrap_or_default(), - ) - .weight( - self.font_weight.clone().unwrap_or_default(), - ) - .size(self.font_size.unwrap_or(100) as u8); + .style(self.font_style.unwrap_or_default()) + .weight(self.font_weight.unwrap_or_default()) + .size( + u8::try_from(self.font_size.unwrap_or(100)) + .unwrap_or(100), + ); let stroke_size = self.stroke_size.unwrap_or_default(); let stroke: Stroke = stroke( @@ -367,22 +370,11 @@ impl ServiceTrait for Song { } } +#[allow(clippy::too_many_lines)] impl FromRow<'_, SqliteRow> for Song { fn from_row(row: &SqliteRow) -> sqlx::Result { let lyrics: &str = row.try_get("lyrics")?; - // let Some((mut verses, mut verse_map)) = - // lyrics_to_verse(lyrics.clone()).ok() - // else { - // return Err(sqlx::Error::ColumnDecode { - // index: "8".into(), - // source: miette!( - // "Couldn't decode the song into verses" - // ) - // .into(), - // }); - // }; - let Ok(verse_map) = ron::de::from_str::< Option>, >(lyrics) else { @@ -508,6 +500,9 @@ impl From for Song { } } +#[allow(clippy::option_if_let_else)] +#[allow(clippy::needless_pass_by_value)] +#[allow(clippy::too_many_lines)] pub fn lisp_to_song(list: Vec) -> Song { const DEFAULT_SONG_ID: i32 = 0; // const DEFAULT_SONG_LOCATION: usize = 0; @@ -586,7 +581,8 @@ pub fn lisp_to_song(list: Vec) -> Song { .position(|v| v == &Value::Keyword(Keyword::from("title"))) { let pos = key_pos + 1; - list.get(pos).map_or(String::from("song"), String::from) + list.get(pos) + .map_or_else(|| String::from("song"), String::from) } else { String::from("song") }; @@ -629,10 +625,7 @@ pub fn lisp_to_song(list: Vec) -> Song { || text.contains("i1") } _ => false, - } && match &inner[1] { - Value::String(_) => true, - _ => false, - }) + } && matches!(&inner[1], Value::String(_))) } _ => false, }) @@ -654,7 +647,7 @@ pub fn lisp_to_song(list: Vec) -> Song { let verse_title = match lyric_verse.as_str() { "i1" => r"\n\nIntro 1\n", - "i2" => r"\n\nIntro 1\n", + "i2" => r"\n\nIntro 2\n", "v1" => r"\n\nVerse 1\n", "v2" => r"\n\nVerse 2\n", "v3" => r"\n\nVerse 3\n", @@ -722,7 +715,7 @@ impl Model { pub async fn load_from_db(&mut self, db: &mut SqlitePool) { // static DATABASE_URL: &str = "sqlite:///home/chris/.local/share/lumina/library-db.sqlite3"; - let db1 = db.acquire().await.unwrap(); + let db1 = db.acquire().await.expect("Database not found"); let result = query("SELECT verse_order, font_size, background_type, horizontal_text_alignment, vertical_text_alignment, title, font, background, lyrics, ccli, author, audio, stroke_size, shadow_size, stroke_color, shadow_color, shadow_offset_x, shadow_offset_y, id from songs").fetch_all(&mut db1.detach()).await; match result { Ok(s) => { @@ -766,16 +759,14 @@ pub async fn add_song_to_db( let mut song = Song::default(); let verse_order = { - if let Some(vo) = song.verse_order.clone() { + song.verse_order.clone().map_or_else(String::new, |vo| { vo.into_iter() .map(|mut s| { s.push(' '); s }) .collect::() - } else { - String::new() - } + }) }; let audio = song @@ -803,7 +794,9 @@ pub async fn add_song_to_db( .execute(&mut db) .await .into_diagnostic()?; - song.id = res.last_insert_rowid() as i32; + song.id = i32::try_from(res.last_insert_rowid()).expect( + "Fairly confident that this number won't get that high", + ); Ok(song) } @@ -921,7 +914,7 @@ impl Song { verse_map .entry(*verse) .and_modify(|old_lyrics| { - *old_lyrics = lyric_copy.clone(); + old_lyrics.clone_from(&lyric_copy); }) .or_insert(lyric_copy); // debug!(?verse_map, "should be updated"); @@ -935,10 +928,6 @@ impl Song { } pub fn get_lyrics(&self) -> Result> { - // --------------------------------- - // new implementation - // --------------------------------- - if let Some(verses) = self.verses.as_ref() { let mut lyrics = vec![]; for verse in verses { @@ -952,73 +941,7 @@ impl Song { } return Ok(lyrics); } - return Err(miette!("No verses in this song yet")); - - // --------------------------------- - // old implementation - // --------------------------------- - - // let mut lyric_list = Vec::new(); - // if self.lyrics.is_none() { - // 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()) - // { - // return Err(miette!("There is no verse_order here")); - // } - // if let Some(raw_lyrics) = self.lyrics.clone() { - // let raw_lyrics = raw_lyrics.as_str(); - // let verse_order = self.verses.clone(); - - // let mut lyric_map = HashMap::new(); - // let mut verse_title = String::new(); - // let mut lyric = String::new(); - // for (i, line) in raw_lyrics.split('\n').enumerate() { - // if VERSE_KEYWORDS.contains(&line) { - // if i != 0 { - // lyric_map.insert(verse_title, lyric); - // lyric = String::new(); - // verse_title = line.to_string(); - // } else { - // verse_title = line.to_string(); - // } - // } else { - // lyric.push_str(line); - // lyric.push('\n'); - // } - // } - // lyric_map.insert(verse_title, lyric); - - // for verse in verse_order.unwrap_or_default() { - // let verse_name = &verse.get_name(); - // if let Some(lyric) = lyric_map.get(verse_name) { - // if lyric.contains("\n\n") { - // let split_lyrics: Vec<&str> = - // lyric.split("\n\n").collect(); - // for lyric in split_lyrics { - // if lyric.is_empty() { - // continue; - // } - // lyric_list.push(lyric.to_string()); - // } - // continue; - // } - // lyric_list.push(lyric.clone()); - // } else { - // // error!("NOT WORKING!"); - // } - // } - // // for lyric in lyric_list.iter() { - // // debug!(lyric = ?lyric) - // // } - // Ok(lyric_list) - // } else { - // Err(miette!("There are no lyrics")) - // } + Err(miette!("No verses in this song yet")) } pub fn update_verse_name( @@ -1123,39 +1046,28 @@ impl Song { #[must_use] pub fn get_next_verse_name(&self) -> VerseName { if let Some(verse_names) = &self.verses { - let verses: Vec<&VerseName> = verse_names + let verses = verse_names .iter() - .filter(|verse| match verse { - VerseName::Verse { .. } => true, - _ => false, + .filter(|verse| { + matches!(verse, VerseName::Verse { .. }) }) - .sorted() - .collect(); - let choruses: Vec<&VerseName> = verse_names - .iter() - .filter(|verse| match verse { - VerseName::Chorus { .. } => true, - _ => false, - }) - .collect(); - let bridges: Vec<&VerseName> = verse_names - .iter() - .filter(|verse| match verse { - VerseName::Bridge { .. } => true, - _ => false, - }) - .collect(); - if verses.is_empty() { + .sorted(); + let mut choruses = verse_names.iter().filter(|verse| { + matches!(verse, VerseName::Chorus { .. }) + }); + let mut bridges = verse_names.iter().filter(|verse| { + matches!(verse, VerseName::Bridge { .. }) + }); + if verses.len() == 0 { VerseName::Verse { number: 1 } - } else if choruses.is_empty() { + } else if choruses.next().is_none() { VerseName::Chorus { number: 1 } } else if verses.len() == 1 { let verse_number = - if let Some(last_verse) = verses.iter().last() { - match last_verse { - VerseName::Verse { number } => *number, - _ => 0, - } + if let Some(VerseName::Verse { number }) = + verses.last() + { + *number } else { 0 }; @@ -1163,10 +1075,10 @@ impl Song { return VerseName::Verse { number: 1 }; } VerseName::Verse { number: 2 } - } else if bridges.is_empty() { + } else if bridges.next().is_none() { VerseName::Bridge { number: 1 } } else { - if let Some(last_verse) = verses.iter().last() + if let Some(last_verse) = verses.last() && let VerseName::Verse { number } = last_verse { return VerseName::Verse { number: number + 1 }; @@ -1194,17 +1106,15 @@ impl Song { pub(crate) fn verse_name_from_str( &self, - verse_name: String, // chorus 2 + verse_name: &str, // chorus 2 old_verse_name: VerseName, // v4 ) -> VerseName { if old_verse_name.get_name() == verse_name { return old_verse_name; } - if let Some(verses) = - self.verse_map.clone().map(|verse_map| { + self.verse_map.clone().map(|verse_map| { verse_map.into_keys().collect::>() - }) - { + }).map_or_else(|| VerseName::from_string(verse_name), |verses| { verses .into_iter() .filter(|verse| { @@ -1212,7 +1122,7 @@ impl Song { .get_name() .split_whitespace() .next() - .unwrap() + .expect("Shouldn't fail, the get_name() fn won't return a string that is blank or all whitespace") == verse_name }) .sorted() @@ -1221,9 +1131,7 @@ impl Song { || VerseName::from_string(verse_name), |verse_name| verse_name.next(), ) - } else { - VerseName::from_string(verse_name) - } + }) } pub(crate) fn delete_verse(&mut self, verse: VerseName) { diff --git a/src/core/videos.rs b/src/core/videos.rs index b08b18b..970669b 100644 --- a/src/core/videos.rs +++ b/src/core/videos.rs @@ -90,6 +90,7 @@ impl From for Video { } } +#[allow(clippy::cast_precision_loss)] impl From<&Value> for Video { fn from(value: &Value) -> Self { match value { diff --git a/src/main.rs b/src/main.rs index d2377ba..36d2f20 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,7 +41,6 @@ use miette::{IntoDiagnostic, Result, miette}; use rayon::prelude::*; use resvg::usvg::fontdb; use std::collections::HashMap; -use std::fs::read_to_string; use std::path::PathBuf; use std::sync::Arc; use tracing::{debug, level_filters::LevelFilter}; diff --git a/src/ui/presenter.rs b/src/ui/presenter.rs index 89de4ed..2126eb7 100644 --- a/src/ui/presenter.rs +++ b/src/ui/presenter.rs @@ -27,6 +27,7 @@ use cosmic::{ menu, mouse_area, responsive, scrollable, text, }, }; +use derive_more::Debug; use iced_video_player::{Position, Video, VideoPlayer, gst_pbutils}; use rodio::{Decoder, OutputStream, OutputStreamBuilder, Sink}; use tracing::{debug, error, info, warn}; @@ -41,7 +42,7 @@ use crate::{ }, }; -const REFERENCE_WIDTH: f32 = 1920.0; +// const REFERENCE_WIDTH: f32 = 1920.0; static DEFAULT_SLIDE: LazyLock = LazyLock::new(Slide::default); // #[derive(Default, Clone, Debug)] @@ -73,8 +74,8 @@ pub(crate) enum Action { None, } -#[derive(Clone)] #[allow(clippy::large_enum_variant)] +#[derive(Clone, Debug)] pub(crate) enum Message { NextSlide, PrevSlide, @@ -83,7 +84,7 @@ pub(crate) enum Message { ClickSlide(usize, usize), EndVideo, StartVideo, - StartAudio, + // StartAudio, EndAudio, VideoPos(f32), VideoFrame, @@ -95,80 +96,19 @@ pub(crate) enum Message { RightClickSlide(usize, usize), AssignObsScene(usize), UpdateObsScenes(Vec), + #[debug("AddObsClient")] AddObsClient(Arc), AssignSlideAction(slide_actions::Action), } -impl std::fmt::Debug for Message { - fn fmt( - &self, - f: &mut std::fmt::Formatter<'_>, - ) -> std::fmt::Result { - match self { - Self::NextSlide => write!(f, "NextSlide"), - Self::PrevSlide => write!(f, "PrevSlide"), - Self::SlideChange(arg0) => { - f.debug_tuple("SlideChange").field(arg0).finish() - } - Self::ActivateSlide(arg0, arg1) => f - .debug_tuple("ActivateSlide") - .field(arg0) - .field(arg1) - .finish(), - Self::ClickSlide(arg0, arg1) => f - .debug_tuple("ClickSlide") - .field(arg0) - .field(arg1) - .finish(), - Self::EndVideo => write!(f, "EndVideo"), - Self::StartVideo => write!(f, "StartVideo"), - Self::StartAudio => write!(f, "StartAudio"), - Self::EndAudio => write!(f, "EndAudio"), - Self::VideoPos(arg0) => { - f.debug_tuple("VideoPos").field(arg0).finish() - } - Self::VideoFrame => write!(f, "VideoFrame"), - Self::MissingPlugin(arg0) => { - f.debug_tuple("MissingPlugin").field(arg0).finish() - } - Self::HoveredSlide(arg0) => { - f.debug_tuple("HoveredSlide").field(arg0).finish() - } - Self::ChangeFont(arg0) => { - f.debug_tuple("ChangeFont").field(arg0).finish() - } - Self::Error(arg0) => { - f.debug_tuple("Error").field(arg0).finish() - } - Self::None => write!(f, "None"), - Self::RightClickSlide(arg0, arg1) => f - .debug_tuple("RightClickSlide") - .field(arg0) - .field(arg1) - .finish(), - Self::AssignObsScene(arg0) => { - f.debug_tuple("ObsSceneAssign").field(arg0).finish() - } - Self::UpdateObsScenes(arg0) => { - f.debug_tuple("UpdateObsScenes").field(arg0).finish() - } - Self::AddObsClient(_) => write!(f, "AddObsClient"), - Self::AssignSlideAction(action) => f - .debug_tuple("AssignSlideAction") - .field(action) - .finish(), - } - } -} - #[allow(clippy::enum_variant_names)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum MenuAction { ObsSceneAssign(usize), ObsStartStream, ObsStopStream, - ObsStartRecord, - ObsStopRecord, + // ObsStartRecord, + // ObsStopRecord, } impl menu::Action for MenuAction { @@ -189,8 +129,8 @@ impl menu::Action for MenuAction { action: ObsAction::StopStream, }, ), - Self::ObsStartRecord => todo!(), - Self::ObsStopRecord => todo!(), + // Self::ObsStartRecord => todo!(), + // Self::ObsStopRecord => todo!(), } } } @@ -642,9 +582,9 @@ impl Presenter { Message::HoveredSlide(slide) => { self.hovered_slide = slide; } - Message::StartAudio => { - return Action::Task(self.start_audio()); - } + // Message::StartAudio => { + // return Action::Task(self.start_audio()); + // } Message::EndAudio => { self.sink.0.stop(); } @@ -1008,13 +948,13 @@ impl Presenter { } } -#[allow(clippy::unused_async)] -async fn obs_scene_switch(client: Arc, scene: Scene) { - match client.scenes().set_current_program_scene(&scene.id).await { - Ok(()) => debug!("Set scene to: {:?}", scene), - Err(e) => error!(?e), - } -} +// #[allow(clippy::unused_async)] +// async fn obs_scene_switch(client: Arc, scene: Scene) { +// match client.scenes().set_current_program_scene(&scene.id).await { +// Ok(()) => debug!("Set scene to: {:?}", scene), +// Err(e) => error!(?e), +// } +// } // This needs to be async so that rodio's audio will work #[allow(clippy::unused_async)] @@ -1033,17 +973,6 @@ async fn start_audio(sink: Arc, audio: PathBuf) { debug!(empty, paused, "Finished running"); } -fn scale_font(font_size: f32, width: f32) -> f32 { - let scale_factor = (REFERENCE_WIDTH / width).sqrt(); - // debug!(scale_factor); - - if font_size > 0.0 { - font_size / scale_factor - } else { - 50.0 - } -} - pub(crate) fn slide_view<'a>( slide: &'a Slide, video: Option<&'a Video>, diff --git a/src/ui/service.rs b/src/ui/service.rs index 674f38e..3fbaa10 100644 --- a/src/ui/service.rs +++ b/src/ui/service.rs @@ -344,7 +344,7 @@ struct State { hovered: bool, left_pressed_position: Option, is_dragging: bool, - cached_bounds: Rectangle, + _cached_bounds: Rectangle, } impl State { diff --git a/src/ui/slide_editor.rs b/src/ui/slide_editor.rs index 6119341..576cddb 100644 --- a/src/ui/slide_editor.rs +++ b/src/ui/slide_editor.rs @@ -13,13 +13,13 @@ use tracing::debug; #[derive(Debug, Default)] struct State { - cache: canvas::Cache, + _cache: canvas::Cache, } #[derive(Debug, Default)] pub struct SlideEditor { - state: State, - font: Font, + _state: State, + _font: Font, program: EditorProgram, } @@ -35,11 +35,11 @@ pub enum Message { } pub struct Text { - text: String, + _text: String, } pub struct Image { - source: PathBuf, + _source: PathBuf, } pub enum SlideWidget { @@ -55,7 +55,7 @@ pub enum SlideError { #[derive(Debug, Default)] struct EditorProgram { - mouse_button_pressed: Option, + _mouse_button_pressed: Option, } impl SlideEditor { diff --git a/src/ui/song_editor.rs b/src/ui/song_editor.rs index 3084f6d..db4a0af 100644 --- a/src/ui/song_editor.rs +++ b/src/ui/song_editor.rs @@ -85,7 +85,7 @@ pub struct SongEditor { video: Option