From f62fce4feaf84a8fb3c2625a64db97a382a9b887 Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Fri, 2 Jul 2021 00:41:50 +1200 Subject: [PATCH] Highlight current chapter in video description --- html/static/js/channel.js | 2 +- html/static/js/chapter-highlight.js | 53 +++++++++++++++++++ .../MarkWatchedButton.js} | 0 .../SubscribeButton.js} | 0 html/static/js/player.js | 2 +- html/static/js/subscriptions.js | 2 +- pug/video.pug | 3 +- sass/includes/video-page.sass | 28 ++++++++++ 8 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 html/static/js/chapter-highlight.js rename html/static/js/{mark-watched.js => modules/MarkWatchedButton.js} (100%) rename html/static/js/{subscribe.js => modules/SubscribeButton.js} (100%) diff --git a/html/static/js/channel.js b/html/static/js/channel.js index 3e202ce..98962c5 100644 --- a/html/static/js/channel.js +++ b/html/static/js/channel.js @@ -1,4 +1,4 @@ import {q} from "/static/js/elemjs/elemjs.js" -import {SubscribeButton} from "/static/js/subscribe.js" +import {SubscribeButton} from "/static/js/modules/SubscribeButton.js" new SubscribeButton(q("#subscribe")) diff --git a/html/static/js/chapter-highlight.js b/html/static/js/chapter-highlight.js new file mode 100644 index 0000000..5b44cd9 --- /dev/null +++ b/html/static/js/chapter-highlight.js @@ -0,0 +1,53 @@ +import {q, qa, ElemJS} from "./elemjs/elemjs.js" + +class Chapter { + constructor(linkElement) { + this.link = new ElemJS(linkElement) + this.time = +linkElement.getAttribute("data-clickable-timestamp") + } +} + +let chapters = [...document.querySelectorAll("[data-clickable-timestamp]")].map(linkElement => new Chapter(linkElement)) +chapters.sort((a, b) => a.time - b.time) + +function getCurrentChapter(time) { + const candidates = chapters.filter(chapter => chapter.time <= time) + if (candidates.length > 0) { + return candidates[candidates.length - 1] + } else { + return null + } +} + +const video = q("#video") +const description = q("#description") +const regularBackground = "var(--regular-background)" +const highlightBackground = "var(--highlight-background)" +const paddingWidth = 4 +let lastChapter = null +setInterval(() => { + const currentChapter = getCurrentChapter(video.currentTime) + + if (currentChapter !== lastChapter) { + // Style link + if (lastChapter) { + lastChapter.link.removeClass("timestamp--active") + } + if (currentChapter) { + currentChapter.link.class("timestamp--active") + } + // Style background + if (currentChapter) { + const {offsetTop, offsetHeight} = currentChapter.link.element; + const offsetBottom = offsetTop + offsetHeight + let gradient = `linear-gradient(to bottom,` + + ` ${regularBackground} ${offsetTop - paddingWidth}px, ${highlightBackground} ${offsetTop - paddingWidth}px,` + + ` ${highlightBackground} ${offsetBottom + paddingWidth}px, ${regularBackground} ${offsetBottom + paddingWidth}px)` + console.log(gradient) + description.style.background = gradient + } else { + description.style.background = "" + } + } + lastChapter = currentChapter +}, 1000) diff --git a/html/static/js/mark-watched.js b/html/static/js/modules/MarkWatchedButton.js similarity index 100% rename from html/static/js/mark-watched.js rename to html/static/js/modules/MarkWatchedButton.js diff --git a/html/static/js/subscribe.js b/html/static/js/modules/SubscribeButton.js similarity index 100% rename from html/static/js/subscribe.js rename to html/static/js/modules/SubscribeButton.js diff --git a/html/static/js/player.js b/html/static/js/player.js index 12bd0ab..d04b34e 100644 --- a/html/static/js/player.js +++ b/html/static/js/player.js @@ -1,5 +1,5 @@ import {q, qa, ElemJS} from "/static/js/elemjs/elemjs.js" -import {SubscribeButton} from "/static/js/subscribe.js" +import {SubscribeButton} from "/static/js/modules/SubscribeButton.js" const video = q("#video") const audio = q("#audio") diff --git a/html/static/js/subscriptions.js b/html/static/js/subscriptions.js index f10fdb1..9093f9f 100644 --- a/html/static/js/subscriptions.js +++ b/html/static/js/subscriptions.js @@ -1,5 +1,5 @@ import {qa} from "/static/js/elemjs/elemjs.js" -import {MarkWatchedButton} from "/static/js/mark-watched.js" +import {MarkWatchedButton} from "/static/js/modules/MarkWatchedButton.js" for (const button of qa(".mark-watched__button")) { new MarkWatchedButton(button) diff --git a/pug/video.pug b/pug/video.pug index c56ac83..04ea3a2 100644 --- a/pug/video.pug +++ b/pug/video.pug @@ -9,6 +9,7 @@ block head else title Error - CloudTube script(type="module" src=getStaticURL("html", "/static/js/player.js")) + script(type="module" src=getStaticURL("html", "/static/js/chapter-highlight.js")) script const data = !{JSON.stringify({...video, continuous})} block content @@ -73,7 +74,7 @@ block content a(href=`https://www.youtube.com/watch?v=${video.videoId}#cloudtube`).border-look YouTube a(href=`https://redirect.invidious.io/watch?v=${video.videoId}`).border-look Invidious - .description!= video.descriptionHtml + .description#description!= video.descriptionHtml //- Standard view aside(style=continuous ? "display: none" : "")#standard-related-videos.related-videos diff --git a/sass/includes/video-page.sass b/sass/includes/video-page.sass index 5b99428..6683986 100644 --- a/sass/includes/video-page.sass +++ b/sass/includes/video-page.sass @@ -93,13 +93,18 @@ flex-shrink: 0 .description + position: relative font-size: 17px + line-height: 1.4 word-break: break-word margin: 16px 4px 4px 4px background-color: c.$bg-accent-area padding: 12px border-radius: 4px + --regular-background: #{c.$bg-accent-area} + --highlight-background: #{c.$bg-darker} + .subscribe-form display: inline-block @@ -149,3 +154,26 @@ .actor margin: 4px 0px 10px + +// Chapter highlights + +.timestamp--active + margin: 4px 0px + display: inline-block + + &::after + display: block + position: absolute + left: 0 + right: 0 + height: calc(1.4em + 4px) + transform: translateY(-1.4em) translateY(-4px) + + padding-right: 6px + text-align: right + content: "⮜" + line-height: 1.6 + color: #fff + + border: solid black + border-width: 2px 0px