aboutsummaryrefslogtreecommitdiff
path: root/server/src/routes/ui/node.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-03-03 18:15:47 +0100
committermetamuffin <metamuffin@disroot.org>2025-03-03 18:15:47 +0100
commitbf84be508aa415b45a51fc0fe007a0879f7bfab7 (patch)
tree6a98c9a534dbb5eed899d0f9ff6f6499dddfd0db /server/src/routes/ui/node.rs
parent26d3a70b0be2809177076e155f987e18e2b2ceb2 (diff)
downloadjellything-bf84be508aa415b45a51fc0fe007a0879f7bfab7.tar
jellything-bf84be508aa415b45a51fc0fe007a0879f7bfab7.tar.bz2
jellything-bf84be508aa415b45a51fc0fe007a0879f7bfab7.tar.zst
nodepage in player and tags
Diffstat (limited to 'server/src/routes/ui/node.rs')
-rw-r--r--server/src/routes/ui/node.rs52
1 files changed, 47 insertions, 5 deletions
diff --git a/server/src/routes/ui/node.rs b/server/src/routes/ui/node.rs
index 9deffbb..76ecd82 100644
--- a/server/src/routes/ui/node.rs
+++ b/server/src/routes/ui/node.rs
@@ -36,7 +36,7 @@ use jellycommon::{
Chapter, MediaInfo, Node, NodeID, NodeKind, PeopleGroup, Rating, SourceTrackKind, Visibility,
};
use rocket::{get, serde::json::Json, Either, State};
-use std::{fmt::Write, sync::Arc};
+use std::{cmp::Reverse, collections::BTreeMap, fmt::Write, sync::Arc};
/// This function is a stub and only useful for use in the uri! macro.
#[get("/n/<id>")]
@@ -74,6 +74,9 @@ pub async fn r_library_node_filter<'a>(
Vec::new()
};
+ let mut similar = get_similar_media(&node, db, &session)?;
+
+ similar.retain(|(n, _)| n.visibility >= Visibility::Reduced);
children.retain(|(n, _)| n.visibility >= Visibility::Reduced);
parents.retain(|(n, _)| n.visibility >= Visibility::Reduced);
@@ -98,13 +101,38 @@ pub async fn r_library_node_filter<'a>(
Either::Left(LayoutPage {
title: node.title.clone().unwrap_or_default(),
content: markup::new! {
- @NodePage { node: &node, udata: &udata, children: &children, parents: &parents, filter: &filter }
+ @NodePage { node: &node, udata: &udata, children: &children, parents: &parents, filter: &filter, player: false, similar: &similar }
},
..Default::default()
})
})
}
+pub fn get_similar_media(
+ node: &Node,
+ db: &Database,
+ session: &Session,
+) -> Result<Vec<(Arc<Node>, NodeUserData)>> {
+ let this_id = NodeID::from_slug(&node.slug);
+ let mut ranking = BTreeMap::<NodeID, usize>::new();
+ for tag in &node.tags {
+ let nodes = db.get_tag_nodes(tag)?;
+ let weight = 1_000_000 / nodes.len();
+ for n in nodes {
+ if n != this_id {
+ *ranking.entry(n).or_default() += weight;
+ }
+ }
+ }
+ let mut ranking = ranking.into_iter().collect::<Vec<_>>();
+ ranking.sort_by_key(|(_, k)| Reverse(*k));
+ ranking
+ .into_iter()
+ .take(32)
+ .map(|(pid, _)| db.get_node_with_userdata(pid, &session))
+ .collect::<anyhow::Result<Vec<_>>>()
+}
+
markup::define! {
NodeCard<'a>(node: &'a Node, udata: &'a NodeUserData) {
@let cls = format!("node card poster {}", aspect_class(node.kind));
@@ -151,12 +179,12 @@ markup::define! {
}
}
}
- NodePage<'a>(node: &'a Node, udata: &'a NodeUserData, children: &'a [(Arc<Node>, NodeUserData)], parents: &'a [(Arc<Node>, NodeUserData)], filter: &'a NodeFilterSort) {
- @if !matches!(node.kind, NodeKind::Collection) {
+ NodePage<'a>(node: &'a Node, udata: &'a NodeUserData, children: &'a [(Arc<Node>, NodeUserData)], parents: &'a [(Arc<Node>, NodeUserData)], similar: &'a [(Arc<Node>, NodeUserData)], filter: &'a NodeFilterSort, player: bool) {
+ @if !matches!(node.kind, NodeKind::Collection) && !player {
img.backdrop[src=uri!(r_item_backdrop(&node.slug, Some(2048))), loading="lazy"];
}
.page.node {
- @if !matches!(node.kind, NodeKind::Collection) {
+ @if !matches!(node.kind, NodeKind::Collection) && !player {
@let cls = format!("bigposter {}", aspect_class(node.kind));
div[class=cls] { img[src=uri!(r_item_poster(&node.slug, Some(2048))), loading="lazy"]; }
}
@@ -248,10 +276,24 @@ markup::define! {
}}
}
}
+ @if !node.tags.is_empty() {
+ details {
+ summary { "Tags" }
+ ol { @for tag in &node.tags {
+ li { @tag }
+ }}
+ }
+ }
}
@if matches!(node.kind, NodeKind::Collection | NodeKind::Channel) {
@NodeFilterSortForm { f: filter }
}
+ @if !similar.is_empty() {
+ h2 { "Similar Media" }
+ ul.children.hlist {@for (node, udata) in similar.iter() {
+ li { @NodeCard { node, udata } }
+ }}
+ }
@match node.kind {
NodeKind::Show | NodeKind::Series | NodeKind::Season => {
ol { @for (node, udata) in children.iter() {