ServiceItems are loaded from lisp and converted to slides

This commit is contained in:
Chris Cochrun 2024-12-10 12:07:10 -06:00
parent cb7fa372a9
commit db39eb12b8
9 changed files with 283 additions and 125 deletions

View file

@ -39,7 +39,11 @@ impl From<&Value> for Image {
};
let title = path.clone().map(|p| {
p.to_str().unwrap_or_default().to_string()
let path =
p.to_str().unwrap_or_default().to_string();
let title =
path.rsplit_once("/").unwrap_or_default().1;
title.to_string()
});
Self {
title: title.unwrap_or_default(),

View file

@ -16,7 +16,7 @@ pub enum ServiceItemKind {
Song(Song),
Video(Video),
Image(Image),
Presentation((Presentation, PresKind)),
Presentation(Presentation),
Content(Slide),
}
@ -26,7 +26,7 @@ impl std::fmt::Display for ServiceItemKind {
Self::Song(s) => "song".to_owned(),
Self::Image(i) => "image".to_owned(),
Self::Video(v) => "video".to_owned(),
Self::Presentation((p, k)) => "html".to_owned(),
Self::Presentation(p) => "html".to_owned(),
Self::Content(s) => "content".to_owned(),
};
write!(f, "{s}")

View file

@ -1,4 +1,4 @@
use crisp::types::Value;
use crisp::types::{Keyword, Value};
use miette::{miette, IntoDiagnostic, Result};
use serde::{Deserialize, Serialize};
use sqlx::{
@ -39,7 +39,30 @@ impl From<Value> for Presentation {
impl From<&Value> for Presentation {
fn from(value: &Value) -> Self {
todo!()
match value {
Value::List(list) => {
let path = if let Some(path_pos) =
list.iter().position(|v| {
v == &Value::Keyword(Keyword::from("source"))
}) {
let pos = path_pos + 1;
list.get(pos)
.map(|p| PathBuf::from(String::from(p)))
} else {
None
};
let title = path.clone().map(|p| {
p.to_str().unwrap_or_default().to_string()
});
Self {
title: title.unwrap_or_default(),
path: path.unwrap_or_default(),
..Default::default()
}
}
_ => todo!(),
}
}
}

View file

@ -1,6 +1,8 @@
use std::ops::Deref;
use crisp::types::{Keyword, Symbol, Value};
use miette::Result;
use tracing::error;
use tracing::{debug, error};
use crate::Slide;
@ -21,12 +23,16 @@ pub struct ServiceItem {
}
impl ServiceItem {
pub fn to_slide(&self) -> Result<Vec<Slide>> {
pub fn title(&self) -> String {
self.title.clone()
}
pub fn to_slides(&self) -> Result<Vec<Slide>> {
match &self.kind {
ServiceItemKind::Song(song) => song.to_slides(),
ServiceItemKind::Video(video) => video.to_slides(),
ServiceItemKind::Image(image) => image.to_slides(),
ServiceItemKind::Presentation((presentation, _)) => {
ServiceItemKind::Presentation(presentation) => {
presentation.to_slides()
}
ServiceItemKind::Content(slide) => {
@ -124,11 +130,27 @@ impl From<&Value> for ServiceItem {
}
}
#[derive(Debug, Default)]
#[derive(Debug, Default, Clone)]
pub struct ServiceItemModel {
items: Vec<ServiceItem>,
}
impl Deref for ServiceItemModel {
type Target = Vec<ServiceItem>;
fn deref(&self) -> &Self::Target {
&self.items
}
}
// impl Iterator for ServiceItemModel {
// type Item = ServiceItem;
// fn next(&mut self) -> Option<Self::Item> {
// *self.items.iter().next()
// }
// }
impl From<Vec<ServiceItem>> for ServiceItemModel {
fn from(items: Vec<ServiceItem>) -> Self {
Self { items }
@ -171,10 +193,7 @@ impl From<&Image> for ServiceItem {
impl From<&Presentation> for ServiceItem {
fn from(presentation: &Presentation) -> Self {
Self {
kind: ServiceItemKind::Presentation((
presentation.clone(),
presentation.kind.clone(),
)),
kind: ServiceItemKind::Presentation(presentation.clone()),
database_id: presentation.id,
title: presentation.title.clone(),
..Default::default()
@ -196,7 +215,11 @@ impl ServiceItemModel {
Ok(self
.items
.iter()
.filter_map(|item| item.to_slide().ok())
.filter_map(|item| {
let slides = item.to_slides().ok();
debug!(?slides);
slides
})
.flatten()
.collect::<Vec<Slide>>())
}
@ -251,26 +274,26 @@ mod test {
}
}
// #[test]
// pub fn test_service_item() {
// let song = test_song();
// let service_item = ServiceItem::from(&song);
// let pres = test_presentation();
// let pres_item = ServiceItem::from(&pres);
// let mut service_model = ServiceItemModel::default();
// match service_model.add_item(&song) {
// Ok(_) => {
// assert_eq!(
// ServiceItemKind::Song,
// service_model.items[0].kind
// );
// assert_eq!(
// ServiceItemKind::Presentation(PresKind::Html),
// pres_item.kind
// );
// assert_eq!(service_item, service_model.items[0]);
// }
// Err(e) => panic!("Problem adding item: {:?}", e),
// }
// }
#[test]
pub fn test_service_item() {
let song = test_song();
let service_item = ServiceItem::from(&song);
let pres = test_presentation();
let pres_item = ServiceItem::from(&pres);
let mut service_model = ServiceItemModel::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),
}
}
}

View file

@ -60,8 +60,22 @@ impl TryFrom<String> for Background {
impl TryFrom<PathBuf> for Background {
type Error = ParseError;
fn try_from(value: PathBuf) -> Result<Self, Self::Error> {
match value.canonicalize() {
fn try_from(path: PathBuf) -> Result<Self, Self::Error> {
let path = if path.starts_with("~") {
let path = path.to_str().unwrap().to_string();
let path = path.trim_start_matches("file://");
let home = dirs::home_dir()
.unwrap()
.to_str()
.unwrap()
.to_string();
let path = path.replace("~", &home);
PathBuf::from(path)
} else {
path
};
match path.canonicalize() {
Ok(value) => {
let extension = value
.extension()
@ -83,7 +97,7 @@ impl TryFrom<PathBuf> for Background {
}
}
Err(e) => {
error!("Couldn't canonicalize: {e}");
error!("Couldn't canonicalize: {e} {:?}", path);
Err(ParseError::CannotCanonicalize)
}
}

View file

@ -4,7 +4,7 @@ use super::{
model::Model, service_items::ServiceTrait, slide::Slide,
};
use cosmic::{executor, iced::Executor};
use crisp::types::Value;
use crisp::types::{Keyword, Value};
use miette::{miette, IntoDiagnostic, Result};
use serde::{Deserialize, Serialize};
use sqlx::{query_as, SqliteConnection};
@ -31,7 +31,76 @@ impl From<Value> for Video {
impl From<&Value> for Video {
fn from(value: &Value) -> Self {
todo!()
match value {
Value::List(list) => {
let path = if let Some(path_pos) =
list.iter().position(|v| {
v == &Value::Keyword(Keyword::from("source"))
}) {
let pos = path_pos + 1;
list.get(pos)
.map(|p| PathBuf::from(String::from(p)))
} else {
None
};
let title = path.clone().map(|p| {
let path =
p.to_str().unwrap_or_default().to_string();
let title =
path.rsplit_once("/").unwrap_or_default().1;
title.to_string()
});
let start_time = if let Some(start_pos) =
list.iter().position(|v| {
v == &Value::Keyword(Keyword::from(
"start-time",
))
}) {
let pos = start_pos + 1;
list.get(pos).map(|p| i32::from(p) as f32)
} else {
None
};
let end_time = if let Some(end_pos) =
list.iter().position(|v| {
v == &Value::Keyword(Keyword::from(
"end-time",
))
}) {
let pos = end_pos + 1;
list.get(pos).map(|p| i32::from(p) as f32)
} else {
None
};
let looping = if let Some(loop_pos) =
list.iter().position(|v| {
v == &Value::Keyword(Keyword::from("loop"))
}) {
let pos = loop_pos + 1;
list.get(pos)
.map(|l| {
String::from(l) == "true".to_string()
})
.unwrap_or_default()
} else {
false
};
Self {
title: title.unwrap_or_default(),
path: path.unwrap_or_default(),
start_time,
end_time,
looping,
..Default::default()
}
}
_ => todo!(),
}
}
}