use crate::{Background, SlideBuilder, TextAlignment}; use super::{ model::Model, service_items::ServiceTrait, slide::Slide, }; use cosmic::iced::Executor; use crisp::types::{Keyword, Value}; use miette::{IntoDiagnostic, Result}; use serde::{Deserialize, Serialize}; use sqlx::{query_as, SqliteConnection}; use std::path::PathBuf; use tracing::error; #[derive( Clone, Debug, Default, PartialEq, Serialize, Deserialize, )] pub struct Video { pub id: i32, pub title: String, pub path: PathBuf, pub start_time: Option, pub end_time: Option, pub looping: bool, } impl From for Video { fn from(value: Value) -> Self { Self::from(&value) } } impl From<&Value> for Video { fn from(value: &Value) -> Self { 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" }) .unwrap_or_default() } else { false }; Self { title: title.unwrap_or_default(), path: path.unwrap_or_default(), start_time, end_time, looping, ..Default::default() } } _ => todo!(), } } } impl ServiceTrait for Video { fn title(&self) -> String { self.title.clone() } fn id(&self) -> i32 { self.id } fn to_slides(&self) -> Result> { let slide = SlideBuilder::new() .background( Background::try_from(self.path.clone()) .into_diagnostic()?, ) .text("") .audio("") .font("") .font_size(50) .text_alignment(TextAlignment::MiddleCenter) .video_loop(self.looping) .video_start_time(self.start_time.unwrap_or(0.0)) .video_end_time(self.end_time.unwrap_or(0.0)) .build()?; Ok(vec![slide]) } fn box_clone(&self) -> Box { Box::new((*self).clone()) } } impl Model