moving the lisp presentation parsing to service_items
Since we need the nav_bar to have the ServiceItemModel, the presentation needs to be a list of service items, not slides, each service item will have a list of slides attached though.
This commit is contained in:
parent
9eb5bec320
commit
cb7fa372a9
|
@ -1,4 +1,7 @@
|
|||
use super::model::Model;
|
||||
use crate::{Background, Slide, SlideBuilder, TextAlignment};
|
||||
|
||||
use super::{model::Model, service_items::ServiceTrait};
|
||||
use crisp::types::{Keyword, Value};
|
||||
use miette::{miette, IntoDiagnostic, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{query_as, SqliteConnection};
|
||||
|
@ -14,6 +17,74 @@ pub struct Image {
|
|||
pub path: PathBuf,
|
||||
}
|
||||
|
||||
impl From<Value> for Image {
|
||||
fn from(value: Value) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Value> for Image {
|
||||
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| {
|
||||
p.to_str().unwrap_or_default().to_string()
|
||||
});
|
||||
Self {
|
||||
title: title.unwrap_or_default(),
|
||||
path: path.unwrap_or_default(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ServiceTrait for Image {
|
||||
fn title(&self) -> String {
|
||||
self.title.clone()
|
||||
}
|
||||
|
||||
fn id(&self) -> i32 {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn to_slides(&self) -> Result<Vec<Slide>> {
|
||||
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(false)
|
||||
.video_start_time(0.0)
|
||||
.video_end_time(0.0)
|
||||
.build()?;
|
||||
|
||||
Ok(vec![slide])
|
||||
}
|
||||
|
||||
fn box_clone(&self) -> Box<dyn ServiceTrait> {
|
||||
Box::new((*self).clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl Model<Image> {
|
||||
pub async fn load_from_db(&mut self) {
|
||||
let result = query_as!(
|
||||
|
|
|
@ -2,65 +2,65 @@ use std::{error::Error, fmt::Display};
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::presentations::PresKind;
|
||||
use crate::Slide;
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize,
|
||||
)]
|
||||
use super::{
|
||||
images::Image,
|
||||
presentations::{PresKind, Presentation},
|
||||
songs::Song,
|
||||
videos::Video,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum ServiceItemKind {
|
||||
#[default]
|
||||
Song,
|
||||
Video,
|
||||
Image,
|
||||
Presentation(PresKind),
|
||||
Content,
|
||||
Song(Song),
|
||||
Video(Video),
|
||||
Image(Image),
|
||||
Presentation((Presentation, PresKind)),
|
||||
Content(Slide),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ServiceItemKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let s = match self {
|
||||
Self::Song => "song".to_owned(),
|
||||
Self::Image => "image".to_owned(),
|
||||
Self::Video => "video".to_owned(),
|
||||
Self::Presentation(PresKind::Html) => "html".to_owned(),
|
||||
Self::Presentation(PresKind::Pdf) => "pdf".to_owned(),
|
||||
Self::Presentation(PresKind::Generic) => {
|
||||
"presentation".to_owned()
|
||||
}
|
||||
Self::Content => "content".to_owned(),
|
||||
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::Content(s) => "content".to_owned(),
|
||||
};
|
||||
write!(f, "{s}")
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for ServiceItemKind {
|
||||
type Error = ParseError;
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
match value.as_str() {
|
||||
"song" => Ok(Self::Song),
|
||||
"image" => Ok(Self::Image),
|
||||
"video" => Ok(Self::Video),
|
||||
"presentation" => {
|
||||
Ok(Self::Presentation(PresKind::Generic))
|
||||
}
|
||||
"html" => Ok(Self::Presentation(PresKind::Html)),
|
||||
"pdf" => Ok(Self::Presentation(PresKind::Pdf)),
|
||||
"content" => Ok(Self::Content),
|
||||
_ => Err(ParseError::UnknownType),
|
||||
}
|
||||
}
|
||||
}
|
||||
// impl TryFrom<String> for ServiceItemKind {
|
||||
// type Error = ParseError;
|
||||
// fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
// match value.as_str() {
|
||||
// "song" => Ok(Self::Song),
|
||||
// "image" => Ok(Self::Image),
|
||||
// "video" => Ok(Self::Video),
|
||||
// "presentation" => {
|
||||
// Ok(Self::Presentation(PresKind::Generic))
|
||||
// }
|
||||
// "html" => Ok(Self::Presentation(PresKind::Html)),
|
||||
// "pdf" => Ok(Self::Presentation(PresKind::Pdf)),
|
||||
// "content" => Ok(Self::Content),
|
||||
// _ => Err(ParseError::UnknownType),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl From<ServiceItemKind> for String {
|
||||
fn from(val: ServiceItemKind) -> String {
|
||||
match val {
|
||||
ServiceItemKind::Song => "song".to_owned(),
|
||||
ServiceItemKind::Video => "video".to_owned(),
|
||||
ServiceItemKind::Image => "image".to_owned(),
|
||||
ServiceItemKind::Song(_) => "song".to_owned(),
|
||||
ServiceItemKind::Video(_) => "video".to_owned(),
|
||||
ServiceItemKind::Image(_) => "image".to_owned(),
|
||||
ServiceItemKind::Presentation(_) => {
|
||||
"presentation".to_owned()
|
||||
}
|
||||
ServiceItemKind::Content => "content".to_owned(),
|
||||
ServiceItemKind::Content(_) => "content".to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crisp::types::Value;
|
||||
use miette::{miette, IntoDiagnostic, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{
|
||||
|
@ -6,7 +7,9 @@ use sqlx::{
|
|||
use std::path::PathBuf;
|
||||
use tracing::error;
|
||||
|
||||
use super::model::Model;
|
||||
use crate::{Background, Slide, SlideBuilder, TextAlignment};
|
||||
|
||||
use super::{model::Model, service_items::ServiceTrait};
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize,
|
||||
|
@ -28,6 +31,51 @@ pub struct Presentation {
|
|||
pub kind: PresKind,
|
||||
}
|
||||
|
||||
impl From<Value> for Presentation {
|
||||
fn from(value: Value) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Value> for Presentation {
|
||||
fn from(value: &Value) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl ServiceTrait for Presentation {
|
||||
fn title(&self) -> String {
|
||||
self.title.clone()
|
||||
}
|
||||
|
||||
fn id(&self) -> i32 {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn to_slides(&self) -> Result<Vec<Slide>> {
|
||||
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(false)
|
||||
.video_start_time(0.0)
|
||||
.video_end_time(0.0)
|
||||
.build()?;
|
||||
|
||||
Ok(vec![slide])
|
||||
}
|
||||
|
||||
fn box_clone(&self) -> Box<dyn ServiceTrait> {
|
||||
Box::new((*self).clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl Presentation {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
|
|
|
@ -1,29 +1,146 @@
|
|||
use crisp::types::{Keyword, Symbol, Value};
|
||||
use miette::Result;
|
||||
use tracing::error;
|
||||
|
||||
use crate::Slide;
|
||||
|
||||
use super::images::Image;
|
||||
use super::presentations::Presentation;
|
||||
use super::songs::Song;
|
||||
use super::songs::{lisp_to_song, Song};
|
||||
use super::videos::Video;
|
||||
|
||||
use super::kinds::ServiceItemKind;
|
||||
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct ServiceItem {
|
||||
pub id: i32,
|
||||
pub title: String,
|
||||
pub database_id: i32,
|
||||
pub kind: ServiceItemKind,
|
||||
// pub item: Box<dyn ServiceTrait>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
impl ServiceItem {
|
||||
pub fn to_slide(&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, _)) => {
|
||||
presentation.to_slides()
|
||||
}
|
||||
ServiceItemKind::Content(slide) => {
|
||||
Ok(vec![slide.clone()])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ServiceItem {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
id: 0,
|
||||
title: String::default(),
|
||||
database_id: 0,
|
||||
kind: ServiceItemKind::Content(Slide::default()),
|
||||
// item: Box::new(Image::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Value> for ServiceItem {
|
||||
fn from(value: Value) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Value> for ServiceItem {
|
||||
fn from(value: &Value) -> Self {
|
||||
match value {
|
||||
Value::List(list) => match &list[0] {
|
||||
Value::Symbol(Symbol(s)) if s == "slide" => {
|
||||
let background_pos = list
|
||||
.iter()
|
||||
.position(|v| match v {
|
||||
Value::Keyword(Keyword(background))
|
||||
if background == "background" =>
|
||||
{
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
.map_or_else(|| 1, |pos| pos + 1);
|
||||
if let Some(background) = list.get(background_pos)
|
||||
{
|
||||
match background {
|
||||
Value::List(item) => match &item[0] {
|
||||
Value::Symbol(Symbol(s))
|
||||
if s == "image" =>
|
||||
{
|
||||
Self::from(&Image::from(
|
||||
background,
|
||||
))
|
||||
}
|
||||
Value::Symbol(Symbol(s))
|
||||
if s == "video" =>
|
||||
{
|
||||
Self::from(&Video::from(
|
||||
background,
|
||||
))
|
||||
}
|
||||
Value::Symbol(Symbol(s))
|
||||
if s == "presentation" =>
|
||||
{
|
||||
Self::from(&Presentation::from(
|
||||
background,
|
||||
))
|
||||
}
|
||||
_ => todo!(),
|
||||
},
|
||||
_ => {
|
||||
error!(
|
||||
"There is no background here: {:?}",
|
||||
background
|
||||
);
|
||||
ServiceItem::default()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error!(
|
||||
"There is no background here: {:?}",
|
||||
background_pos
|
||||
);
|
||||
ServiceItem::default()
|
||||
}
|
||||
}
|
||||
Value::Symbol(Symbol(s)) if s == "song" => {
|
||||
let song = lisp_to_song(list.clone());
|
||||
Self::from(&song)
|
||||
}
|
||||
_ => todo!(),
|
||||
},
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ServiceItemModel {
|
||||
items: Vec<ServiceItem>,
|
||||
}
|
||||
|
||||
impl From<Vec<ServiceItem>> for ServiceItemModel {
|
||||
fn from(items: Vec<ServiceItem>) -> Self {
|
||||
Self { items }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Song> for ServiceItem {
|
||||
fn from(song: &Song) -> Self {
|
||||
Self {
|
||||
kind: ServiceItemKind::Song,
|
||||
kind: ServiceItemKind::Song(song.clone()),
|
||||
database_id: song.id,
|
||||
title: song.title.clone(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +149,9 @@ impl From<&Song> for ServiceItem {
|
|||
impl From<&Video> for ServiceItem {
|
||||
fn from(video: &Video) -> Self {
|
||||
Self {
|
||||
kind: ServiceItemKind::Video,
|
||||
kind: ServiceItemKind::Video(video.clone()),
|
||||
database_id: video.id,
|
||||
title: video.title.clone(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -42,8 +160,9 @@ impl From<&Video> for ServiceItem {
|
|||
impl From<&Image> for ServiceItem {
|
||||
fn from(image: &Image) -> Self {
|
||||
Self {
|
||||
kind: ServiceItemKind::Image,
|
||||
kind: ServiceItemKind::Image(image.clone()),
|
||||
database_id: image.id,
|
||||
title: image.title.clone(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -52,10 +171,12 @@ impl From<&Image> for ServiceItem {
|
|||
impl From<&Presentation> for ServiceItem {
|
||||
fn from(presentation: &Presentation) -> Self {
|
||||
Self {
|
||||
kind: ServiceItemKind::Presentation(
|
||||
kind: ServiceItemKind::Presentation((
|
||||
presentation.clone(),
|
||||
presentation.kind.clone(),
|
||||
),
|
||||
)),
|
||||
database_id: presentation.id,
|
||||
title: presentation.title.clone(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +191,37 @@ impl ServiceItemModel {
|
|||
self.items.push(service_item);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn to_slides(&self) -> Result<Vec<Slide>> {
|
||||
Ok(self
|
||||
.items
|
||||
.iter()
|
||||
.filter_map(|item| item.to_slide().ok())
|
||||
.flatten()
|
||||
.collect::<Vec<Slide>>())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ServiceTrait {
|
||||
fn title(&self) -> String;
|
||||
fn id(&self) -> i32;
|
||||
fn to_slides(&self) -> Result<Vec<Slide>>;
|
||||
fn box_clone(&self) -> Box<dyn ServiceTrait>;
|
||||
}
|
||||
|
||||
impl Clone for Box<dyn ServiceTrait> {
|
||||
fn clone(&self) -> Self {
|
||||
self.box_clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Box<dyn ServiceTrait> {
|
||||
fn fmt(
|
||||
&self,
|
||||
f: &mut std::fmt::Formatter<'_>,
|
||||
) -> Result<(), std::fmt::Error> {
|
||||
write!(f, "{}: {}", self.id(), self.title())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -99,26 +251,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,
|
||||
// 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),
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -228,6 +228,10 @@ impl Slide {
|
|||
|
||||
Ok(slides)
|
||||
}
|
||||
|
||||
// pub fn slides_from_item(item: &ServiceItem) -> Result<Vec<Self>> {
|
||||
// todo!()
|
||||
// }
|
||||
}
|
||||
|
||||
impl From<Value> for Slide {
|
||||
|
|
|
@ -10,10 +10,11 @@ use sqlx::{
|
|||
};
|
||||
use tracing::{debug, error};
|
||||
|
||||
use crate::core::slide;
|
||||
use crate::{core::slide, Slide, SlideBuilder};
|
||||
|
||||
use super::{
|
||||
model::Model,
|
||||
service_items::ServiceTrait,
|
||||
slide::{Background, TextAlignment},
|
||||
};
|
||||
|
||||
|
@ -34,6 +35,47 @@ pub struct Song {
|
|||
pub font_size: Option<i32>,
|
||||
}
|
||||
|
||||
impl ServiceTrait for Song {
|
||||
fn title(&self) -> String {
|
||||
self.title.clone()
|
||||
}
|
||||
|
||||
fn id(&self) -> i32 {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn to_slides(&self) -> Result<Vec<Slide>> {
|
||||
let lyrics = self.get_lyrics()?;
|
||||
let slides: Vec<Slide> = lyrics
|
||||
.iter()
|
||||
.map(|l| {
|
||||
SlideBuilder::new()
|
||||
.background(
|
||||
self.background.clone().unwrap_or_default(),
|
||||
)
|
||||
.font(self.font.clone().unwrap_or_default())
|
||||
.font_size(self.font_size.unwrap_or_default())
|
||||
.text_alignment(
|
||||
self.text_alignment.unwrap_or_default(),
|
||||
)
|
||||
.audio(self.audio.clone().unwrap_or_default())
|
||||
.video_loop(true)
|
||||
.video_start_time(0.0)
|
||||
.video_end_time(0.0)
|
||||
.text(l)
|
||||
.build()
|
||||
.unwrap_or_default()
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(slides)
|
||||
}
|
||||
|
||||
fn box_clone(&self) -> Box<dyn ServiceTrait> {
|
||||
Box::new((*self).clone())
|
||||
}
|
||||
}
|
||||
|
||||
const VERSE_KEYWORDS: [&str; 24] = [
|
||||
"Verse 1", "Verse 2", "Verse 3", "Verse 4", "Verse 5", "Verse 6",
|
||||
"Verse 7", "Verse 8", "Chorus 1", "Chorus 2", "Chorus 3",
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
use super::model::Model;
|
||||
use crate::{Background, SlideBuilder, TextAlignment};
|
||||
|
||||
use super::{
|
||||
model::Model, service_items::ServiceTrait, slide::Slide,
|
||||
};
|
||||
use cosmic::{executor, iced::Executor};
|
||||
use crisp::types::Value;
|
||||
use miette::{miette, IntoDiagnostic, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{query_as, SqliteConnection};
|
||||
|
@ -18,6 +23,51 @@ pub struct Video {
|
|||
pub looping: bool,
|
||||
}
|
||||
|
||||
impl From<Value> for Video {
|
||||
fn from(value: Value) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Value> for Video {
|
||||
fn from(value: &Value) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl ServiceTrait for Video {
|
||||
fn title(&self) -> String {
|
||||
self.title.clone()
|
||||
}
|
||||
|
||||
fn id(&self) -> i32 {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn to_slides(&self) -> Result<Vec<Slide>> {
|
||||
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<dyn ServiceTrait> {
|
||||
Box::new((*self).clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl Model<Video> {
|
||||
pub async fn load_from_db(&mut self) {
|
||||
let result = query_as!(Video, r#"SELECT title as "title!", file_path as "path!", start_time as "start_time!: f32", end_time as "end_time!: f32", loop as "looping!", id as "id: i32" from videos"#).fetch_all(&mut self.db).await;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use clap::{command, Parser};
|
||||
use core::service_items::ServiceItem;
|
||||
use cosmic::app::{Core, Settings, Task};
|
||||
use cosmic::iced::keyboard::Key;
|
||||
use cosmic::iced::window::{Mode, Position};
|
||||
|
@ -93,6 +94,8 @@ struct App {
|
|||
enum Message {
|
||||
Present(presenter::Message),
|
||||
File(PathBuf),
|
||||
DndEnter(ServiceItem),
|
||||
DndDrop(ServiceItem),
|
||||
OpenWindow,
|
||||
CloseWindow(Option<window::Id>),
|
||||
WindowOpened(window::Id, Option<Point>),
|
||||
|
@ -429,6 +432,8 @@ impl cosmic::Application for App {
|
|||
}
|
||||
}
|
||||
Message::Quit => cosmic::iced::exit(),
|
||||
Message::DndEnter(service_item) => todo!(),
|
||||
Message::DndDrop(service_item) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::time::Duration;
|
||||
use std::{rc::Rc, time::Duration};
|
||||
|
||||
use cosmic::{
|
||||
dialog::ashpd::url::Url,
|
||||
|
@ -13,7 +13,6 @@ use cosmic::{
|
|||
stack,
|
||||
},
|
||||
prelude::*,
|
||||
theme::CosmicTheme,
|
||||
widget::{
|
||||
container, image, mouse_area, responsive, scrollable,
|
||||
Container, Responsive, Row, Space,
|
||||
|
@ -25,14 +24,17 @@ use miette::{Context, IntoDiagnostic, Result};
|
|||
use tracing::{debug, error, info};
|
||||
|
||||
use crate::{
|
||||
core::{service_items::ServiceItem, slide::Slide},
|
||||
core::{
|
||||
service_items::{ServiceItem, ServiceItemModel},
|
||||
slide::Slide,
|
||||
},
|
||||
BackgroundKind,
|
||||
};
|
||||
|
||||
// #[derive(Default, Clone, Debug)]
|
||||
pub(crate) struct Presenter {
|
||||
pub slides: Vec<Slide>,
|
||||
pub items: Vec<ServiceItem>,
|
||||
pub items: ServiceItemModel,
|
||||
pub current_slide: Slide,
|
||||
pub current_slide_index: u16,
|
||||
pub video: Option<Video>,
|
||||
|
@ -56,7 +58,47 @@ impl Presenter {
|
|||
pub fn with_slides(slides: Vec<Slide>) -> Self {
|
||||
Self {
|
||||
slides: slides.clone(),
|
||||
items: vec![],
|
||||
items: ServiceItemModel::default(),
|
||||
current_slide: slides[0].clone(),
|
||||
current_slide_index: 0,
|
||||
video: {
|
||||
if let Some(slide) = slides.get(0) {
|
||||
let path = slide.background().path.clone();
|
||||
if path.exists() {
|
||||
let url = Url::from_file_path(path).unwrap();
|
||||
let result = Video::new(&url);
|
||||
match result {
|
||||
Ok(mut v) => {
|
||||
v.set_paused(true);
|
||||
Some(v)
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Had an error creating the video object: {e}");
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
video_position: 0.0,
|
||||
hovered_slide: -1,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_items(items: Vec<ServiceItem>) -> Self {
|
||||
let items = ServiceItemModel::from(items);
|
||||
let slides = if let Ok(slides) = items.to_slides() {
|
||||
slides
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
Self {
|
||||
slides: slides.clone(),
|
||||
items: items.into(),
|
||||
current_slide: slides[0].clone(),
|
||||
current_slide_index: 0,
|
||||
video: {
|
||||
|
|
Loading…
Reference in a new issue