mirror of https://git.sr.ht/~cadence/cloudtube
Compare commits
No commits in common. "21629de5947e4da4d2962ce3f0c16b1a7c447e21" and "eb111a44c4392f982d120ce6158067101c27a636" have entirely different histories.
21629de594
...
eb111a44c4
|
@ -1,4 +1,4 @@
|
||||||
import {q} from "/static/js/elemjs/elemjs.js"
|
import {q} from "/static/js/elemjs/elemjs.js"
|
||||||
import {SubscribeButton} from "/static/js/modules/SubscribeButton.js"
|
import {SubscribeButton} from "/static/js/subscribe.js"
|
||||||
|
|
||||||
new SubscribeButton(q("#subscribe"))
|
new SubscribeButton(q("#subscribe"))
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
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)
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {q, qa, ElemJS} from "/static/js/elemjs/elemjs.js"
|
import {q, qa, ElemJS} from "/static/js/elemjs/elemjs.js"
|
||||||
import {SubscribeButton} from "/static/js/modules/SubscribeButton.js"
|
import {SubscribeButton} from "/static/js/subscribe.js"
|
||||||
|
|
||||||
const video = q("#video")
|
const video = q("#video")
|
||||||
const audio = q("#audio")
|
const audio = q("#audio")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {qa} from "/static/js/elemjs/elemjs.js"
|
import {qa} from "/static/js/elemjs/elemjs.js"
|
||||||
import {MarkWatchedButton} from "/static/js/modules/MarkWatchedButton.js"
|
import {MarkWatchedButton} from "/static/js/mark-watched.js"
|
||||||
|
|
||||||
for (const button of qa(".mark-watched__button")) {
|
for (const button of qa(".mark-watched__button")) {
|
||||||
new MarkWatchedButton(button)
|
new MarkWatchedButton(button)
|
||||||
|
|
|
@ -9,7 +9,6 @@ block head
|
||||||
else
|
else
|
||||||
title Error - CloudTube
|
title Error - CloudTube
|
||||||
script(type="module" src=getStaticURL("html", "/static/js/player.js"))
|
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})}
|
script const data = !{JSON.stringify({...video, continuous})}
|
||||||
|
|
||||||
block content
|
block content
|
||||||
|
@ -74,7 +73,7 @@ block content
|
||||||
a(href=`https://www.youtube.com/watch?v=${video.videoId}#cloudtube`).border-look YouTube
|
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
|
a(href=`https://redirect.invidious.io/watch?v=${video.videoId}`).border-look Invidious
|
||||||
|
|
||||||
.description#description!= video.descriptionHtml
|
.description!= video.descriptionHtml
|
||||||
|
|
||||||
//- Standard view
|
//- Standard view
|
||||||
aside(style=continuous ? "display: none" : "")#standard-related-videos.related-videos
|
aside(style=continuous ? "display: none" : "")#standard-related-videos.related-videos
|
||||||
|
|
|
@ -93,18 +93,13 @@
|
||||||
flex-shrink: 0
|
flex-shrink: 0
|
||||||
|
|
||||||
.description
|
.description
|
||||||
position: relative
|
|
||||||
font-size: 17px
|
font-size: 17px
|
||||||
line-height: 1.4
|
|
||||||
word-break: break-word
|
word-break: break-word
|
||||||
margin: 16px 4px 4px 4px
|
margin: 16px 4px 4px 4px
|
||||||
background-color: c.$bg-accent-area
|
background-color: c.$bg-accent-area
|
||||||
padding: 12px
|
padding: 12px
|
||||||
border-radius: 4px
|
border-radius: 4px
|
||||||
|
|
||||||
--regular-background: #{c.$bg-accent-area}
|
|
||||||
--highlight-background: #{c.$bg-darker}
|
|
||||||
|
|
||||||
.subscribe-form
|
.subscribe-form
|
||||||
display: inline-block
|
display: inline-block
|
||||||
|
|
||||||
|
@ -154,26 +149,3 @@
|
||||||
|
|
||||||
.actor
|
.actor
|
||||||
margin: 4px 0px 10px
|
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
|
|
||||||
|
|
|
@ -66,15 +66,8 @@ function rewriteVideoDescription(descriptionHtml, id) {
|
||||||
// https://www.youtube.com/watch?v=fhum63fAwrI www.youtube.com/watch?v=<videoid>
|
// https://www.youtube.com/watch?v=fhum63fAwrI www.youtube.com/watch?v=<videoid>
|
||||||
// https://www.youtube.com/watch?v=i-szWOrc3Mo www.youtube.com/<channelname> (unsupported by cloudtube currently)
|
// https://www.youtube.com/watch?v=i-szWOrc3Mo www.youtube.com/<channelname> (unsupported by cloudtube currently)
|
||||||
// https://www.youtube.com/watch?v=LSG71wbKpbQ www.youtube.com/channel/<id>
|
// https://www.youtube.com/watch?v=LSG71wbKpbQ www.youtube.com/channel/<id>
|
||||||
// https://www.youtube.com/watch?v=RiEkOKFOG3s youtu.be/<videoid> with params
|
|
||||||
|
|
||||||
descriptionHtml = descriptionHtml.replace(new RegExp(`<a href="https?://(?:www\\.)?youtu\\.be/(${constants.regex.video_id})[?]?([^"]*)">([^<]+)</a>`, "g"), (_, id, params, innerText) => {
|
descriptionHtml = descriptionHtml.replace(new RegExp(`<a href="https?://(?:www\\.)?youtu\\.be/(${constants.regex.video_id})([^"]*)">([^<]+)</a>`, "g"), `<a href="/watch?v=$1$2">$3</a>`)
|
||||||
if (params) {
|
|
||||||
return `<a href="/watch?v=${id}&${params}">${innerText}</a>`
|
|
||||||
} else {
|
|
||||||
return `<a href="/watch?v=${id}">${innerText}</a>`
|
|
||||||
}
|
|
||||||
})
|
|
||||||
descriptionHtml = descriptionHtml.replace(new RegExp(`<a href="https?://(?:www\\.)?youtu(?:\\.be|be\\.com)/([^"]*)">([^<]+)<\/a>`, "g"), `<a href="/$1">$2</a>`)
|
descriptionHtml = descriptionHtml.replace(new RegExp(`<a href="https?://(?:www\\.)?youtu(?:\\.be|be\\.com)/([^"]*)">([^<]+)<\/a>`, "g"), `<a href="/$1">$2</a>`)
|
||||||
descriptionHtml = descriptionHtml.replace(new RegExp(`(?:([0-9]*):)?([0-5]?[0-9]):([0-5][0-9])`, "g"), (_, hours, minutes, seconds) => {
|
descriptionHtml = descriptionHtml.replace(new RegExp(`(?:([0-9]*):)?([0-5]?[0-9]):([0-5][0-9])`, "g"), (_, hours, minutes, seconds) => {
|
||||||
let timeURL, timeDisplay, timeSeconds
|
let timeURL, timeDisplay, timeSeconds
|
||||||
|
|
Loading…
Reference in New Issue