aboutsummaryrefslogtreecommitdiff
path: root/server/src/routes
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/routes')
-rw-r--r--server/src/routes/mod.rs13
-rw-r--r--server/src/routes/stream.rs11
-rw-r--r--server/src/routes/ui/admin/log.rs4
-rw-r--r--server/src/routes/ui/admin/mod.rs75
-rw-r--r--server/src/routes/ui/assets.rs70
-rw-r--r--server/src/routes/ui/browser.rs1
-rw-r--r--server/src/routes/ui/home.rs34
-rw-r--r--server/src/routes/ui/node.rs112
-rw-r--r--server/src/routes/ui/player.rs13
-rw-r--r--server/src/routes/ui/search.rs3
-rw-r--r--server/src/routes/ui/sort.rs4
11 files changed, 163 insertions, 177 deletions
diff --git a/server/src/routes/mod.rs b/server/src/routes/mod.rs
index 33f1c69..45dd89a 100644
--- a/server/src/routes/mod.rs
+++ b/server/src/routes/mod.rs
@@ -30,15 +30,15 @@ use ui::{
},
admin::{
log::r_admin_log,
- r_admin_dashboard, r_admin_delete_cache, r_admin_import, r_admin_invite,
- r_admin_remove_invite, r_admin_transcode_posters,
+ r_admin_dashboard, r_admin_delete_cache, r_admin_invite, r_admin_remove_invite,
+ r_admin_transcode_posters,
user::{r_admin_remove_user, r_admin_user, r_admin_user_permission, r_admin_users},
},
- assets::{r_asset, r_item_assets, r_node_thumbnail, r_person_asset},
+ assets::{r_asset, r_item_backdrop, r_item_poster, r_node_thumbnail, r_person_asset},
browser::r_all_items_filter,
error::{r_api_catch, r_catch},
home::{r_home, r_home_unpriv},
- node::{r_library_node_ext, r_library_node_filter},
+ node::r_library_node_filter,
player::r_player,
search::r_search,
style::{r_assets_font, r_assets_js, r_assets_js_map, r_assets_style},
@@ -100,12 +100,12 @@ pub fn build_rocket(database: DataAcid, federation: Federation) -> Rocket<Build>
r_streamsync,
r_favicon,
r_asset,
- r_item_assets,
+ r_item_backdrop,
+ r_item_poster,
r_person_asset,
r_search,
r_all_items_filter,
r_library_node_filter,
- r_library_node_ext,
r_assets_style,
r_assets_font,
r_assets_js,
@@ -130,7 +130,6 @@ pub fn build_rocket(database: DataAcid, federation: Federation) -> Rocket<Build>
r_admin_users,
r_admin_remove_invite,
r_admin_user_permission,
- r_admin_import,
r_admin_delete_cache,
r_admin_transcode_posters,
r_admin_log,
diff --git a/server/src/routes/stream.rs b/server/src/routes/stream.rs
index 756c502..3500ee4 100644
--- a/server/src/routes/stream.rs
+++ b/server/src/routes/stream.rs
@@ -57,22 +57,21 @@ pub async fn r_stream(
.get(db, id)?
.only_if_permitted(&session.user.permissions)
.ok_or(anyhow!("node does not exist"))?;
- let source = node
- .private
- .source
+ let media = node
+ .media
.as_ref()
.ok_or(anyhow!("item does not contain media"))?;
// TODO its unclear how requests with multiple tracks should be handled.
if spec.track.len() == 1 {
let ti = spec.track[0];
- if let TrackSource::Remote(remote_index) = source[ti] {
+ if let TrackSource::Remote(remote_index) = media.tracks[ti].source {
session
.user
.permissions
.assert(&UserPermission::FederatedContent)?;
- let track = &node.public.media.ok_or(anyhow!("no media"))?.tracks[ti];
+ let track = &node.media.ok_or(anyhow!("no media"))?.tracks[ti];
let host = track
.federated
.last()
@@ -100,7 +99,7 @@ pub async fn r_stream(
.await?;
let uri = session.stream_url(
- node.public.id.as_ref().unwrap(),
+ &node.slug,
&StreamSpec {
track: vec![remote_index],
..spec
diff --git a/server/src/routes/ui/admin/log.rs b/server/src/routes/ui/admin/log.rs
index 884ad7a..b123ada 100644
--- a/server/src/routes/ui/admin/log.rs
+++ b/server/src/routes/ui/admin/log.rs
@@ -136,9 +136,7 @@ impl log::Log for Log {
fn vt100_to_html(s: &str) -> String {
let mut out = HtmlOut::default();
let mut st = vte::Parser::new();
- for b in s.bytes() {
- st.advance(&mut out, b);
- }
+ st.advance(&mut out, s.as_bytes());
out.s
}
diff --git a/server/src/routes/ui/admin/mod.rs b/server/src/routes/ui/admin/mod.rs
index 25f1f42..6e19373 100644
--- a/server/src/routes/ui/admin/mod.rs
+++ b/server/src/routes/ui/admin/mod.rs
@@ -26,12 +26,10 @@ use jellybase::{
database::{
redb::{ReadableTable, ReadableTableMetadata},
tantivy::query::Bm25StatisticsProvider,
- TableExt, T_INVITE, T_NODE, T_NODE_EXTENDED, T_USER_NODE,
+ TableExt, T_INVITE, T_NODE, T_USER_NODE,
},
- federation::Federation,
CONF,
};
-use jellyimport::{import, is_importing, IMPORT_ERRORS};
use markup::DynRender;
use rand::Rng;
use rocket::{form::Form, get, post, FromForm, State};
@@ -66,7 +64,7 @@ pub async fn admin_dashboard<'a>(
};
let flash = flash.map(|f| f.map_err(|e| format!("{e:?}")));
- let last_import_err = IMPORT_ERRORS.read().await.to_owned();
+ // let last_import_err = IMPORT_ERRORS.read().await.to_owned();
let database = database.to_owned();
Ok(LayoutPage {
@@ -74,28 +72,28 @@ pub async fn admin_dashboard<'a>(
content: markup::new! {
h1 { "Admin Panel" }
@FlashDisplay { flash: flash.clone() }
- @if !last_import_err.is_empty() {
- section.message.error {
- p.error {"The last import resulted in at least one error:"}
- ol { @for e in &last_import_err {
- li.error { pre.error { @e } }
- }}
- }
- }
+ // @if !last_import_err.is_empty() {
+ // section.message.error {
+ // p.error {"The last import resulted in at least one error:"}
+ // ol { @for e in &last_import_err {
+ // li.error { pre.error { @e } }
+ // }}
+ // }
+ // }
ul {
li{a[href=uri!(r_admin_log(true))] { "Server Log (Warnings only)" }}
li{a[href=uri!(r_admin_log(false))] { "Server Log (Full) " }}
}
h2 { "Library" }
- @if is_importing() {
- section.message { p.warn { "An import is currently running." } }
- }
+ // @if is_importing() {
+ // section.message { p.warn { "An import is currently running." } }
+ // }
@if is_transcoding() {
section.message { p.warn { "Currently transcoding posters." } }
}
- form[method="POST", action=uri!(r_admin_import())] {
- input[type="submit", disabled=is_importing(), value="(Re-)Import Library"];
- }
+ // form[method="POST", action=uri!(r_admin_import())] {
+ // input[type="submit", disabled=is_importing(), value="(Re-)Import Library"];
+ // }
form[method="POST", action=uri!(r_admin_transcode_posters())] {
input[type="submit", disabled=is_transcoding(), value="Transcode all posters with low resolution"];
}
@@ -133,7 +131,7 @@ pub async fn r_admin_invite(
_session: AdminSession,
database: &State<DataAcid>,
) -> MyResult<DynLayoutPage<'static>> {
- let i = format!("{}", rand::thread_rng().gen::<u128>());
+ let i = format!("{}", rand::rng().random::<u128>());
T_INVITE.insert(database, &*i, ())?;
admin_dashboard(database, Some(Ok(format!("Invite: {}", i)))).await
@@ -158,24 +156,24 @@ pub async fn r_admin_remove_invite(
admin_dashboard(database, Some(Ok("Invite invalidated".into()))).await
}
-#[post("/admin/import")]
-pub async fn r_admin_import(
- session: AdminSession,
- database: &State<DataAcid>,
- federation: &State<Federation>,
-) -> MyResult<DynLayoutPage<'static>> {
- drop(session);
- let t = Instant::now();
- let r = import(database, federation).await;
- admin_dashboard(
- database,
- Some(
- r.map_err(|e| e.into())
- .map(|_| format!("Import successful; took {:?}", t.elapsed())),
- ),
- )
- .await
-}
+// #[post("/admin/import")]
+// pub async fn r_admin_import(
+// session: AdminSession,
+// database: &State<DataAcid>,
+// federation: &State<Federation>,
+// ) -> MyResult<DynLayoutPage<'static>> {
+// drop(session);
+// let t = Instant::now();
+// let r = import(database, federation).await;
+// admin_dashboard(
+// database,
+// Some(
+// r.map_err(|e| e.into())
+// .map(|_| format!("Import successful; took {:?}", t.elapsed())),
+// ),
+// )
+// .await
+// }
#[post("/admin/delete_cache")]
pub async fn r_admin_delete_cache(
@@ -218,7 +216,7 @@ pub async fn r_admin_transcode_posters(
let nodes = txn.open_table(T_NODE)?;
for node in nodes.iter()? {
let (_, node) = node?;
- if let Some(poster) = &node.value().0.public.poster {
+ if let Some(poster) = &node.value().0.poster {
let asset = AssetInner::deser(&poster.0)?;
if asset.is_federated() {
continue;
@@ -246,7 +244,6 @@ fn db_stats(db: &DataAcid) -> anyhow::Result<DynRender> {
let txn = db.inner.begin_read()?;
let stats = [
("node", txn.open_table(T_NODE)?.stats()?),
- ("node-ext", txn.open_table(T_NODE_EXTENDED)?.stats()?),
("user", txn.open_table(T_USER_NODE)?.stats()?),
("user-node", txn.open_table(T_USER_NODE)?.stats()?),
("invite", txn.open_table(T_INVITE)?.stats()?),
diff --git a/server/src/routes/ui/assets.rs b/server/src/routes/ui/assets.rs
index ad31240..aeb4eff 100644
--- a/server/src/routes/ui/assets.rs
+++ b/server/src/routes/ui/assets.rs
@@ -9,16 +9,15 @@ use base64::Engine;
use jellybase::{
assetfed::AssetInner,
cache::async_cache_file,
- database::{DataAcid, TableExt, T_NODE, T_NODE_EXTENDED},
+ database::{DataAcid, TableExt, T_NODE},
federation::Federation,
permission::NodePermissionExt,
CONF,
};
-pub use jellycommon::AssetRole;
use jellycommon::{LocalTrack, PeopleGroup, SourceTrackKind, TrackSource};
use log::info;
use rocket::{get, http::ContentType, response::Redirect, State};
-use std::path::PathBuf;
+use std::{path::PathBuf, str::FromStr};
pub const AVIF_QUALITY: f32 = 50.;
pub const AVIF_SPEED: u8 = 5;
@@ -66,12 +65,11 @@ pub async fn resolve_asset(asset: AssetInner) -> anyhow::Result<PathBuf> {
}
}
-#[get("/n/<id>/asset?<role>&<width>")]
-pub async fn r_item_assets(
+#[get("/n/<id>/poster?<width>")]
+pub async fn r_item_poster(
session: Session,
db: &State<DataAcid>,
id: &str,
- role: AssetRole,
width: Option<usize>,
) -> MyResult<Redirect> {
let node = T_NODE
@@ -79,26 +77,45 @@ pub async fn r_item_assets(
.only_if_permitted(&session.user.permissions)
.ok_or(anyhow!("node does not exist"))?;
- let mut asset = match role {
- AssetRole::Backdrop => node.public.backdrop,
- AssetRole::Poster => node.public.poster,
+ let mut asset = node.poster;
+ if asset.is_none() {
+ if let Some(parent) = &node.parents.last() {
+ let parent = T_NODE
+ .get(db, parent.as_str())?
+ .ok_or(anyhow!("node does not exist"))?;
+ asset = parent.poster;
+ }
};
+ let asset = asset.unwrap_or_else(|| {
+ AssetInner::Assets(format!("fallback-{:?}.avif", node.kind.unwrap_or_default()).into())
+ .ser()
+ });
+ Ok(Redirect::temporary(rocket::uri!(r_asset(asset.0, width))))
+}
+#[get("/n/<id>/backdrop?<width>")]
+pub async fn r_item_backdrop(
+ session: Session,
+ db: &State<DataAcid>,
+ id: &str,
+ width: Option<usize>,
+) -> MyResult<Redirect> {
+ let node = T_NODE
+ .get(db, id)?
+ .only_if_permitted(&session.user.permissions)
+ .ok_or(anyhow!("node does not exist"))?;
+
+ let mut asset = node.poster;
if asset.is_none() {
- if let Some(parent) = &node.public.path.last() {
+ if let Some(parent) = &node.parents.last() {
let parent = T_NODE
.get(db, parent.as_str())?
.ok_or(anyhow!("node does not exist"))?;
- asset = match role {
- AssetRole::Backdrop => parent.public.backdrop,
- AssetRole::Poster => parent.public.poster,
- };
+ asset = parent.poster;
}
};
let asset = asset.unwrap_or_else(|| {
- AssetInner::Assets(
- format!("fallback-{:?}.avif", node.public.kind.unwrap_or_default()).into(),
- )
- .ser()
+ AssetInner::Assets(format!("fallback-{:?}.avif", node.kind.unwrap_or_default()).into())
+ .ser()
});
Ok(Redirect::temporary(rocket::uri!(r_asset(asset.0, width))))
}
@@ -109,7 +126,7 @@ pub async fn r_person_asset(
db: &State<DataAcid>,
id: &str,
index: usize,
- group: PeopleGroup,
+ group: String,
width: Option<usize>,
) -> MyResult<Redirect> {
T_NODE
@@ -117,10 +134,10 @@ pub async fn r_person_asset(
.only_if_permitted(&session.user.permissions)
.ok_or(anyhow!("node does not exist"))?;
- let ext = T_NODE_EXTENDED.get(db, id)?.unwrap_or_default();
- let app = ext
+ let node = T_NODE.get(db, id)?.unwrap_or_default();
+ let app = node
.people
- .get(&group)
+ .get(&PeopleGroup::from_str(&group).map_err(|()| anyhow!("unknown people group"))?)
.ok_or(anyhow!("group has no members"))?
.get(index)
.ok_or(anyhow!("person does not exist"))?;
@@ -150,15 +167,18 @@ pub async fn r_node_thumbnail(
.only_if_permitted(&session.user.permissions)
.ok_or(anyhow!("node does not exist"))?;
- let media = node.public.media.ok_or(anyhow!("no media"))?;
+ let media = node.media.ok_or(anyhow!("no media"))?;
let (thumb_track_index, thumb_track) = media
.tracks
.iter()
.enumerate()
.find(|(_i, t)| matches!(t.kind, SourceTrackKind::Video { .. }))
.ok_or(anyhow!("no video track to create a thumbnail of"))?;
- let source = node.private.source.ok_or(anyhow!("no source"))?;
- let thumb_track_source = &source[thumb_track_index];
+ let source = media
+ .tracks
+ .get(thumb_track_index)
+ .ok_or(anyhow!("no source"))?;
+ let thumb_track_source = source.source.clone();
if t < 0. || t > media.duration {
Err(anyhow!("thumbnail instant not within media duration"))?
diff --git a/server/src/routes/ui/browser.rs b/server/src/routes/ui/browser.rs
index da17271..4faf40b 100644
--- a/server/src/routes/ui/browser.rs
+++ b/server/src/routes/ui/browser.rs
@@ -39,7 +39,6 @@ pub fn r_all_items_filter(
.unwrap()
.map(|z| z.value().0)
.unwrap_or_default();
- let y = y.public;
(x, y, z)
})
.collect::<Vec<_>>();
diff --git a/server/src/routes/ui/home.rs b/server/src/routes/ui/home.rs
index 0a1089a..6f70644 100644
--- a/server/src/routes/ui/home.rs
+++ b/server/src/routes/ui/home.rs
@@ -3,19 +3,14 @@
which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
Copyright (C) 2024 metamuffin <metamuffin.org>
*/
-use super::{
- account::session::Session,
- layout::LayoutPage,
- node::{DatabaseNodeUserDataExt, NodeCard},
-};
+use super::{account::session::Session, layout::LayoutPage, node::NodeCard};
use crate::{
database::DataAcid,
routes::ui::{error::MyResult, layout::DynLayoutPage},
};
-use anyhow::Context;
use chrono::{Datelike, Utc};
use jellybase::{
- database::{redb::ReadableTable, TableExt, T_NODE, T_USER_NODE},
+ database::{redb::ReadableTable, T_NODE, T_USER_NODE},
CONF,
};
use jellycommon::{user::WatchedState, Rating};
@@ -38,7 +33,6 @@ pub fn r_home(sess: Session, db: &State<DataAcid>) -> MyResult<DynLayoutPage> {
.unwrap()
.map(|z| z.value().0)
.unwrap_or_default();
- let y = y.public;
(x, y, z)
})
.collect::<Vec<_>>();
@@ -49,16 +43,14 @@ pub fn r_home(sess: Session, db: &State<DataAcid>) -> MyResult<DynLayoutPage> {
.flat_map(|i| Some(items[cheap_daily_random(i).checked_rem(items.len())?].clone()))
.collect::<Vec<_>>();
- let toplevel = T_NODE
- .get(db, "library")?
- .context("root node missing")?
- .public
- .children
- .into_iter()
- .map(|n| db.get_node_with_userdata(&n, &sess))
- .collect::<anyhow::Result<Vec<_>>>()?
- .into_iter()
- .collect::<Vec<_>>();
+ // let toplevel = T_NODE
+ // .get(db, "library")?
+ // .context("root node missing")?
+ // .into_iter()
+ // .map(|n| db.get_node_with_userdata(&n, &sess))
+ // .collect::<anyhow::Result<Vec<_>>>()?
+ // .into_iter()
+ // .collect::<Vec<_>>();
items.sort_by_key(|(_, n, _)| {
n.ratings
@@ -98,9 +90,9 @@ pub fn r_home(sess: Session, db: &State<DataAcid>) -> MyResult<DynLayoutPage> {
title: "Home".to_string(),
content: markup::new! {
h2 { "Explore " @CONF.brand }
- ul.children.hlist {@for (id, node, udata) in &toplevel {
- li { @NodeCard { id, node, udata } }
- }}
+ // ul.children.hlist {@for (id, node, udata) in &toplevel {
+ // li { @NodeCard { id, node, udata } }
+ // }}
@if !continue_watching.is_empty() {
h2 { "Continue Watching" }
ul.children.hlist {@for (id, node, udata) in &continue_watching {
diff --git a/server/src/routes/ui/node.rs b/server/src/routes/ui/node.rs
index 40faf5a..88f71b7 100644
--- a/server/src/routes/ui/node.rs
+++ b/server/src/routes/ui/node.rs
@@ -4,7 +4,10 @@
Copyright (C) 2024 metamuffin <metamuffin.org>
*/
use super::{
- assets::{rocket_uri_macro_r_item_assets, rocket_uri_macro_r_node_thumbnail},
+ assets::{
+ rocket_uri_macro_r_item_backdrop, rocket_uri_macro_r_item_poster,
+ rocket_uri_macro_r_node_thumbnail,
+ },
error::MyResult,
sort::{filter_and_sort_nodes, NodeFilterSort, NodeFilterSortForm, SortOrder, SortProperty},
};
@@ -14,7 +17,7 @@ use crate::{
api::AcceptJson,
ui::{
account::session::Session,
- assets::{rocket_uri_macro_r_person_asset, AssetRole},
+ assets::rocket_uri_macro_r_person_asset,
layout::{DynLayoutPage, LayoutPage},
player::{rocket_uri_macro_r_player, PlayerConfig},
},
@@ -28,12 +31,12 @@ use crate::{
use anyhow::{anyhow, Result};
use chrono::DateTime;
use jellybase::{
- database::{TableExt, T_NODE, T_NODE_EXTENDED, T_USER_NODE},
+ database::{TableExt, T_NODE, T_USER_NODE},
permission::NodePermissionExt,
};
use jellycommon::{
user::{NodeUserData, WatchedState},
- Chapter, ExtendedNode, MediaInfo, NodeKind, NodePublic, PeopleGroup, Rating, SourceTrackKind,
+ Chapter, MediaInfo, Node, NodeKind, PeopleGroup, Rating, SourceTrackKind,
};
use rocket::{get, serde::json::Json, Either, State};
@@ -43,20 +46,6 @@ pub fn r_library_node(id: String) {
drop(id)
}
-#[get("/n/<id>/extended")]
-pub async fn r_library_node_ext<'a>(
- session: Session,
- id: &'a str,
- db: &'a State<DataAcid>,
-) -> MyResult<Json<ExtendedNode>> {
- T_NODE
- .get(db, id)?
- .only_if_permitted(&session.user.permissions)
- .ok_or(anyhow!("node does not exist"))?;
-
- Ok(Json(T_NODE_EXTENDED.get(db, id)?.unwrap_or_default()))
-}
-
#[get("/n/<id>?<filter..>")]
pub async fn r_library_node_filter<'a>(
session: Session,
@@ -64,13 +53,11 @@ pub async fn r_library_node_filter<'a>(
db: &'a State<DataAcid>,
aj: AcceptJson,
filter: NodeFilterSort,
-) -> MyResult<Either<DynLayoutPage<'a>, Json<NodePublic>>> {
+) -> MyResult<Either<DynLayoutPage<'a>, Json<Node>>> {
let node = T_NODE
.get(db, id)?
.only_if_permitted(&session.user.permissions)
- .ok_or(anyhow!("node does not exist"))?
- .public;
- let node_ext = T_NODE_EXTENDED.get(db, id)?.unwrap_or_default();
+ .ok_or(anyhow!("node does not exist"))?;
let udata = T_USER_NODE
.get(db, &(session.user.name.as_str(), id))?
@@ -80,29 +67,29 @@ pub async fn r_library_node_filter<'a>(
return Ok(Either::Right(Json(node)));
}
- let mut children = node
- .children
- .iter()
- .map(|c| db.get_node_with_userdata(c, &session))
- .collect::<anyhow::Result<Vec<_>>>()?
- .into_iter()
- .collect();
+ // let mut children = node
+ // .children
+ // .iter()
+ // .map(|c| db.get_node_with_userdata(c, &session))
+ // .collect::<anyhow::Result<Vec<_>>>()?
+ // .into_iter()
+ // .collect();
- let path = node
- .path
- .iter()
- .map(|c| {
- Ok((
- c.to_owned(),
- T_NODE
- .get(db, c.as_str())?
- .ok_or(anyhow!("parent node missing"))?
- .public,
- ))
- })
- .collect::<anyhow::Result<Vec<_>>>()?
- .into_iter()
- .collect::<Vec<_>>();
+ // let path = node
+ // .path
+ // .iter()
+ // .map(|c| {
+ // Ok((
+ // c.to_owned(),
+ // T_NODE
+ // .get(db, c.as_str())?
+ // .ok_or(anyhow!("parent node missing"))?
+ // .public,
+ // ))
+ // })
+ // .collect::<anyhow::Result<Vec<_>>>()?
+ // .into_iter()
+ // .collect::<Vec<_>>();
filter_and_sort_nodes(
&filter,
@@ -110,25 +97,26 @@ pub async fn r_library_node_filter<'a>(
NodeKind::Channel => (SortProperty::ReleaseDate, SortOrder::Descending),
_ => (SortProperty::Title, SortOrder::Ascending),
},
- &mut children,
+ // TODO
+ &mut Vec::new(),
);
Ok(Either::Left(LayoutPage {
title: node.title.clone().unwrap_or_default(),
content: markup::new! {
- @NodePage { node: &node, id, udata: &udata, children: &children, path: &path, filter: &filter, node_ext: &node_ext }
+ @NodePage { node: &node, id, udata: &udata, children: &[], path: &[], filter: &filter }
},
..Default::default()
}))
}
markup::define! {
- NodeCard<'a>(id: &'a str, node: &'a NodePublic, udata: &'a NodeUserData) {
+ NodeCard<'a>(id: &'a str, node: &'a Node, udata: &'a NodeUserData) {
@let cls = format!("node card poster {}", aspect_class(node.kind.unwrap_or_default()));
div[class=cls] {
.poster {
a[href=uri!(r_library_node(id))] {
- img[src=uri!(r_item_assets(id, AssetRole::Poster, Some(1024))), loading="lazy"];
+ img[src=uri!(r_item_poster(id, Some(1024))), loading="lazy"];
}
.cardhover.item {
@if node.media.is_some() {
@@ -149,14 +137,14 @@ markup::define! {
}
}
}
- NodePage<'a>(id: &'a str, node: &'a NodePublic, node_ext: &'a ExtendedNode, udata: &'a NodeUserData, children: &'a [(String, NodePublic, NodeUserData)], path: &'a [(String, NodePublic)], filter: &'a NodeFilterSort) {
+ NodePage<'a>(id: &'a str, node: &'a Node, udata: &'a NodeUserData, children: &'a [(String, Node, NodeUserData)], path: &'a [(String, Node)], filter: &'a NodeFilterSort) {
@if !matches!(node.kind.unwrap_or_default(), NodeKind::Collection) {
- img.backdrop[src=uri!(r_item_assets(id, AssetRole::Backdrop, Some(2048))), loading="lazy"];
+ img.backdrop[src=uri!(r_item_backdrop(id, Some(2048))), loading="lazy"];
}
.page.node {
@if !matches!(node.kind.unwrap_or_default(), NodeKind::Collection) {
@let cls = format!("bigposter {}", aspect_class(node.kind.unwrap_or_default()));
- div[class=cls] { img[src=uri!(r_item_assets(id, AssetRole::Poster, Some(2048))), loading="lazy"]; }
+ div[class=cls] { img[src=uri!(r_item_poster(id, Some(2048))), loading="lazy"]; }
}
.title {
h1 { @node.title }
@@ -213,16 +201,16 @@ markup::define! {
}}
}}
}
- @if !node_ext.people.is_empty() {
+ @if !node.people.is_empty() {
h2 { "Cast & Crew" }
- @for (group, people) in &node_ext.people {
+ @for (group, people) in &node.people {
details[open=group==&PeopleGroup::Cast] {
summary { h3 { @format!("{}", group) } }
ul.children.hlist { @for (i, pe) in people.iter().enumerate() {
li { .card."aspect-port" {
.poster {
a[href="#"] {
- img[src=&uri!(r_person_asset(id, i, group, Some(1024))), loading="lazy"];
+ img[src=&uri!(r_person_asset(id, i, group.to_string(), Some(1024))), loading="lazy"];
}
}
.title {
@@ -265,7 +253,7 @@ markup::define! {
}
}
- Props<'a>(node: &'a NodePublic, udata: &'a NodeUserData, full: bool) {
+ Props<'a>(node: &'a Node, udata: &'a NodeUserData, full: bool) {
.props {
@if let Some(m) = &node.media {
p { @format_duration(m.duration) }
@@ -278,9 +266,10 @@ markup::define! {
@DateTime::from_timestamp_millis(*d).unwrap().date_naive().to_string()
}}
}
- @if !node.children.is_empty() {
- p { @format!("{} items", node.children.len()) }
- }
+ // TODO
+ // @if !node.children.is_empty() {
+ // p { @format!("{} items", node.children.len()) }
+ // }
@for (kind, value) in &node.ratings {
@match kind {
Rating::YoutubeLikes => {p{ @format_count(*value as usize) " Likes" }}
@@ -337,21 +326,20 @@ pub trait DatabaseNodeUserDataExt {
&self,
id: &str,
session: &Session,
- ) -> Result<(String, NodePublic, NodeUserData)>;
+ ) -> Result<(String, Node, NodeUserData)>;
}
impl DatabaseNodeUserDataExt for DataAcid {
fn get_node_with_userdata(
&self,
id: &str,
session: &Session,
- ) -> Result<(String, NodePublic, NodeUserData)> {
+ ) -> Result<(String, Node, NodeUserData)> {
Ok((
id.to_owned(),
T_NODE
.get(self, id)?
.only_if_permitted(&session.user.permissions)
- .ok_or(anyhow!("node does not exist: {id}"))?
- .public,
+ .ok_or(anyhow!("node does not exist: {id}"))?,
T_USER_NODE
.get(self, &(session.user.name.as_str(), id))?
.unwrap_or_default(),
diff --git a/server/src/routes/ui/player.rs b/server/src/routes/ui/player.rs
index 55e1303..c5232e1 100644
--- a/server/src/routes/ui/player.rs
+++ b/server/src/routes/ui/player.rs
@@ -11,11 +11,7 @@ use crate::{
database::DataAcid,
routes::{
stream::rocket_uri_macro_r_stream,
- ui::{
- assets::{rocket_uri_macro_r_item_assets, AssetRole},
- error::MyResult,
- layout::DynLayoutPage,
- },
+ ui::{assets::rocket_uri_macro_r_item_backdrop, error::MyResult, layout::DynLayoutPage},
},
uri,
};
@@ -121,13 +117,13 @@ pub fn r_player<'a>(
let conf = player_conf(item.clone(), playing)?;
Ok(Either::Left(LayoutPage {
- title: item.public.title.to_owned().unwrap_or_default(),
+ title: item.title.to_owned().unwrap_or_default(),
class: Some("player"),
content: markup::new! {
@if playing {
video[src=uri!(r_stream(&id, &spec)), controls, preload="auto"]{}
} else {
- img.backdrop[src=uri!(r_item_assets(&id, AssetRole::Backdrop, Some(2048))).to_string()];
+ img.backdrop[src=uri!(r_item_backdrop(&id, Some(2048))).to_string()];
}
@conf
},
@@ -139,7 +135,6 @@ pub fn player_conf<'a>(item: Node, playing: bool) -> anyhow::Result<DynRender<'a
let mut video_tracks = vec![];
let mut sub_tracks = vec![];
let tracks = item
- .public
.media
.clone()
.ok_or(anyhow!("node does not have media"))?
@@ -155,7 +150,7 @@ pub fn player_conf<'a>(item: Node, playing: bool) -> anyhow::Result<DynRender<'a
Ok(markup::new! {
form.playerconf[method = "GET", action = ""] {
- h2 { "Select tracks for " @item.public.title }
+ h2 { "Select tracks for " @item.title }
fieldset.video {
legend { "Video" }
diff --git a/server/src/routes/ui/search.rs b/server/src/routes/ui/search.rs
index 5ca4b51..c1f9865 100644
--- a/server/src/routes/ui/search.rs
+++ b/server/src/routes/ui/search.rs
@@ -51,8 +51,7 @@ pub async fn r_search<'a>(
let node = T_NODE
.get(db, id)?
.only_if_permitted(&session.user.permissions)
- .ok_or(anyhow!("node does not exist"))?
- .public;
+ .ok_or(anyhow!("node does not exist"))?;
let udata = T_USER_NODE
.get(db, &(session.user.name.as_str(), id))?
.unwrap_or_default();
diff --git a/server/src/routes/ui/sort.rs b/server/src/routes/ui/sort.rs
index bcd9fe3..bb71184 100644
--- a/server/src/routes/ui/sort.rs
+++ b/server/src/routes/ui/sort.rs
@@ -1,7 +1,7 @@
use jellycommon::{
helpers::SortAnyway,
user::{NodeUserData, WatchedState},
- NodeKind, NodePublic, Rating,
+ Node, NodeKind, Rating,
};
use markup::RenderAttributeValue;
use rocket::{
@@ -134,7 +134,7 @@ pub enum SortOrder {
pub fn filter_and_sort_nodes(
f: &NodeFilterSort,
default_sort: (SortProperty, SortOrder),
- nodes: &mut Vec<(String, NodePublic, NodeUserData)>,
+ nodes: &mut Vec<(String, Node, NodeUserData)>,
) {
let sort_prop = f.sort_by.unwrap_or(default_sort.0);
nodes.retain(|(_id, node, udata)| {