1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
/*
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 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/<path..>")]
pub async fn r_library_node(
_sess: Session,
path: PathBuf,
library: &State<Library>,
) -> Result<DynLayoutPage<'_>, 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<Node>) {
@match node.deref() {
Node::Directory(dir) => { @DirectoryPage { dir: dir.clone() } }
Node::Item(item) => { @ItemPage { item: item.clone() } }
}
}
DirectoryCard(dir: Arc<Directory>) {
div.card.dir { a[href=&uri!(r_library_node(&dir.lib_path)).to_string()] { @dir.data.name } }
}
DirectoryPage(dir: Arc<Directory>) {
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<Item>) {
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<Item>) {
// 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 { @item.info.description_head }
p { @item.info.description }
}
}
}
}
#[get("/item_assets/<path..>")]
pub async fn r_item_assets(
_sess: Session,
path: PathBuf,
library: &State<Library>,
) -> 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?))
}
|