From c6ae2a0fbda152cd28c23423ff073866ada3536b Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Tue, 17 Feb 2026 14:22:34 -0600 Subject: [PATCH] updating db to allow for changing the style and weight of the font Also, fixed a bug in showing the stroke and shadow size if set to 0 --- ...260217193356_add_text_weight_and_style.sql | 6 ++ src/core/songs.rs | 29 +++++- src/ui/song_editor.rs | 94 ++++++++++-------- src/ui/text_svg.rs | 6 +- test.db | Bin 69632 -> 69632 bytes 5 files changed, 84 insertions(+), 51 deletions(-) create mode 100644 migrations/20260217193356_add_text_weight_and_style.sql diff --git a/migrations/20260217193356_add_text_weight_and_style.sql b/migrations/20260217193356_add_text_weight_and_style.sql new file mode 100644 index 0000000..ce3f306 --- /dev/null +++ b/migrations/20260217193356_add_text_weight_and_style.sql @@ -0,0 +1,6 @@ +-- Add migration script here +ALTER TABLE songs +ADD COLUMN weight TEXT; + +ALTER TABLE songs +ADD COLUMN style TEXT; diff --git a/src/core/songs.rs b/src/core/songs.rs index 0086c59..79fd7ff 100644 --- a/src/core/songs.rs +++ b/src/core/songs.rs @@ -436,6 +436,18 @@ impl FromRow<'_, SqliteRow> for Song { _ => None, }; + let style_string: String = row.try_get("style")?; + let font_style = + ron::de::from_str::>(&style_string) + .ok() + .flatten(); + + let weight_string: String = row.try_get("weight")?; + let font_weight = + ron::de::from_str::>(&weight_string) + .ok() + .flatten(); + Ok(Self { id: row.try_get("id")?, title: row.try_get("title")?, @@ -479,6 +491,8 @@ impl FromRow<'_, SqliteRow> for Song { }), font: row.try_get("font")?, font_size: row.try_get("font_size")?, + font_style, + font_weight, stroke_size, stroke_color, shadow_size, @@ -698,7 +712,7 @@ pub async fn get_song_from_db( index: i32, db: &mut SqliteConnection, ) -> Result { - let row = query("SELECT verse_order, font_size, background_type, horizontal_text_alignment, vertical_text_alignment, title, font, background, lyrics, ccli, author, audio, stroke_size, stroke_color, shadow_color, shadow_size, shadow_offset_x, shadow_offset_y, id from songs where id = $1").bind(index).fetch_one(db).await.into_diagnostic()?; + let row = query("SELECT verse_order, font_size, background_type, horizontal_text_alignment, vertical_text_alignment, title, font, background, lyrics, ccli, author, audio, stroke_size, stroke_color, shadow_color, shadow_size, shadow_offset_x, shadow_offset_y, style, weight, id from songs where id = $1").bind(index).fetch_one(db).await.into_diagnostic()?; Song::from_row(&row).into_diagnostic() } @@ -716,7 +730,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.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; + 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, style, weight, id from songs").fetch_all(&mut db1.detach()).await; match result { Ok(s) => { for song in s { @@ -854,6 +868,11 @@ pub async fn update_song_in_db( let shadow_color = ron::ser::to_string(&item.shadow_color).into_diagnostic()?; + let style = + ron::ser::to_string(&item.font_style).into_diagnostic()?; + let weight = + ron::ser::to_string(&item.font_weight).into_diagnostic()?; + // debug!( // ?stroke_size, // ?stroke_color, @@ -864,7 +883,7 @@ 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 WHERE id = $1"#, + 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, lyrics, @@ -882,7 +901,9 @@ pub async fn update_song_in_db( stroke_size, shadow_size, shadow_offset_x, - shadow_offset_y + shadow_offset_y, + style, + weight ) .execute(&mut db.detach()) .await diff --git a/src/ui/song_editor.rs b/src/ui/song_editor.rs index db4a0af..81780b5 100644 --- a/src/ui/song_editor.rs +++ b/src/ui/song_editor.rs @@ -447,7 +447,7 @@ impl SongEditor { if let Some(song) = &mut self.song { song.font = Some(font.0.families[0].0.clone()); let song = song.to_owned(); - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } Message::ChangeFontStyle => { @@ -466,7 +466,7 @@ impl SongEditor { song.font_style = Some(Style::Italic); } let song = song.clone(); - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } Message::ChangeFontWeight => { @@ -485,7 +485,7 @@ impl SongEditor { song.font_weight = Some(Weight::Bold); } let song = song.clone(); - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } Message::ChangeFontSize(size) => { @@ -494,7 +494,7 @@ impl SongEditor { if let Some(song) = &mut self.song { song.font_size = i32::try_from(size).ok(); let song = song.to_owned(); - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } } @@ -503,7 +503,7 @@ impl SongEditor { if let Some(song) = &mut self.song { song.title = title; let song = song.to_owned(); - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } Message::ChangeVerseOrder(verse_order) => { @@ -514,7 +514,7 @@ impl SongEditor { .map(std::borrow::ToOwned::to_owned) .collect(); song.verse_order = Some(verse_order); - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } Message::ChangeLyrics(action) => { @@ -524,7 +524,7 @@ impl SongEditor { if let Some(mut song) = self.song.clone() { song.lyrics = Some(lyrics); - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } Message::Edit(edit) => { @@ -536,7 +536,7 @@ impl SongEditor { self.author.clone_from(&author); if let Some(mut song) = self.song.clone() { song.author = Some(author); - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } Message::ChangeBackground(Ok(path)) => { @@ -545,7 +545,7 @@ impl SongEditor { let background = Background::try_from(path).ok(); self.background_video(background.as_ref()); song.background = background; - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } Message::ChangeBackground(Err(error)) => { @@ -571,7 +571,7 @@ impl SongEditor { song.stroke_size = if size == 0 { None } else { Some(size) }; let song = song.to_owned(); - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } Message::UpdateStrokeColor(update) => { @@ -583,7 +583,7 @@ impl SongEditor { { debug!(?color); song.stroke_color = Some(color.into()); - tasks.push(self.update_song(song)); + tasks.push(self.update_song(&song)); } return Action::Task(Task::batch(tasks)); } @@ -657,7 +657,7 @@ impl SongEditor { ); return Action::Task( - self.update_song(song), + self.update_song(&song), ); } } @@ -672,7 +672,7 @@ impl SongEditor { // index, verse, lyric, // ); return Action::Task( - self.update_song(song), + self.update_song(&song), ); } } @@ -692,7 +692,7 @@ impl SongEditor { verses.remove(verse); } return Action::Task( - self.update_song(song), + self.update_song(&song), ); } } @@ -716,7 +716,7 @@ impl SongEditor { } if let Some(mut song) = self.song.clone() { song.add_verse(verse, lyric); - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } Message::RemoveVerse(index) => { @@ -727,7 +727,7 @@ impl SongEditor { verses.remove(index); }, ); - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } Message::ChipHovered(index) => { @@ -746,7 +746,7 @@ impl SongEditor { verses.insert(index, verse); let song = song.clone(); return Action::Task( - self.update_song(song), + self.update_song(&song), ); } error!("No verses in this song?"); @@ -769,7 +769,7 @@ impl SongEditor { verses.push(verse); let song = song.clone(); return Action::Task( - self.update_song(song), + self.update_song(&song), ); } error!( @@ -793,7 +793,7 @@ impl SongEditor { let verse = verses.remove(index); verses.insert(target_index, verse); debug!(?verses); - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } draggable::DragEvent::Picked { .. } @@ -808,7 +808,7 @@ impl SongEditor { Message::SetTextAlignment(alignment) => { if let Some(mut song) = self.song.clone() { song.text_alignment = Some(alignment); - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } Message::UpdateShadowSize(index) => { @@ -820,7 +820,7 @@ impl SongEditor { song.shadow_size = if size == 0 { None } else { Some(size) }; let song = song.to_owned(); - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } Message::UpdateShadowOffsetX(index) => { @@ -837,7 +837,7 @@ impl SongEditor { } else { song.shadow_offset = Some((x, 0)); } - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } Message::UpdateShadowOffsetY(index) => { @@ -854,7 +854,7 @@ impl SongEditor { } else { song.shadow_offset = Some((0, y)); } - return Action::Task(self.update_song(song)); + return Action::Task(self.update_song(&song)); } } Message::UpdateShadowColor(update) => { @@ -866,7 +866,7 @@ impl SongEditor { { debug!(?color); song.shadow_color = Some(color.into()); - tasks.push(self.update_song(song)); + tasks.push(self.update_song(&song)); } return Action::Task(Task::batch(tasks)); } @@ -1419,16 +1419,18 @@ impl SongEditor { dropdown( &self.stroke_sizes, self.song.as_ref().and_then(|song| { - song.stroke_size.and_then(|size| { - self.stroke_sizes.iter().position( - |size_string| { - size_string - .parse::() - .expect("these are fine") - == size - }, - ) - }) + song.stroke_size + .and_then(|size| { + self.stroke_sizes.iter().position( + |size_string| { + size_string + .parse::() + .expect("these are fine") + == size + }, + ) + }) + .map_or(Some(0), Some) }), Message::UpdateStrokeSize, ) @@ -1499,14 +1501,18 @@ impl SongEditor { let shadow_size_dropdown = dropdown( &self.shadow_sizes, self.song.as_ref().and_then(|song| { - song.shadow_size.and_then(|size| { - self.shadow_sizes.iter().position(|size_string| { - size_string - .parse::() - .expect("these are fine") - == size + song.shadow_size + .and_then(|size| { + self.shadow_sizes.iter().position( + |size_string| { + size_string + .parse::() + .expect("these are fine") + == size + }, + ) }) - }) + .map_or(Some(0), Some) }), Message::UpdateShadowSize, ) @@ -1533,7 +1539,7 @@ impl SongEditor { let shadow_offset_y_dropdown = dropdown( &self.shadow_offset_sizes, self.song.as_ref().and_then(|song| { - song.shadow_offset.and_then(|(offset_y, _)| { + song.shadow_offset.and_then(|(_, offset_y)| { self.shadow_offset_sizes.iter().position( |y_string| { y_string @@ -1801,7 +1807,7 @@ impl SongEditor { // fn update_verse_slide_subscription(&self) - fn update_song(&mut self, song: Song) -> Task { + fn update_song(&mut self, song: &Song) -> Task { // use cosmic::iced_futures::futures::stream; // use cosmic::iced_futures::futures::{Stream, StreamExt}; // use cosmic::iced_futures::stream::channel; @@ -1873,7 +1879,7 @@ impl SongEditor { self.update_slide_handle = Some(handle); tasks.push(task); } - tasks.push(Task::done(Message::UpdateSong(song))); + tasks.push(Task::done(Message::UpdateSong(song.clone()))); Task::batch(tasks) } diff --git a/src/ui/text_svg.rs b/src/ui/text_svg.rs index 6c5c4b5..8197c46 100644 --- a/src/ui/text_svg.rs +++ b/src/ui/text_svg.rs @@ -22,7 +22,7 @@ use resvg::{ usvg::{Tree, fontdb}, }; use serde::{Deserialize, Serialize}; -use tracing::{debug, error}; +use tracing::error; use crate::TextAlignment; @@ -580,7 +580,7 @@ pub fn text_svg_generator_with_cache( text_svg }; let text_svg = text_svg.font(font).fontdb(Arc::clone(fontdb)); - debug!(fill = ?text_svg.fill, font = ?text_svg.font, stroke = ?text_svg.stroke, shadow = ?text_svg.shadow, text = ?text_svg.text); + // debug!(fill = ?text_svg.fill, font = ?text_svg.font, stroke = ?text_svg.stroke, shadow = ?text_svg.shadow, text = ?text_svg.text); let text_svg = text_svg.build(Size::new(1280.0, 720.0), cache); slide.text_svg = Some(text_svg); @@ -598,7 +598,7 @@ mod tests { #[test] fn test_generator() { let slide = Slide::default(); - + debug!("test"); let mut fontdb = Database::new(); fontdb.load_system_fonts(); let fontdb = Arc::new(fontdb); diff --git a/test.db b/test.db index fc81009e9edbebba6e83ee2053a5930acabffc15..64f3fbf302265b9f733a9d777ae0a44c2960627d 100644 GIT binary patch delta 303 zcmZozz|ydQWrDOICj$e6AOiz~00RR9BLf42^h6zFNlpg6ssdhaNd`8KH4J>+{M$L! z@HBIEb5GpZXu`qO9K*~mE-ud4F24CZ$0|k%h4R$Q^o$aP5Z8zh9fjhO%A8a%dvXDf z$mSld3RVF&-T(&vCHzi&JNYzt_wfd7Rur(|t%GmJhoam>`dYz6zE4DwG7xnRK{ZXes*Os_8 zEq!$OUdWbyhqAjnw7RmFt=pukuyo?r){{!@q8Y60tmY8gj5e$jO-$K*Ue=UJfQ^4Y l1OGSv*ZdFoukxSb-@jSWU^PEC7c(m(#8qsYPwAUI008(ZU?Bhi delta 143 zcmZozz|ydQWrDOI2Ll6xAOiz~00RR9BLf42 z@-%aGb5Go?DB#P%)$Gj7E-o(4*p@muhPQ9C3#Sa@nP4e#cCvTjU#to)}K_`mVL=6}F{mH*UcMS~sullSYhZN8vy@BjeAlO_!S