aboutsummaryrefslogtreecommitdiff
path: root/server/src/routes/ui/node.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/routes/ui/node.rs')
-rw-r--r--server/src/routes/ui/node.rs172
1 files changed, 75 insertions, 97 deletions
diff --git a/server/src/routes/ui/node.rs b/server/src/routes/ui/node.rs
index 4d599dc..0ae0d9e 100644
--- a/server/src/routes/ui/node.rs
+++ b/server/src/routes/ui/node.rs
@@ -1,163 +1,141 @@
/*
-This file is part of jellything (https://codeberg.org/metamuffin/jellything)
-which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
-Copyright (C) 2023 metamuffin <metamuffin.org>
+ This file is part of jellything (https://codeberg.org/metamuffin/jellything)
+ which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
+ Copyright (C) 2023 metamuffin <metamuffin.org>
*/
-use super::error::MyError;
-use super::player::player_uri;
-use super::CacheControlFile;
-use crate::uri;
+use super::{assets::rocket_uri_macro_r_item_assets, error::MyError, player::player_uri};
use crate::{
- library::{Directory, Item, Library, Node},
+ database::Database,
routes::ui::{
account::session::Session,
+ assets::AssetRole,
layout::{DynLayoutPage, LayoutPage},
},
+ uri,
};
-use anyhow::Context;
-use jellycommon::DirectoryKind;
-use log::info;
-use rocket::{get, http::ContentType, State};
-use rocket::{FromFormField, UriDisplayQuery};
-use std::{path::PathBuf, sync::Arc};
-use tokio::fs::File;
+use anyhow::{anyhow, Context};
+use jellycommon::{Node, NodeKind};
+use rocket::{get, State};
-#[get("/library/<path..>")]
+#[get("/library/<id>")]
pub async fn r_library_node(
_sess: Session,
- path: PathBuf,
- library: &State<Library>,
+ id: String,
+ db: &State<Database>,
) -> Result<DynLayoutPage<'_>, MyError> {
- let node = library
- .nested_path(&path)
- .context("retrieving library node")?;
+ let node = db
+ .node
+ .get(&id)
+ .context("retrieving library node")?
+ .ok_or(anyhow!("node does not exist"))?;
+
+ let children = node
+ .public
+ .children
+ .iter()
+ .map(|c| {
+ Ok((
+ c.to_owned(),
+ db.node.get(c)?.ok_or(anyhow!("child does not exist"))?,
+ ))
+ })
+ .collect::<anyhow::Result<Vec<_>>>()?
+ .into_iter()
+ .collect();
+
Ok(LayoutPage {
- title: node.common().title.to_string(),
- show_back: node.get_item().is_ok(),
+ title: node.public.title.to_string(),
+ show_back: matches!(node.public.kind, NodeKind::Movie | NodeKind::Episode),
content: markup::new! {
- @NodePage { node: &node }
+ @NodePage { node: &node, id: &id, children: &children }
},
..Default::default()
})
}
markup::define! {
- NodePage<'a>(node: &'a Arc<Node>) {
- @match node.as_ref() {
- Node::Directory(dir) => { @match dir.info.kind {
- DirectoryKind::Series => { @SeriesPage { dir } }
- _ => { @DirectoryPage { dir } }
- } }
- Node::Item(item) => { @ItemPage { item } }
+ NodePage<'a>(id: &'a str, node: &'a Node, children: &'a Vec<(String,Node)>) {
+ @match node.public.kind {
+ NodeKind::Collection | NodeKind::Show | NodeKind::Season => { @DirectoryPage { node, id, children } }
+ NodeKind::Series => { @SeriesPage { node, children, id } }
+ NodeKind::Movie | NodeKind::Episode => { @ItemPage { node, id } }
}
}
- NodeCard<'a>(node: &'a Arc<Node>) {
- @match node.as_ref() {
- Node::Directory(dir) => {@PosterCard {
- wide: !matches!(dir.info.kind, DirectoryKind::Series | DirectoryKind::Season),
- dir: true,
- path: dir.lib_path.clone(),
- title: &dir.info.title
- }}
- Node::Item(item) => {@PosterCard {
- wide: false, dir: false,
- path: item.lib_path.clone(),
- title: &item.info.title
- }}
+ NodeCard<'a>(id: &'a str, node: &'a Node) {
+ @PosterCard {
+ wide: matches!(node.public.kind, NodeKind::Collection),
+ dir: !matches!(node.public.kind, NodeKind::Movie | NodeKind::Episode),
+ id,
+ title: &node.public.title
}
}
- DirectoryPage<'a>(dir: &'a Arc<Directory>) {
+ DirectoryPage<'a>(id: &'a str, node: &'a Node, children: &'a Vec<(String,Node)>) {
div.page.dir {
- h1 { @dir.info.title }
- @if let Some(parent) = dir.lib_path.parent() {
- a.dirup[href=uri!(r_library_node(&parent))] { "Go up" }
- }
+ h1 { @node.public.title }
+ // @if let Some(parent) = node.lib_path.parent() {
+ // a.dirup[href=uri!(r_library_node(&parent))] { "Go up" }
+ // }
ul.directorylisting {
- @for node in &dir.children {
- li { @NodeCard { node } }
+ @for (id, node) in children.iter() {
+ li { @NodeCard { id, node } }
}
}
}
}
- PosterCard<'a>(path: PathBuf, title: &'a str, wide: bool, dir: bool) {
+ PosterCard<'a>(id: &'a str, title: &'a str, wide: bool, dir: bool) {
div[class=if *wide {"card wide poster"} else {"card poster"}] {
div.banner {
- a[href=uri!(r_library_node(path))] {
- img[src=uri!(r_item_assets(path, AssetRole::Poster))];
+ a[href=uri!(r_library_node(id))] {
+ img[src=uri!(r_item_assets(id, AssetRole::Poster))];
}
@if *dir {
- div.hoverdir { a[href=&uri!(r_library_node(path))] { "Open" } }
+ div.hoverdir { a[href=&uri!(r_library_node(id))] { "Open" } }
} else {
- div.hoveritem { a[href=&player_uri(path)] { "▶" } }
+ div.hoveritem { a[href=&player_uri(id)] { "▶" } }
}
}
p.title {
- a[href=uri!(r_library_node(path))] {
+ a[href=uri!(r_library_node(id))] {
@title
}
}
}
}
- ItemPage<'a>(item: &'a Arc<Item>) {
+ ItemPage<'a>(id: &'a str, node: &'a Node) {
// TODO different image here
- img.backdrop[src=uri!(r_item_assets(&item.lib_path, AssetRole::Backdrop))];
+ img.backdrop[src=uri!(r_item_assets(id, AssetRole::Backdrop))];
div.page.item {
div.banner {
- img[src=uri!(r_item_assets(&item.lib_path, AssetRole::Poster))];
+ img[src=uri!(r_item_assets(id, AssetRole::Poster))];
}
div.title {
- h1 { @item.info.title }
+ h1 { @node.public.title }
// TODO release date, duration, ratings
- a.play[href=&player_uri(&item.lib_path)] { "Watch now" }
+ a.play[href=&player_uri(id)] { "Watch now" }
}
div.details {
- h3 { @item.info.tagline }
- p { @item.info.description }
+ h3 { @node.public.tagline }
+ p { @node.public.description }
}
}
}
- SeriesPage<'a>(dir: &'a Arc<Directory>) {
+ SeriesPage<'a>(id: &'a str, node: &'a Node, children: &'a Vec<(String,Node)>) {
// TODO different image here
- img.backdrop[src=uri!(r_item_assets(&dir.lib_path, AssetRole::Backdrop))];
+ img.backdrop[src=uri!(r_item_assets(id, AssetRole::Backdrop))];
div.page.item {
div.banner {
- img[src=uri!(r_item_assets(&dir.lib_path, AssetRole::Poster))];
+ img[src=uri!(r_item_assets(id, AssetRole::Poster))];
}
div.title {
- h1 { @dir.info.title }
+ h1 { @node.public.title }
}
div.details {
- h3 { @dir.info.tagline }
- p { @dir.info.description }
+ h3 { @node.public.tagline }
+ p { @node.public.description }
}
- ol { @for ep in &dir.children {
- li { a[href=uri!(r_library_node(ep.lib_path()))] { @ep.common().title } }
+ ol { @for (id, c) in children.iter() {
+ li { a[href=uri!(r_library_node(id))] { @c.public.title } }
} }
}
}
}
-
-#[derive(FromFormField, UriDisplayQuery)]
-pub enum AssetRole {
- Poster,
- Backdrop,
-}
-
-#[get("/item_assets/<path..>?<role>")]
-pub async fn r_item_assets(
- _sess: Session,
- path: PathBuf,
- role: AssetRole,
- library: &State<Library>,
-) -> Result<(ContentType, CacheControlFile), MyError> {
- let node = library
- .nested_path(&path)
- .context("retrieving library node")?;
- let path = node.get_asset(library, role);
- info!("loading asset from {path:?}");
- let ext = path.extension().unwrap().to_str().unwrap();
- Ok((
- ContentType::from_extension(ext).unwrap(),
- CacheControlFile::new(File::open(path).await?).await,
- ))
-}