/* 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) 2026 metamuffin */ use crate::{ RenderInfo, components::{node_page::aspect_class, props::Props}, }; use jellycommon::{ jellyobject::{EMPTY, Object}, routes::{u_image, u_image_fallback_person, u_node_slug, u_node_slug_player}, *, }; markup::define! { NodeCard<'a>(ri: &'a RenderInfo<'a>, nku: &'a Nku<'a>) { @let node = &nku.node; @let slug = node.get(NO_SLUG).unwrap_or_default(); div[class=&format!("card {}", aspect_class(&node))] { .poster { a[href=u_node_slug(&slug)] { img[src=cover_image(&node, 512), loading="lazy"]; } .overlay { @if node.has(NO_TRACK.0) { a.play.icon[href=u_node_slug_player(&slug)] { "play_arrow" } } @Props { ri, nku, full: false } } } div.title { a[href=u_node_slug(&slug)] { @node.get(NO_TITLE) } } div.subtitle { span { @nku.role.or(node.get(NO_SUBTITLE)) } } } } NodeCardWide<'a>(ri: &'a RenderInfo<'a>, nku: Nku<'a>) { @let node = &nku.node; @let slug = node.get(NO_SLUG).unwrap_or_default(); div[class="card wide"] { div[class=&format!("poster {}", aspect_class(node))] { a[href=u_node_slug(&slug)] { img[src=cover_image(&node, 512), loading="lazy"]; } .overlay { @if node.has(NO_TRACK.0) { a.play.icon[href=u_node_slug_player(&slug)] { "play_arrow" } } } } div.details { a.title[href=u_node_slug(&slug)] { @node.get(NO_TITLE) } @Props { ri, nku ,full: false } span.overview { @node.get(NO_DESCRIPTION) } } } } NodeCardHightlight<'a>(ri: &'a RenderInfo<'a>, nku: &'a Nku<'a>) { @let node = &nku.node; @let slug = node.get(NO_SLUG).unwrap_or_default(); @let backdrop = u_image(node.get(NO_PICTURES).unwrap_or(EMPTY).get(PICT_BACKDROP).unwrap_or_default(), 2048); div[class="card highlight", style=format!("background-image: url(\"{backdrop}\")")] { .inner { div.overview { h2 { a[href=u_node_slug(slug)] { @node.get(NO_TITLE) } } @Props { ri, nku: *nku, full: false } p { b { @node.get(NO_TAGLINE) } " " @node.get(NO_DESCRIPTION) } } div[class=&format!("poster {}", aspect_class(node))] { a[href=u_node_slug(&slug)] { img[src=cover_image(&node, 512), loading="lazy"]; } .overlay { @if node.has(NO_TRACK.0) { a.play.icon[href=u_node_slug_player(&slug)] { "play_arrow" } } } } } } } } fn cover_image(node: &Object, size: usize) -> String { if let Some(cover) = node.get(NO_PICTURES).unwrap_or(EMPTY).get(PICT_COVER) { return u_image(cover, size); } if let Some(title) = node.get(NO_TITLE) && node.get(NO_KIND) == Some(KIND_PERSON) { return u_image_fallback_person(title, 512); } return String::new(); }