aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/src/routes/ui/player.rs25
-rw-r--r--server/src/routes/ui/style/directorypage.css74
-rw-r--r--server/src/routes/ui/style/itempage.css50
-rw-r--r--server/src/routes/ui/style/layout.css119
-rw-r--r--server/src/routes/ui/style/mod.rs42
-rw-r--r--server/src/routes/ui/style/player.css17
-rw-r--r--server/src/routes/ui/style/transition.js2
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)
})