mirror of
https://codeberg.org/simonrepp/hyper8.git
synced 2026-08-14 13:45:27 +02:00
Draft playlist pane on video pages, ensure stable height for playlist thumbs
This commit is contained in:
+5
-4
@@ -50,7 +50,7 @@ pub fn perform_build(context: &Context) {
|
||||
match &site.content {
|
||||
SiteContent::Collection(collection) => build_collection(context, collection, &site, &breadcrumbs),
|
||||
SiteContent::Playlist(playlist) => build_playlist(context, playlist, &site, &breadcrumbs),
|
||||
SiteContent::Video(video) => build_video(context, video, &site, &breadcrumbs),
|
||||
SiteContent::Video(video) => build_video(context, None, video, &site, &breadcrumbs),
|
||||
SiteContent::Empty => (),
|
||||
SiteContent::Invalid => todo!()
|
||||
}
|
||||
@@ -78,7 +78,7 @@ fn build_collection(
|
||||
}
|
||||
|
||||
for video in &collection.videos {
|
||||
build_video(context, video, site, &breadcrumbs_extended);
|
||||
build_video(context, None, video, site, &breadcrumbs_extended);
|
||||
}
|
||||
|
||||
collection_html(context, collection, site, &breadcrumbs_extended);
|
||||
@@ -116,12 +116,13 @@ fn build_playlist(
|
||||
playlist_html(context, playlist, site, &breadcrumbs_extended);
|
||||
|
||||
for video in &playlist.videos {
|
||||
build_video(context, video, site, &breadcrumbs_extended);
|
||||
build_video(context, Some(playlist), video, site, &breadcrumbs_extended);
|
||||
}
|
||||
}
|
||||
|
||||
fn build_video(
|
||||
context: &Context,
|
||||
playlist: Option<&Playlist>,
|
||||
video: &Video,
|
||||
site: &Site,
|
||||
breadcrumbs: &[Breadcrumb]
|
||||
@@ -177,5 +178,5 @@ fn build_video(
|
||||
}
|
||||
}
|
||||
|
||||
video_html(context, video, site, &breadcrumbs_extended);
|
||||
video_html(context, playlist, video, site, &breadcrumbs_extended);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ video { width: 100%; }
|
||||
.center {
|
||||
margin: 0 auto;
|
||||
max-width: 33rem;
|
||||
position: relative;
|
||||
}
|
||||
.chart {
|
||||
align-items: center;
|
||||
@@ -48,6 +49,9 @@ video { width: 100%; }
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.current {
|
||||
background-color: var(--c-bg-3);
|
||||
}
|
||||
.duration {
|
||||
background-color: hsla(0, 0%, 0%, .9);
|
||||
border-radius: .2rem;
|
||||
@@ -78,6 +82,11 @@ img { max-width: 100%; }
|
||||
font-weight: 500;
|
||||
padding: .5rem;
|
||||
}
|
||||
.playlist > div {
|
||||
column-gap: 1rem;
|
||||
display: flex;
|
||||
}
|
||||
.playlist.context .thumbnail { height: 5rem; }
|
||||
.savings .bar { background-color: var(--c-green); }
|
||||
.savings_percent {
|
||||
color: var(--c-green);
|
||||
@@ -110,15 +119,11 @@ svg {
|
||||
background-color: var(--c-letterbox);
|
||||
border-radius: 0.4rem;
|
||||
flex-shrink: 0;
|
||||
height: 9rem;
|
||||
object-fit: contain;
|
||||
width: 16rem;
|
||||
}
|
||||
.thumbnail_wrapper {
|
||||
position: relative;
|
||||
}
|
||||
.thumbnail_wrapper:hover .duration {
|
||||
opacity: 1;
|
||||
}
|
||||
.thumbnail_wrapper { position: relative; }
|
||||
.thumbnail_wrapper:hover .duration { opacity: 1; }
|
||||
.video {
|
||||
color: var(--c-fg-2);
|
||||
display: flex;
|
||||
@@ -134,4 +139,13 @@ svg {
|
||||
display: grid;
|
||||
grid-gap: 1rem;
|
||||
grid-template-columns: 16rem auto;
|
||||
}
|
||||
|
||||
@media (min-width: 80rem) {
|
||||
.playlist.context {
|
||||
left: calc(100% + 2rem);
|
||||
position: absolute;
|
||||
top: 6rem;
|
||||
width: 24rem;
|
||||
}
|
||||
}
|
||||
+10
-8
@@ -55,17 +55,19 @@ pub fn playlist_html(
|
||||
if !playlist.videos.is_empty() {
|
||||
let videos = playlist.videos
|
||||
.iter()
|
||||
.map(|video| {
|
||||
let slug = &video.slug();
|
||||
let title = video.title.as_deref().unwrap_or_else(|| video.slug());
|
||||
.enumerate()
|
||||
.map(|(index, video)| {
|
||||
let number = index + 1;
|
||||
let slug = video.slug();
|
||||
let label = video.label();
|
||||
let video_prefix = format!("{slug}/");
|
||||
let video_thumbnail = thumbnail(video, &video_prefix);
|
||||
|
||||
formatdoc!(r#"
|
||||
<a href="{slug}{index_suffix}">
|
||||
{video_thumbnail}
|
||||
<div>{title}</div>
|
||||
</a>
|
||||
<div>
|
||||
<div>{video_thumbnail}</div>
|
||||
<div>{number} <a href="{slug}{index_suffix}">{label}</a></div>
|
||||
</div>
|
||||
"#)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
@@ -74,7 +76,7 @@ pub fn playlist_html(
|
||||
let videos_rendered = formatdoc!(r#"
|
||||
<h2>Videos</h2>
|
||||
|
||||
<div>
|
||||
<div class="playlist">
|
||||
{videos}
|
||||
</div>
|
||||
"#);
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ pub fn layout(
|
||||
"#),
|
||||
ThemeKind::Static(_) => String::new()
|
||||
};
|
||||
|
||||
|
||||
let body = formatdoc!(r##"
|
||||
<body>
|
||||
<div class="center">
|
||||
|
||||
+70
-2
@@ -1,25 +1,93 @@
|
||||
use std::fs;
|
||||
|
||||
use crate::{Context, Site, Video};
|
||||
use indoc::formatdoc;
|
||||
|
||||
use crate::{Context, Playlist, Site, Video};
|
||||
use crate::build::Breadcrumb;
|
||||
use crate::build::render::{layout, player};
|
||||
use crate::build::render::{layout, player, thumbnail};
|
||||
|
||||
pub fn video_html(
|
||||
context: &Context,
|
||||
playlist: Option<&Playlist>,
|
||||
video: &Video,
|
||||
site: &Site,
|
||||
breadcrumbs: &Vec<Breadcrumb>
|
||||
) {
|
||||
let index_suffix = context.index_suffix();
|
||||
let description = if let Some(description) = &video.description { description } else { "" };
|
||||
let title = video.title.as_deref().unwrap_or(video.slug());
|
||||
let player_rendered = player(video, "");
|
||||
|
||||
let playlist_context = match playlist {
|
||||
Some(playlist) => {
|
||||
let position = playlist.videos
|
||||
.iter()
|
||||
.position(|video_iterated| video_iterated.path == video.path)
|
||||
.unwrap();
|
||||
|
||||
let mut out = String::new();
|
||||
|
||||
let adjacent_shown: usize = 2;
|
||||
|
||||
// TODO: Below a certain threshold just show all videos (at least 6 or so)
|
||||
// TODO: Make the display a bit more compact too so that more videos can fit
|
||||
// (but also need to determine what to do with different aspect ratios as that changes the visual proportions)
|
||||
|
||||
let previous_videos = position;
|
||||
if previous_videos > adjacent_shown {
|
||||
out.push_str(&format!("{} previous videos", previous_videos - adjacent_shown));
|
||||
}
|
||||
|
||||
for (index, video_iterated) in playlist.videos.iter().enumerate() {
|
||||
if (index as i16) < (position as i16) - (adjacent_shown as i16) || index > position + adjacent_shown { continue; }
|
||||
|
||||
let label = video_iterated.label();
|
||||
let slug = video_iterated.slug();
|
||||
|
||||
let video_prefix = if index == position {
|
||||
String::new()
|
||||
} else {
|
||||
format!("../{slug}/")
|
||||
};
|
||||
|
||||
let thumbnail_rendered = thumbnail(video_iterated, &video_prefix);
|
||||
|
||||
let number = index + 1;
|
||||
let (current, href) = if index == position {
|
||||
("current", String::new())
|
||||
} else {
|
||||
("", format!("../{slug}{index_suffix}"))
|
||||
};
|
||||
|
||||
let line = formatdoc!(r#"
|
||||
<div class="{current}">
|
||||
<div>{thumbnail_rendered}</div>
|
||||
<div>{number} <a href="{href}">{label}</a></div>
|
||||
</div>
|
||||
"#);
|
||||
|
||||
out.push_str(&line);
|
||||
}
|
||||
|
||||
let remaining_videos = playlist.videos.len() - position - 1;
|
||||
if remaining_videos > adjacent_shown {
|
||||
out.push_str(&format!("{} more videos", remaining_videos - adjacent_shown));
|
||||
}
|
||||
|
||||
out
|
||||
}
|
||||
None => String::new()
|
||||
};
|
||||
|
||||
let body = format!(r#"
|
||||
<h1>{title}</h1>
|
||||
{player_rendered}
|
||||
<p>
|
||||
{description}
|
||||
</p>
|
||||
<div class="playlist context">
|
||||
{playlist_context}
|
||||
</div>
|
||||
<div>
|
||||
<a href="TODO">Share</a>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user