From dcc3b7a9f3c29df31907af1280b9000ac344458c Mon Sep 17 00:00:00 2001 From: metamuffin Date: Sat, 5 Aug 2023 17:39:42 +0200 Subject: refactor node views --- server/src/main.rs | 6 +- server/src/routes/ui/browser.rs | 10 +- server/src/routes/ui/node.rs | 77 ++++---------- server/src/routes/ui/style/directorypage.css | 135 ------------------------ server/src/routes/ui/style/itempage.css | 64 ------------ server/src/routes/ui/style/layout.css | 5 +- server/src/routes/ui/style/mod.rs | 4 +- server/src/routes/ui/style/nodecard.css | 147 +++++++++++++++++++++++++++ server/src/routes/ui/style/nodepage.css | 64 ++++++++++++ 9 files changed, 243 insertions(+), 269 deletions(-) delete mode 100644 server/src/routes/ui/style/directorypage.css delete mode 100644 server/src/routes/ui/style/itempage.css create mode 100644 server/src/routes/ui/style/nodecard.css create mode 100644 server/src/routes/ui/style/nodepage.css (limited to 'server/src') diff --git a/server/src/main.rs b/server/src/main.rs index 6a75c30..3c5f7f9 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -42,9 +42,9 @@ async fn async_main() { let database = Database::open(&CONF.database_path).unwrap(); let federation = Federation::initialize(); database.create_admin(); - if let Err(err) = import::import(&database, &federation).await { - error!("import not sucessful: {err:?}") - } + // if let Err(err) = import::import(&database, &federation).await { + // error!("import not sucessful: {err:?}") + // } build_rocket(remuxer, database, federation) .launch() .await diff --git a/server/src/routes/ui/browser.rs b/server/src/routes/ui/browser.rs index e7f7d96..6e772d0 100644 --- a/server/src/routes/ui/browser.rs +++ b/server/src/routes/ui/browser.rs @@ -3,7 +3,7 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2023 metamuffin */ -use super::{account::session::Session, error::MyError, layout::DynLayoutPage, node::PosterCard}; +use super::{account::session::Session, error::MyError, layout::DynLayoutPage, node::NodeCard}; use crate::database::Database; use anyhow::Context; use jellycommon::{Node, NodeKind}; @@ -25,12 +25,8 @@ pub fn r_all_items(_sess: Session, db: &State) -> Result(id: &'a str, node: &'a NodePublic, children: &'a Vec<(String, NodePublic)>) { - @match node.kind { - NodeKind::Collection | NodeKind::Show | NodeKind::Season => { @DirectoryPage { node, _id: id, children } } - NodeKind::Series => { @SeriesPage { node, children, id } } - NodeKind::Movie | NodeKind::Episode | NodeKind::Video => { @ItemPage { node, id } } - } - } NodeCard<'a>(id: &'a str, node: &'a NodePublic) { - @PosterCard { - wide: matches!(node.kind, NodeKind::Collection | NodeKind::Video), - dir: !matches!(node.kind, NodeKind::Movie | NodeKind::Video | NodeKind::Episode), - id, - title: &node.title - } - } - DirectoryPage<'a>(_id: &'a str, node: &'a NodePublic, children: &'a Vec<(String, NodePublic)>) { - div.page.dir { - h1 { @node.title } - @if let Some(parent) = &node.parent { - a.dirup[href=uri!(r_library_node(parent))] { "Go up" } - } - ul.directorylisting { - @for (id, node) in children.iter() { - li { @NodeCard { id, node } } - } - } - } - } - PosterCard<'a>(id: &'a str, title: &'a str, wide: bool, dir: bool) { - div[class=if *wide {"card wide poster"} else {"card poster"}] { + @let cls = format!("card poster {}", match node.kind {NodeKind::Channel => "poster-square", NodeKind::Video => "thumb-land", NodeKind::Collection => "poster-land", _ => "poster-port"}); + div[class=cls] { div.banner { a[href=uri!(r_library_node(id))] { img[src=uri!(r_item_assets(id, AssetRole::Poster))]; } - @if *dir { + @if matches!(node.kind, NodeKind::Collection | NodeKind::Channel) { div.hoverdir { a[href=&uri!(r_library_node(id))] { "Open" } } } else { div.hoveritem { a[href=&player_uri(id)] { "▶" } } @@ -107,21 +80,18 @@ markup::define! { } p.title { a[href=uri!(r_library_node(id))] { - @title + @node.title } } } } - ItemPage<'a>(id: &'a str, node: &'a NodePublic) { - // TODO different image here + NodePage<'a>(id: &'a str, node: &'a NodePublic, children: &'a Vec<(String, NodePublic)>) { img.backdrop[src=uri!(r_item_assets(id, AssetRole::Backdrop))]; div.page.item { - div.banner { - img[src=uri!(r_item_assets(id, AssetRole::Poster))]; - } + div.banner { img[src=uri!(r_item_assets(id, AssetRole::Poster))]; } div.title { h1 { @node.title } - a.play[href=&player_uri(id)] { "Watch now" } + @if node.media.is_some() { a.play[href=&player_uri(id)] { "Watch now" }} } div.details { div.props { @@ -133,6 +103,7 @@ markup::define! { p { @match r { Rating::YoutubeLikes(n) => { @format_count(*n) " Likes" } Rating::YoutubeViews(n) => { @format_count(*n) " Views" } + Rating::YoutubeFollowers(n) => { @format_count(*n) " Subscribers" } _ => { "Unknown Rating" } } } } @@ -140,25 +111,19 @@ markup::define! { h3 { @node.tagline } p { @node.description } } - } - } - SeriesPage<'a>(id: &'a str, node: &'a NodePublic, children: &'a Vec<(String, NodePublic)>) { - // TODO different image here - img.backdrop[src=uri!(r_item_assets(id, AssetRole::Backdrop))]; - div.page.item { - div.banner { - img[src=uri!(r_item_assets(id, AssetRole::Poster))]; - } - div.title { - h1 { @node.title } - } - div.details { - h3 { @node.tagline } - p { @node.description } + @match node.kind { + NodeKind::Collection | NodeKind::Channel => { + ul.children {@for (id, node) in children.iter() { + li { @NodeCard { id, node } } + }} + } + NodeKind::Series => { + ol { @for (id, c) in children.iter() { + li { a[href=uri!(r_library_node(id))] { @c.title } } + }} + } + _ => {} } - ol { @for (id, c) in children.iter() { - li { a[href=uri!(r_library_node(id))] { @c.title } } - } } } } } diff --git a/server/src/routes/ui/style/directorypage.css b/server/src/routes/ui/style/directorypage.css deleted file mode 100644 index 0d18c82..0000000 --- a/server/src/routes/ui/style/directorypage.css +++ /dev/null @@ -1,135 +0,0 @@ -/* - 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 - Copyright (C) 2023 tpart -*/ -.page.dir { - padding: 1em; - padding-left: 3em; - padding-right: 3em; -} -.directorylisting { - list-style: none; - display: flex; - flex-wrap: wrap; -} -.directorylisting li { - display: block; -} - -.page.dir .dirup { - width: 100%; - font-size: large; - display: block; - text-align: center; - background-color: var(--background-light); - border-radius: 0.2em; - padding: 0.6em; - margin: 0.2em; - transition: filter 0.2s; -} -.page.dir .dirup:hover { - filter: brightness(120%); -} - -.card { - padding: 1em; - height: var(--card-size); -} -.card.poster { - width: calc(var(--card-size) / var(--item-banner-aspect)); -} -.card.poster.wide { - width: calc(var(--card-size) / var(--dir-banner-aspect)); -} - -.card .title { - margin-top: 0.1em; - text-align: center; - text-overflow: ellipsis; -} -.card .banner { - display: grid; -} -.card .banner a { - grid-area: 1 / 1; -} - -.card.poster .banner img { - width: calc(var(--card-size) / var(--item-banner-aspect)); - height: var(--card-size); -} -.card.poster.wide .banner img { - width: calc(var(--card-size) / var(--dir-banner-aspect)); - height: var(--card-size); -} -.card .banner a img { - object-fit: cover; - object-position: center; -} - - -.card.poster .banner .hoverdir { - transition: opacity 0.3s, backdrop-filter 0.3s; - opacity: 0; - display: flex; - position: relative; - bottom: 0px; - height: 5em; - margin-top: -5em; -} -.card.poster .banner:hover .hoverdir { - opacity: 1; - background-color: #0004; - backdrop-filter: blur(3px); -} -.card.poster .banner .hoverdir a { - text-decoration: none; - width: 100%; - height: 1.7em; - font-size: large; - display: block; - text-align: center; - background-color: #0004; - border-radius: 0.2em; - padding: 0.6em; - margin: 0.6em; - transition: background-color 0.2s; -} -.card.poster .banner .hoverdir a:hover { - background-color: #0008; -} - -.card.poster .banner .hoveritem { - pointer-events: none; - grid-area: 1 / 1; - transition: opacity 0.3s, backdrop-filter 0.3s; - opacity: 0; - display: flex; - justify-content: center; - align-items: center; -} -.card.poster .banner:hover .hoveritem { - opacity: 1; - background-color: #0004; - backdrop-filter: blur(3px); -} -.card.poster .banner .hoveritem a { - text-decoration: none; - font-stretch: 200%; - width: 1em; - height: 1em; - line-height: 1; - margin: auto; - padding: 0.4em 0.3em 0.4em 0.5em; - border-radius: 50%; - font-size: 1.8em; - pointer-events: all; - background-color: #0005; - transition: background-color 0.2s, font-size 0.2s; -} -.card.poster .banner .hoveritem a:hover { - background-color: #0008; - font-size: 2.4em; -} diff --git a/server/src/routes/ui/style/itempage.css b/server/src/routes/ui/style/itempage.css deleted file mode 100644 index 2913ff7..0000000 --- a/server/src/routes/ui/style/itempage.css +++ /dev/null @@ -1,64 +0,0 @@ -/* - 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 - Copyright (C) 2023 tpart -*/ -.backdrop { - width: calc(100% + 2 * var(--main-side-margin)); - height: calc(var(--backdrop-height) + 5em); - margin-left: calc(-1 * var(--main-side-margin)); - margin-right: calc(-1 * var(--main-side-margin)); - margin-top: calc(-1 * var(--bar-height)); - margin-bottom: -5em; - -webkit-mask-image: linear-gradient( - rgba(0, 0, 0, 1), - transparent calc(var(--backdrop-height) + 5em) - ); - mask-image: linear-gradient( - rgba(0, 0, 0, 1), - transparent calc(var(--backdrop-height) + 5em) - ); - -webkit-mask-mode: alpha; - mask-mode: alpha; - pointer-events: none; - object-fit: cover; - object-position: center; -} -.page.item { - position: relative; - width: 100%; -} -.page.item .banner { - width: max(8em, 25%); - float: left; - margin: 3em; - margin-top: -1em; -} -.page.item .banner img { - width: 100%; - height: 100%; - object-fit: cover; - object-position: center; -} - -.page.item .title h1 { - display: inline; - margin-right: 1em; -} -.page.item .title .play { - display: inline; - font-stretch: 200%; -} -.page.item .title .play::before { - content: "▶"; -} - -.page.item .props p { - margin: 0.4em; - font-size: small; - font-weight: bolder; - display: inline-block; - padding: 0.2em; - background: #ffffff15; -} diff --git a/server/src/routes/ui/style/layout.css b/server/src/routes/ui/style/layout.css index 7aadadc..2da6d97 100644 --- a/server/src/routes/ui/style/layout.css +++ b/server/src/routes/ui/style/layout.css @@ -12,8 +12,9 @@ :root { --card-size: 17em; --bar-height: 5em; - --item-banner-aspect: 1.41; - --dir-banner-aspect: (1.41 / 2); + --port-poster-aspect: 1.41; + --land-poster-aspect: (1.41 / 2); + --land-thumb-aspect: (9 / 16); --accent-light: rgb(255, 163, 87); --accent-dark: rgb(199, 90, 0); --backdrop-height: 24em; diff --git a/server/src/routes/ui/style/mod.rs b/server/src/routes/ui/style/mod.rs index e1ba17b..9098691 100644 --- a/server/src/routes/ui/style/mod.rs +++ b/server/src/routes/ui/style/mod.rs @@ -35,8 +35,8 @@ fn css_bundle() -> String { concat_files!( "layout.css", "player.css", - "itempage.css", - "directorypage.css", + "nodepage.css", + "nodecard.css", "js-player.css", "forms.css" ) diff --git a/server/src/routes/ui/style/nodecard.css b/server/src/routes/ui/style/nodecard.css new file mode 100644 index 0000000..fea2a10 --- /dev/null +++ b/server/src/routes/ui/style/nodecard.css @@ -0,0 +1,147 @@ +/* + 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 + Copyright (C) 2023 tpart +*/ +.children { + padding: 1em; + padding-left: 3em; + padding-right: 3em; + list-style: none; + display: flex; + flex-wrap: wrap; +} +.children li { + display: block; +} + +.dirup { + width: 100%; + font-size: large; + display: block; + text-align: center; + background-color: var(--background-light); + border-radius: 0.2em; + padding: 0.6em; + margin: 0.2em; + transition: filter 0.2s; +} +.dirup:hover { + filter: brightness(120%); +} + +.card { + padding: 1em; + height: var(--card-size); +} +.card.poster.poster-port { + width: calc(var(--card-size) / var(--port-poster-aspect)); +} +.card.poster.poster-land { + width: calc(var(--card-size) / var(--land-poster-aspect)); +} +.card.poster.thumb-land { + width: calc(var(--card-size) / var(--land-thumb-aspect)); +} +.card.poster.poster-square { + width: calc(var(--card-size)); +} + +.card .title { + margin-top: 0.1em; + text-align: center; + text-overflow: ellipsis; +} +.card .banner { + display: grid; +} +.card .banner a { + grid-area: 1 / 1; +} + +.card.poster.poster-port .banner img { + width: calc(var(--card-size) / var(--port-poster-aspect)); + height: var(--card-size); +} +.card.poster.poster-land .banner img { + width: calc(var(--card-size) / var(--land-poster-aspect)); + height: var(--card-size); +} +.card.poster.thumb-land .banner img { + width: calc(var(--card-size) / var(--land-thumb-aspect)); + height: var(--card-size); +} +.card.poster.poster-square .banner img { + width: calc(var(--card-size)); + height: var(--card-size); +} +.card .banner a img { + object-fit: cover; + object-position: center; +} + + +.card.poster .banner .hoverdir { + transition: opacity 0.3s, backdrop-filter 0.3s; + opacity: 0; + display: flex; + position: relative; + bottom: 0px; + height: 5em; + margin-top: -5em; +} +.card.poster .banner:hover .hoverdir { + opacity: 1; + background-color: #0004; + backdrop-filter: blur(3px); +} +.card.poster .banner .hoverdir a { + text-decoration: none; + width: 100%; + height: 1.7em; + font-size: large; + display: block; + text-align: center; + background-color: #0004; + border-radius: 0.2em; + padding: 0.6em; + margin: 0.6em; + transition: background-color 0.2s; +} +.card.poster .banner .hoverdir a:hover { + background-color: #0008; +} + +.card.poster .banner .hoveritem { + pointer-events: none; + grid-area: 1 / 1; + transition: opacity 0.3s, backdrop-filter 0.3s; + opacity: 0; + display: flex; + justify-content: center; + align-items: center; +} +.card.poster .banner:hover .hoveritem { + opacity: 1; + background-color: #0004; + backdrop-filter: blur(3px); +} +.card.poster .banner .hoveritem a { + text-decoration: none; + font-stretch: 200%; + width: 1em; + height: 1em; + line-height: 1; + margin: auto; + padding: 0.4em 0.3em 0.4em 0.5em; + border-radius: 50%; + font-size: 1.8em; + pointer-events: all; + background-color: #0005; + transition: background-color 0.2s, font-size 0.2s; +} +.card.poster .banner .hoveritem a:hover { + background-color: #0008; + font-size: 2.4em; +} diff --git a/server/src/routes/ui/style/nodepage.css b/server/src/routes/ui/style/nodepage.css new file mode 100644 index 0000000..2913ff7 --- /dev/null +++ b/server/src/routes/ui/style/nodepage.css @@ -0,0 +1,64 @@ +/* + 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 + Copyright (C) 2023 tpart +*/ +.backdrop { + width: calc(100% + 2 * var(--main-side-margin)); + height: calc(var(--backdrop-height) + 5em); + margin-left: calc(-1 * var(--main-side-margin)); + margin-right: calc(-1 * var(--main-side-margin)); + margin-top: calc(-1 * var(--bar-height)); + margin-bottom: -5em; + -webkit-mask-image: linear-gradient( + rgba(0, 0, 0, 1), + transparent calc(var(--backdrop-height) + 5em) + ); + mask-image: linear-gradient( + rgba(0, 0, 0, 1), + transparent calc(var(--backdrop-height) + 5em) + ); + -webkit-mask-mode: alpha; + mask-mode: alpha; + pointer-events: none; + object-fit: cover; + object-position: center; +} +.page.item { + position: relative; + width: 100%; +} +.page.item .banner { + width: max(8em, 25%); + float: left; + margin: 3em; + margin-top: -1em; +} +.page.item .banner img { + width: 100%; + height: 100%; + object-fit: cover; + object-position: center; +} + +.page.item .title h1 { + display: inline; + margin-right: 1em; +} +.page.item .title .play { + display: inline; + font-stretch: 200%; +} +.page.item .title .play::before { + content: "▶"; +} + +.page.item .props p { + margin: 0.4em; + font-size: small; + font-weight: bolder; + display: inline-block; + padding: 0.2em; + background: #ffffff15; +} -- cgit v1.2.3-70-g09d2