use super::error::MyError; use super::player::player_uri; use crate::{ library::{Directory, Item, Library, Node}, routes::ui::{ account::session::Session, layout::{DynLayoutPage, LayoutPage}, }, }; use anyhow::{anyhow, Context}; use log::info; use rocket::{get, http::ContentType, uri, State}; use std::{ops::Deref, path::PathBuf, sync::Arc}; use tokio::fs::File; #[get("/library/")] pub async fn r_library_node( _sess: Session, path: PathBuf, library: &State, ) -> Result, MyError> { let node = library .nested_path(&path) .context("retrieving library node")? .clone(); Ok(LayoutPage { title: format!("{}", node.title()), content: markup::new! { @NodePage { node: node.clone() } }, }) } markup::define! { NodePage(node: Arc) { @match node.deref() { Node::Directory(dir) => { @DirectoryPage { dir: dir.clone() } } Node::Item(item) => { @ItemPage { item: item.clone() } } } } DirectoryCard(dir: Arc) { div.card.dir { a[href=&uri!(r_library_node(&dir.lib_path)).to_string()] { @dir.data.name } } } DirectoryPage(dir: Arc) { div.page.dir { h1 { @dir.data.name } ul.directorylisting { @for el in &dir.children { li { @match el.deref().to_owned() { Node::Directory(dir) => { @DirectoryCard { dir } } Node::Item(item) => { @ItemCard { item } } } } } } } } ItemCard(item: Arc) { div.card.item { div.banner { a[href=&uri!(r_library_node(&item.lib_path)).to_string()] { img[src=uri!(r_item_assets(&item.lib_path)).to_string()]; } div.hover { a[href=&player_uri(&item.lib_path)] { "▶" } } } p.title { a[href=&uri!(r_library_node(&item.lib_path)).to_string()] { @item.info.title } } } } ItemPage(item: Arc) { // TODO different image here img.backdrop[src=uri!(r_item_assets(&item.lib_path)).to_string()]; div.page.item { div.banner { img[src=uri!(r_item_assets(&item.lib_path)).to_string()]; } div.title { h1 { @item.info.title } a.play[href=&player_uri(&item.lib_path)] { "Watch now" } } div.details { h3 { "Lorem Ipsum!" } p { "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." } } } } } #[get("/item_assets/")] pub async fn r_item_assets( _sess: Session, path: PathBuf, library: &State, ) -> Result<(ContentType, File), MyError> { let node = library .nested_path(&path) .context("retrieving library node")? .get_item()? .clone(); let path = node.fs_path.parent().unwrap().join( node.info .banner .clone() .ok_or(anyhow!("no banner available"))?, ); info!("loading asset from {path:?}"); Ok((ContentType::WEBP, File::open(path).await?)) }