starting to make db universal across app
This commit is contained in:
parent
804850505e
commit
d1ae7ba4f5
|
@ -9,7 +9,7 @@ use super::{
|
|||
use crisp::types::{Keyword, Symbol, Value};
|
||||
use miette::{IntoDiagnostic, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{query_as, SqliteConnection};
|
||||
use sqlx::{query_as, SqliteConnection, SqlitePool};
|
||||
use std::path::PathBuf;
|
||||
use tracing::error;
|
||||
|
||||
|
@ -125,13 +125,15 @@ impl ServiceTrait for Image {
|
|||
}
|
||||
|
||||
impl Model<Image> {
|
||||
pub async fn new_image_model(db: &mut SqliteConnection) -> Self {
|
||||
pub async fn new_image_model(db: &mut SqlitePool) -> Self {
|
||||
let mut model = Self {
|
||||
items: vec![],
|
||||
kind: LibraryKind::Image,
|
||||
};
|
||||
|
||||
model.load_from_db(db).await;
|
||||
let mut db = db.acquire().await.expect("probs");
|
||||
|
||||
model.load_from_db(&mut db).await;
|
||||
model
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@ use crisp::types::{Keyword, Symbol, Value};
|
|||
use miette::{IntoDiagnostic, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{
|
||||
prelude::FromRow, query, sqlite::SqliteRow, Row, SqliteConnection,
|
||||
prelude::FromRow, query, sqlite::SqliteRow, Row,
|
||||
SqliteConnection, SqlitePool,
|
||||
};
|
||||
use std::path::PathBuf;
|
||||
use tracing::error;
|
||||
|
@ -166,15 +167,14 @@ impl FromRow<'_, SqliteRow> for Presentation {
|
|||
}
|
||||
|
||||
impl Model<Presentation> {
|
||||
pub async fn new_presentation_model(
|
||||
db: &mut SqliteConnection,
|
||||
) -> Self {
|
||||
pub async fn new_presentation_model(db: &mut SqlitePool) -> Self {
|
||||
let mut model = Self {
|
||||
items: vec![],
|
||||
kind: LibraryKind::Presentation,
|
||||
};
|
||||
let mut db = db.acquire().await.expect("probs");
|
||||
|
||||
model.load_from_db(db).await;
|
||||
model.load_from_db(&mut db).await;
|
||||
model
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use miette::{miette, IntoDiagnostic, Result};
|
|||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{
|
||||
query, sqlite::SqliteRow, FromRow, Row, SqliteConnection,
|
||||
SqlitePool,
|
||||
};
|
||||
use tracing::{debug, error};
|
||||
|
||||
|
@ -380,25 +381,68 @@ impl Model<Song> {
|
|||
index: i32,
|
||||
db: &mut SqliteConnection,
|
||||
) -> Result<()> {
|
||||
self.update_item(item, index)?;
|
||||
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 = {} WHERE id = {}"#,
|
||||
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.id
|
||||
item.lyrics,
|
||||
item.author,
|
||||
item.ccli,
|
||||
verse_order,
|
||||
audio,
|
||||
item.font,
|
||||
item.font_size,
|
||||
background
|
||||
)
|
||||
.fetch_one(db)
|
||||
.await?;
|
||||
.execute(db)
|
||||
.await
|
||||
.into_diagnostic()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub async fn new_song_model(db: &mut SqliteConnection) -> Self {
|
||||
pub async fn new_song_model(db: &mut SqlitePool) -> Self {
|
||||
let mut model = Self {
|
||||
items: vec![],
|
||||
kind: LibraryKind::Song,
|
||||
};
|
||||
let mut db = db.acquire().await.expect("probs");
|
||||
|
||||
model.load_from_db(db).await;
|
||||
model.load_from_db(&mut db).await;
|
||||
model
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ use cosmic::iced::Executor;
|
|||
use crisp::types::{Keyword, Symbol, Value};
|
||||
use miette::{IntoDiagnostic, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{query_as, SqliteConnection};
|
||||
use sqlx::{query_as, SqliteConnection, SqlitePool};
|
||||
use std::path::PathBuf;
|
||||
use tracing::error;
|
||||
|
||||
|
@ -170,13 +170,14 @@ impl ServiceTrait for Video {
|
|||
}
|
||||
|
||||
impl Model<Video> {
|
||||
pub async fn new_video_model(db: &mut SqliteConnection) -> Self {
|
||||
pub async fn new_video_model(db: &mut SqlitePool) -> Self {
|
||||
let mut model = Self {
|
||||
items: vec![],
|
||||
kind: LibraryKind::Video,
|
||||
};
|
||||
let mut db = db.acquire().await.expect("probs");
|
||||
|
||||
model.load_from_db(db).await;
|
||||
model.load_from_db(&mut db).await;
|
||||
model
|
||||
}
|
||||
|
||||
|
|
95
src/main.rs
95
src/main.rs
|
@ -1,5 +1,5 @@
|
|||
use clap::{command, Parser};
|
||||
use core::model::LibraryKind;
|
||||
use core::model::{get_db, LibraryKind};
|
||||
use core::service_items::{ServiceItem, ServiceItemModel};
|
||||
use core::slide::*;
|
||||
use cosmic::app::context_drawer::ContextDrawer;
|
||||
|
@ -27,6 +27,7 @@ use cosmic::{widget::Container, Theme};
|
|||
use crisp::types::Value;
|
||||
use lisp::parse_lisp;
|
||||
use miette::{miette, Result};
|
||||
use sqlx::{SqliteConnection, SqlitePool};
|
||||
use std::fs::read_to_string;
|
||||
use std::path::PathBuf;
|
||||
use tracing::{debug, level_filters::LevelFilter};
|
||||
|
@ -417,60 +418,34 @@ impl cosmic::Application for App {
|
|||
}
|
||||
Message::SongEditor(message) => {
|
||||
debug!(?message);
|
||||
match message {
|
||||
song_editor::Message::ChangeFont(ref font) => {
|
||||
if let Some(mut song) =
|
||||
let library_task = if let Some(mut song) =
|
||||
self.song_editor.song.clone()
|
||||
{
|
||||
match message {
|
||||
song_editor::Message::ChangeFont(
|
||||
ref font,
|
||||
) => {
|
||||
song.font = Some(font.to_string());
|
||||
self.song_editor.song =
|
||||
Some(song.clone());
|
||||
if let Some(library) = &mut self.library {
|
||||
match library.update_song(song) {
|
||||
Ok(_) => (),
|
||||
Err(e) => error!(?e),
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
song_editor::Message::ChangeFontSize(
|
||||
font_size,
|
||||
) => {
|
||||
if let Some(mut song) =
|
||||
self.song_editor.song.clone()
|
||||
{
|
||||
song.font_size = Some(font_size as i32);
|
||||
self.song_editor.song =
|
||||
Some(song.clone());
|
||||
if let Some(library) = &mut self.library {
|
||||
match library.update_song(song) {
|
||||
Ok(_) => (),
|
||||
Err(e) => error!(?e),
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
song_editor::Message::ChangeTitle(ref title) => {
|
||||
if let Some(mut song) =
|
||||
self.song_editor.song.clone()
|
||||
{
|
||||
song_editor::Message::ChangeTitle(
|
||||
ref title,
|
||||
) => {
|
||||
song.title = title.to_string();
|
||||
self.song_editor.song =
|
||||
Some(song.clone());
|
||||
if let Some(library) = &mut self.library {
|
||||
match library.update_song(song) {
|
||||
Ok(_) => (),
|
||||
Err(e) => error!(?e),
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
song_editor::Message::ChangeVerseOrder(
|
||||
ref vo,
|
||||
) => {
|
||||
if let Some(mut song) =
|
||||
self.song_editor.song.clone()
|
||||
{
|
||||
let verse_order = vo
|
||||
.split(" ")
|
||||
.into_iter()
|
||||
|
@ -479,13 +454,6 @@ impl cosmic::Application for App {
|
|||
song.verse_order = Some(verse_order);
|
||||
self.song_editor.song =
|
||||
Some(song.clone());
|
||||
if let Some(library) = &mut self.library {
|
||||
match library.update_song(song) {
|
||||
Ok(_) => (),
|
||||
Err(e) => error!(?e),
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
song_editor::Message::ChangeLyrics(
|
||||
ref action,
|
||||
|
@ -493,45 +461,42 @@ impl cosmic::Application for App {
|
|||
self.song_editor
|
||||
.lyrics
|
||||
.perform(action.clone());
|
||||
let lyrics = self.song_editor.lyrics.text();
|
||||
if let Some(mut song) =
|
||||
self.song_editor.song.clone()
|
||||
{
|
||||
let lyrics =
|
||||
self.song_editor.lyrics.text();
|
||||
song.lyrics = Some(lyrics.to_string());
|
||||
self.song_editor.song =
|
||||
Some(song.clone());
|
||||
if let Some(library) = &mut self.library {
|
||||
match library.update_song(song) {
|
||||
Ok(_) => (),
|
||||
Err(e) => error!(?e),
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
song_editor::Message::ChangeAuthor(
|
||||
ref author,
|
||||
) => {
|
||||
if let Some(mut song) =
|
||||
self.song_editor.song.clone()
|
||||
{
|
||||
song.author = Some(author.to_string());
|
||||
self.song_editor.song =
|
||||
Some(song.clone());
|
||||
if let Some(library) = &mut self.library {
|
||||
match library.update_song(song) {
|
||||
Ok(_) => (),
|
||||
Err(e) => error!(?e),
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
song_editor::Message::Edit(_) => todo!(),
|
||||
_ => (),
|
||||
};
|
||||
|
||||
if let Some(library) = &mut self.library {
|
||||
let task = library.update(
|
||||
library::Message::UpdateSong(song),
|
||||
);
|
||||
task.map(|m| {
|
||||
cosmic::app::Message::App(Message::None)
|
||||
})
|
||||
} else {
|
||||
Task::none()
|
||||
}
|
||||
} else {
|
||||
Task::none()
|
||||
};
|
||||
let song_editor_task =
|
||||
self.song_editor.update(message).map(|m| {
|
||||
debug!(?m);
|
||||
cosmic::app::Message::App(Message::None)
|
||||
})
|
||||
});
|
||||
Task::batch(vec![song_editor_task, library_task])
|
||||
}
|
||||
Message::Present(message) => {
|
||||
// debug!(?message);
|
||||
|
@ -853,7 +818,7 @@ where
|
|||
}
|
||||
|
||||
fn add_library(&mut self) -> Task<Message> {
|
||||
Task::perform(async { Library::new().await }, |x| {
|
||||
Task::perform(async move { Library::new().await }, |x| {
|
||||
cosmic::app::Message::App(Message::AddLibrary(x))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
use cosmic::{
|
||||
iced::{alignment::Vertical, Background, Border, Length},
|
||||
iced_core::widget::tree,
|
||||
iced_widget::{column, row as rowm, text as textm},
|
||||
theme,
|
||||
widget::{
|
||||
container, horizontal_space, icon, mouse_area, responsive,
|
||||
row, scrollable, text, Container, DndSource, Space, Widget,
|
||||
},
|
||||
Element, Task,
|
||||
};
|
||||
use miette::{miette, Result};
|
||||
use tracing::debug;
|
||||
use miette::{miette, IntoDiagnostic, Result};
|
||||
use sqlx::{SqliteConnection, SqlitePool};
|
||||
use tracing::{debug, error};
|
||||
|
||||
use crate::core::{
|
||||
content::Content,
|
||||
images::Image,
|
||||
model::{get_db, LibraryKind, Model},
|
||||
model::{LibraryKind, Model},
|
||||
presentations::Presentation,
|
||||
service_items::ServiceItem,
|
||||
songs::Song,
|
||||
|
@ -34,6 +33,7 @@ pub(crate) struct Library {
|
|||
hovered_item: Option<(LibraryKind, i32)>,
|
||||
dragged_item: Option<(LibraryKind, i32)>,
|
||||
editing_item: Option<(LibraryKind, i32)>,
|
||||
db: SqlitePool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -45,12 +45,13 @@ pub(crate) enum Message {
|
|||
OpenLibrary(Option<LibraryKind>),
|
||||
HoverItem(Option<(LibraryKind, i32)>),
|
||||
SelectItem(Option<(LibraryKind, i32)>),
|
||||
UpdateSong(Song),
|
||||
None,
|
||||
}
|
||||
|
||||
impl Library {
|
||||
impl<'a> Library {
|
||||
pub async fn new() -> Self {
|
||||
let mut db = get_db().await;
|
||||
let mut db = add_db().await.expect("probs");
|
||||
Self {
|
||||
song_library: Model::new_song_model(&mut db).await,
|
||||
image_library: Model::new_image_model(&mut db).await,
|
||||
|
@ -65,6 +66,7 @@ impl Library {
|
|||
hovered_item: None,
|
||||
dragged_item: None,
|
||||
editing_item: None,
|
||||
db,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +74,7 @@ impl Library {
|
|||
self.song_library.get_item(index)
|
||||
}
|
||||
|
||||
pub fn update(&mut self, message: Message) -> Task<Message> {
|
||||
pub fn update(&'a mut self, message: Message) -> Task<Message> {
|
||||
match message {
|
||||
Message::AddItem => Task::none(),
|
||||
Message::None => Task::none(),
|
||||
|
@ -98,6 +100,33 @@ impl Library {
|
|||
self.selected_item = item;
|
||||
Task::none()
|
||||
}
|
||||
Message::UpdateSong(song) => {
|
||||
let Some((kind, index)) = self.editing_item else {
|
||||
error!("Not editing an item");
|
||||
return Task::none();
|
||||
};
|
||||
|
||||
if kind != LibraryKind::Song {
|
||||
error!("Not editing a song item");
|
||||
return Task::none();
|
||||
}
|
||||
let mut db = self.db.clone();
|
||||
let mut song_library = self.song_library.clone();
|
||||
|
||||
let future = update_song(
|
||||
song,
|
||||
index as usize,
|
||||
&mut db,
|
||||
&mut song_library,
|
||||
);
|
||||
Task::perform(future, |r| {
|
||||
match r {
|
||||
Ok(_) => (),
|
||||
Err(e) => error!(?e),
|
||||
};
|
||||
Message::None
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,7 +145,7 @@ impl Library {
|
|||
column.height(Length::Fill).spacing(5).into()
|
||||
}
|
||||
|
||||
pub fn library_item<'a, T>(
|
||||
pub fn library_item<T>(
|
||||
&'a self,
|
||||
model: &'a Model<T>,
|
||||
) -> Element<'a, Message>
|
||||
|
@ -257,7 +286,7 @@ impl Library {
|
|||
column![button, lib_container].into()
|
||||
}
|
||||
|
||||
fn single_item<'a, T>(
|
||||
fn single_item<T>(
|
||||
&'a self,
|
||||
index: usize,
|
||||
item: &'a T,
|
||||
|
@ -342,7 +371,10 @@ impl Library {
|
|||
.into()
|
||||
}
|
||||
|
||||
pub(crate) fn update_song(&mut self, song: Song) -> Result<()> {
|
||||
pub(crate) async fn update_song(
|
||||
&'a mut self,
|
||||
song: Song,
|
||||
) -> Result<()> {
|
||||
let Some((kind, index)) = self.editing_item else {
|
||||
return Err(miette!("Not editing an item"));
|
||||
};
|
||||
|
@ -352,7 +384,11 @@ impl Library {
|
|||
}
|
||||
|
||||
if let Some(_) = self.song_library.items.get(index as usize) {
|
||||
self.song_library.update_item(song, index);
|
||||
let mut db = self.db.acquire().await.expect("probs");
|
||||
|
||||
self.song_library
|
||||
.update_song(song, index, &mut db)
|
||||
.await?;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(miette!("Song not found"))
|
||||
|
@ -360,6 +396,32 @@ impl Library {
|
|||
}
|
||||
}
|
||||
|
||||
async fn add_db() -> Result<SqlitePool> {
|
||||
let mut data = dirs::data_local_dir().unwrap();
|
||||
data.push("lumina");
|
||||
data.push("library-db.sqlite3");
|
||||
let mut db_url = String::from("sqlite://");
|
||||
db_url.push_str(data.to_str().unwrap());
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue