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
This commit is contained in:
Chris Cochrun 2026-02-17 14:22:34 -06:00
parent d77205cdec
commit c6ae2a0fbd
5 changed files with 84 additions and 51 deletions

View file

@ -0,0 +1,6 @@
-- Add migration script here
ALTER TABLE songs
ADD COLUMN weight TEXT;
ALTER TABLE songs
ADD COLUMN style TEXT;

View file

@ -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::<Option<Style>>(&style_string)
.ok()
.flatten();
let weight_string: String = row.try_get("weight")?;
let font_weight =
ron::de::from_str::<Option<Weight>>(&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<Song> {
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<Song> {
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

View file

@ -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::<u16>()
.expect("these are fine")
== size
},
)
})
song.stroke_size
.and_then(|size| {
self.stroke_sizes.iter().position(
|size_string| {
size_string
.parse::<u16>()
.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::<u16>()
.expect("these are fine")
== size
song.shadow_size
.and_then(|size| {
self.shadow_sizes.iter().position(
|size_string| {
size_string
.parse::<u16>()
.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<Message> {
fn update_song(&mut self, song: &Song) -> Task<Message> {
// 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)
}

View file

@ -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);

BIN
test.db

Binary file not shown.