updating songs now works

This commit is contained in:
Chris Cochrun 2025-03-08 22:35:18 -06:00
parent 95fb1d86d8
commit 49e1e767c3
5 changed files with 110 additions and 56 deletions

3
Cargo.lock generated
View file

@ -5498,6 +5498,8 @@ dependencies = [
"sha2",
"smallvec",
"thiserror 2.0.11",
"tokio",
"tokio-stream",
"tracing",
"url",
]
@ -5537,6 +5539,7 @@ dependencies = [
"sqlx-sqlite",
"syn 2.0.98",
"tempfile",
"tokio",
"url",
]

View file

@ -20,7 +20,7 @@ iced_video_player = { git = "https://github.com/jackpot51/iced_video_player", br
strum = "0.26.3"
strum_macros = "0.26.4"
ron = "0.8.1"
sqlx = { version = "0.8.2", features = ["sqlite"] }
sqlx = { version = "0.8.2", features = ["sqlite", "runtime-tokio"] }
dirs = "5.0.1"
tokio = "1.41.1"
crisp = { git = "https://git.tfcconnection.org/chris/crisp", version = "0.1.3" }

View file

@ -5,8 +5,8 @@ use crisp::types::{Keyword, Symbol, Value};
use miette::{miette, IntoDiagnostic, Result};
use serde::{Deserialize, Serialize};
use sqlx::{
query, sqlite::SqliteRow, FromRow, Row, SqliteConnection,
SqlitePool,
pool::PoolConnection, query, sqlite::SqliteRow, FromRow, Row,
Sqlite, SqliteConnection, SqlitePool,
};
use tracing::{debug, error};
@ -375,13 +375,12 @@ pub async fn get_song_from_db(
}
impl Model<Song> {
pub async fn update_song(
pub async fn update_song_in_db(
&mut self,
item: Song,
index: i32,
db: &mut SqliteConnection,
) -> Result<()> {
self.update_item(item.clone(), index)?;
// self.update_item(item.clone(), index)?;
let verse_order = {
if let Some(vo) = item.verse_order {
@ -469,6 +468,65 @@ impl Model<Song> {
}
}
pub async fn update_song_in_db<'a>(
item: Song,
db: PoolConnection<Sqlite>,
) -> Result<()> {
// self.update_item(item.clone(), index)?;
let verse_order = {
if let Some(vo) = item.verse_order {
vo.into_iter()
.map(|mut s| {
s.push_str(" ");
s
})
.collect::<String>()
} else {
String::from("")
}
};
let audio = item
.audio
.map(|a| a.to_str().unwrap_or_default().to_string());
let background = item
.background
.map(|b| b.path.to_str().unwrap_or_default().to_string());
// let text_alignment = item.text_alignment.map(|ta| match ta {
// TextAlignment::TopLeft => todo!(),
// TextAlignment::TopCenter => todo!(),
// TextAlignment::TopRight => todo!(),
// TextAlignment::MiddleLeft => todo!(),
// TextAlignment::MiddleCenter => todo!(),
// TextAlignment::MiddleRight => todo!(),
// TextAlignment::BottomLeft => todo!(),
// TextAlignment::BottomCenter => todo!(),
// TextAlignment::BottomRight => todo!(),
// })
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 WHERE id = $1"#,
item.id,
item.title,
item.lyrics,
item.author,
item.ccli,
verse_order,
audio,
item.font,
item.font_size,
background
)
.execute(&mut db.detach())
.await
.into_diagnostic()?;
Ok(())
}
impl Song {
pub fn get_lyrics(&self) -> Result<Vec<String>> {
let mut lyric_list = Vec::new();

View file

@ -1,5 +1,8 @@
use cosmic::{
iced::{alignment::Vertical, Background, Border, Length},
iced::{
alignment::Vertical, futures::FutureExt, Background, Border,
Length,
},
iced_widget::{column, row as rowm, text as textm},
widget::{
container, horizontal_space, icon, mouse_area, responsive,
@ -17,7 +20,7 @@ use crate::core::{
model::{LibraryKind, Model},
presentations::Presentation,
service_items::ServiceItem,
songs::Song,
songs::{update_song_in_db, Song},
videos::Video,
};
@ -46,6 +49,8 @@ pub(crate) enum Message {
HoverItem(Option<(LibraryKind, i32)>),
SelectItem(Option<(LibraryKind, i32)>),
UpdateSong(Song),
SongChanged,
Error(String),
None,
}
@ -101,15 +106,42 @@ impl<'a> Library {
Task::none()
}
Message::UpdateSong(song) => {
let future = self.update_song(song);
Task::perform(future, |r| {
match r {
Ok(_) => (),
Err(e) => error!(?e),
let Some((kind, index)) = self.editing_item else {
error!("Not editing an item");
return Task::none();
};
Message::None
})
if kind != LibraryKind::Song {
error!("Not editing a song item");
return Task::none();
};
match self
.song_library
.update_item(song.clone(), index)
{
Ok(_) => Task::future(self.db.acquire())
.and_then(move |conn| {
Task::perform(
update_song_in_db(song.clone(), conn)
.map(|r| match r {
Ok(_) => {}
Err(e) => {
error!(?e);
}
}),
|_| Message::SongChanged,
)
}),
Err(_) => todo!(),
}
}
Message::SongChanged => {
// self.song_library.update_item(song, index);
debug!("song changed");
Task::none()
}
Message::Error(_) => todo!(),
}
}
@ -353,29 +385,6 @@ impl<'a> Library {
})
.into()
}
pub async fn update_song<'b>(
&'b mut self,
song: Song,
) -> Result<()> {
let Some((kind, index)) = self.editing_item else {
return Err(miette!("Not editing an item"));
};
if kind != LibraryKind::Song {
return Err(miette!("Not editing a song item"));
}
let mut db = self.db.acquire().await.expect("foo");
if let Some(_) = self.song_library.items.get(index as usize) {
self.song_library
.update_song(song, index, &mut db)
.await?;
Ok(())
} else {
Err(miette!("Song not found"))
}
}
}
async fn add_db() -> Result<SqlitePool> {
@ -387,23 +396,6 @@ async fn add_db() -> Result<SqlitePool> {
SqlitePool::connect(&db_url).await.into_diagnostic()
}
pub(crate) async fn update_song(
song: Song,
index: usize,
db: &mut SqlitePool,
song_library: &mut Model<Song>,
) -> Result<()> {
if let Some(_) = song_library.items.get(index) {
let mut db = db.acquire().await.expect("foo");
song_library
.update_song(song, index as i32, &mut db)
.await?;
Ok(())
} else {
Err(miette!("Song not found"))
}
}
fn elide_text(text: String, width: f32) -> String {
const CHAR_SIZE: f32 = 8.0;
let text_length = text.len() as f32 * CHAR_SIZE;

View file

@ -1,3 +1,4 @@
pub mod double_ended_slider;
pub mod library;
pub mod presenter;
pub mod song_editor;