diff options
Diffstat (limited to 'server/src')
-rw-r--r-- | server/src/routes/ui/player.rs | 25 | ||||
-rw-r--r-- | server/src/routes/ui/style/directorypage.css | 74 | ||||
-rw-r--r-- | server/src/routes/ui/style/itempage.css | 50 | ||||
-rw-r--r-- | server/src/routes/ui/style/layout.css | 119 | ||||
-rw-r--r-- | server/src/routes/ui/style/mod.rs | 42 | ||||
-rw-r--r-- | server/src/routes/ui/style/player.css | 17 | ||||
-rw-r--r-- | server/src/routes/ui/style/transition.js | 2 |
7 files changed, 184 insertions, 145 deletions
diff --git a/server/src/routes/ui/player.rs b/server/src/routes/ui/player.rs index c7c7d51..c79addd 100644 --- a/server/src/routes/ui/player.rs +++ b/server/src/routes/ui/player.rs @@ -1,9 +1,15 @@ use super::HtmlTemplate; -use crate::routes::stream::stream_uri; -use crate::{library::Item, routes::ui::error::MyResult, AppState}; +use crate::{ + library::Item, + routes::{ + stream::stream_uri, + ui::{error::MyResult, node::rocket_uri_macro_r_item_assets}, + }, + AppState, +}; use jellycommon::SourceTrackKind; use log::warn; -use rocket::{get, FromForm, State}; +use rocket::{get, uri, FromForm, State}; use std::{path::PathBuf, sync::Arc}; pub fn player_uri(path: &PathBuf) -> String { @@ -60,13 +66,14 @@ pub fn player_conf<'a>(item: Arc<Item>) -> MyResult<HtmlTemplate<markup::DynRend Ok(HtmlTemplate( "Configure Player".to_string(), markup::new! { + // img.backdrop[src=uri!(r_item_assets(&item.lib_path)).to_string()]; form.playerconf[method = "GET", action = ""] { h2 { "Select tracks for " @item.info.title } fieldset.video { legend { "Video" } - @for (tid, track) in &video_tracks { - input[type="radio", id=tid, name="v", value=tid]; + @for (i, (tid, track)) in video_tracks.iter().enumerate() { + input[type="radio", id=tid, name="v", value=tid, checked=i==0]; label[for=tid] { @format!("{track}") } br; } input[type="radio", id="v-none", name="v", value=""]; @@ -75,8 +82,8 @@ pub fn player_conf<'a>(item: Arc<Item>) -> MyResult<HtmlTemplate<markup::DynRend fieldset.audio { legend { "Audio" } - @for (tid, track) in &audio_tracks { - input[type="radio", id=tid, name="a", value=tid]; + @for (i, (tid, track)) in audio_tracks.iter().enumerate() { + input[type="radio", id=tid, name="a", value=tid, checked=i==0]; label[for=tid] { @format!("{track}") } br; } input[type="radio", id="a-none", name="a", value=""]; @@ -85,8 +92,8 @@ pub fn player_conf<'a>(item: Arc<Item>) -> MyResult<HtmlTemplate<markup::DynRend fieldset.subtitles { legend { "Subtitles" } - @for (tid, track) in &sub_tracks { - input[type="radio", id=tid, name="s", value=tid]; + @for (i, (tid, track)) in sub_tracks.iter().enumerate() { + input[type="radio", id=tid, name="s", value=tid, checked=i==0]; label[for=tid] { @format!("{track}") } br; } input[type="radio", id="s-none", name="s", value=""]; diff --git a/server/src/routes/ui/style/directorypage.css b/server/src/routes/ui/style/directorypage.css new file mode 100644 index 0000000..8c6d5d9 --- /dev/null +++ b/server/src/routes/ui/style/directorypage.css @@ -0,0 +1,74 @@ + +.page.dir { + padding: 1em; + padding-left: 3em; + padding-right: 3em; +} +.directorylisting { + list-style: none; + display: flex; + flex-wrap: wrap; +} +.directorylisting li { + display: block; +} + +.card.item { + width: var(--card-size); + height: calc(var(--card-size) * var(--banner-aspect)); + padding: 1em; +} +.card.dir { + width: calc(var(--card-size) * 2); + height: calc(var(--card-size) * var(--banner-aspect)); +} + +.card.item .title { + margin-top: 0.1em; + text-align: center; + text-overflow: ellipsis; +} +.card.item .banner { + display: grid; +} +.card.item .banner a { + grid-area: 1 / 1; +} +.card.item .banner a img { + width: 100%; + height: 100%; + object-fit: cover; + object-position: center; +} +.card.item .banner .hover { + 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.item .banner:hover .hover { + opacity: 1; + background-color: #0004; + backdrop-filter: blur(3px); +} +.card.item .banner .hover 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.item .banner .hover 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 new file mode 100644 index 0000000..284d74f --- /dev/null +++ b/server/src/routes/ui/style/itempage.css @@ -0,0 +1,50 @@ + +.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, 20%); + 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: "▶"; +} diff --git a/server/src/routes/ui/style/layout.css b/server/src/routes/ui/style/layout.css index ef03873..8f7afb4 100644 --- a/server/src/routes/ui/style/layout.css +++ b/server/src/routes/ui/style/layout.css @@ -71,7 +71,6 @@ nav a:hover { background-size: 0 2px, 100% 2px; } - nav h1 { margin: 0px; font-size: 1.5em; @@ -92,121 +91,3 @@ nav h1 { font-family: monospace; } -.page.dir { - padding: 1em; - padding-left: 3em; - padding-right: 3em; -} -.directorylisting { - list-style: none; - display: flex; - flex-wrap: wrap; -} -.directorylisting li { - display: block; -} - -.card.item { - width: var(--card-size); - height: calc(var(--card-size) * var(--banner-aspect)); - padding: 1em; -} -.card.dir { - width: calc(var(--card-size) * 2); - height: calc(var(--card-size) * var(--banner-aspect)); -} - -.card.item .title { - margin-top: 0.1em; - text-align: center; - text-overflow: ellipsis; -} -.card.item .banner { - display: grid; -} -.card.item .banner a { - grid-area: 1 / 1; -} -.card.item .banner a img { - width: 100%; - height: 100%; - object-fit: cover; - object-position: center; -} -.card.item .banner .hover { - 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.item .banner:hover .hover { - opacity: 1; - background-color: #0004; - backdrop-filter: blur(3px); -} -.card.item .banner .hover 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: 2.2em; - pointer-events: all; - background-color: #0005; - transition: background-color 0.2s, font-size 0.2s; -} -.card.item .banner .hover a:hover { - background-color: #0008; - font-size: 3em; -} - -.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; - mask-image: linear-gradient( - rgba(0, 0, 0, 1), - transparent calc(var(--backdrop-height) + 5em) - ); - mask-mode: alpha; - pointer-events: none; - object-fit: cover; - object-position: center; -} -.page.item { - position: relative; - width: 100%; -} -.page.item .banner { - width: max(8em, 20%); - 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: "▶"; -} diff --git a/server/src/routes/ui/style/mod.rs b/server/src/routes/ui/style/mod.rs index ad9c5e5..39e11af 100644 --- a/server/src/routes/ui/style/mod.rs +++ b/server/src/routes/ui/style/mod.rs @@ -8,22 +8,33 @@ use std::{ fn css_bundle() -> String { if cfg!(debug_assertions) { - ["layout.css", "player.css"] - .into_iter() - .map(|n| { - read_to_string( - PathBuf::from_str(file!()) - .unwrap() - .parent() - .unwrap() - .join(n), - ) - .unwrap() - }) - .collect::<Vec<_>>() - .join("\n") + [ + "layout.css", + "player.css", + "itempage.css", + "directorypage.css", + ] + .into_iter() + .map(|n| { + read_to_string( + PathBuf::from_str(file!()) + .unwrap() + .parent() + .unwrap() + .join(n), + ) + .unwrap() + }) + .collect::<Vec<_>>() + .join("\n") } else { - concat!(include_str!("layout.css"), include_str!("player.css")).to_string() + concat!( + include_str!("layout.css"), + include_str!("player.css"), + include_str!("itempage.css"), + include_str!("directorypage.css") + ) + .to_string() } } @@ -68,7 +79,6 @@ fn js_bundle() -> String { } } - #[get("/assets/style.css")] pub fn r_assets_style() -> (ContentType, String) { (ContentType::CSS, css_bundle()) diff --git a/server/src/routes/ui/style/player.css b/server/src/routes/ui/style/player.css index 3468a38..b34653e 100644 --- a/server/src/routes/ui/style/player.css +++ b/server/src/routes/ui/style/player.css @@ -36,6 +36,23 @@ form.playerconf { legend { font-size: 1.5em; } +input[type="radio"] { + appearance: none; + display: inline-block; + width: 1.2em; + height: 1.2em; + border-radius: 8px; + background-clip: content-box; + border: 2px solid var(--font); + background-color: transparent; +} +input[type="radio"]:checked { + background-color: var(--accent-light); +} + +input[type=submit]:hover { + filter: hue-rotate(-20deg); +} fieldset label { transition: color 0.2s; diff --git a/server/src/routes/ui/style/transition.js b/server/src/routes/ui/style/transition.js index 193f5a2..5ee7f80 100644 --- a/server/src/routes/ui/style/transition.js +++ b/server/src/routes/ui/style/transition.js @@ -46,7 +46,7 @@ function fade(dir) { document.body.appendChild(overlay) return new Promise(res => { setTimeout(() => { - document.body.removeChild(overlay) + if (dir) document.body.removeChild(overlay) res() }, duration * 1000) }) |