mirror of
https://git.sr.ht/~cadence/cloudtube
synced 2024-11-14 04:17:29 +00:00
Implement continuous mode
This commit is contained in:
parent
e4f6ffe122
commit
2b2f8bf84a
30
api/video.js
30
api/video.js
@ -183,21 +183,35 @@ module.exports = [
|
||||
const user = getUser(req)
|
||||
const settings = user.getSettingsOrDefaults()
|
||||
const id = url.searchParams.get("v")
|
||||
|
||||
// Media fragment
|
||||
const t = url.searchParams.get("t")
|
||||
let mediaFragment = converters.tToMediaFragment(t)
|
||||
|
||||
// Continuous mode
|
||||
const continuous = url.searchParams.get("continuous") === "1"
|
||||
const swp = url.searchParams.get("session-watched")
|
||||
const sessionWatched = swp ? swp.split(" ") : []
|
||||
const sessionWatchedNext = sessionWatched.concat([id]).join("+")
|
||||
if (continuous) settings.quality = 0 // autoplay with synced streams does not work
|
||||
|
||||
if (req.method === "GET") {
|
||||
if (settings.local) {
|
||||
if (settings.local) { // skip to the local fetching page, which will then POST video data in a moment
|
||||
return render(200, "pug/local-video.pug", {id})
|
||||
}
|
||||
const instanceOrigin = settings.instance
|
||||
const outURL = `${instanceOrigin}/api/v1/videos/${id}`
|
||||
const video = await request(outURL).then(res => res.json())
|
||||
return renderVideo(video, {user, settings, id, instanceOrigin}, {mediaFragment})
|
||||
var instanceOrigin = settings.instance
|
||||
var outURL = `${instanceOrigin}/api/v1/videos/${id}`
|
||||
var video = await request(outURL).then(res => res.json())
|
||||
} else { // req.method === "POST"
|
||||
const video = JSON.parse(new URLSearchParams(body.toString()).get("video"))
|
||||
const instanceOrigin = "http://localhost:3000"
|
||||
return renderVideo(video, {user, settings, id, instanceOrigin}, {mediaFragment})
|
||||
var instanceOrigin = "http://localhost:3000"
|
||||
var video = JSON.parse(new URLSearchParams(body.toString()).get("video"))
|
||||
}
|
||||
|
||||
return renderVideo(video, {
|
||||
user, settings, id, instanceOrigin
|
||||
}, {
|
||||
mediaFragment, continuous, sessionWatched, sessionWatchedNext
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
34
html/static/js/continuous.js
Normal file
34
html/static/js/continuous.js
Normal file
@ -0,0 +1,34 @@
|
||||
import {q, ejs, ElemJS} from "/static/js/elemjs/elemjs.js"
|
||||
|
||||
const video = q("#video")
|
||||
|
||||
console.log
|
||||
|
||||
video.addEventListener("ended", () => {
|
||||
if (data.continuous) {
|
||||
const first = data.recommendedVideos[0]
|
||||
window.location.assign(`/watch?v=${first.videoId}&continuous=1`)
|
||||
}
|
||||
})
|
||||
|
||||
class ContinuousControls extends ElemJS {
|
||||
constructor() {
|
||||
super(q("#continuous-controls"))
|
||||
this.button = ejs(q("#continuous-stop"))
|
||||
this.button.on("click", this.onClick.bind(this))
|
||||
}
|
||||
|
||||
onClick(event) {
|
||||
event.preventDefault()
|
||||
this.element.style.display = "none"
|
||||
data.continuous = false
|
||||
q("#continuous-related-videos").remove()
|
||||
q("#standard-related-videos").style.display = ""
|
||||
const url = new URL(location)
|
||||
url.searchParams.delete("continuous")
|
||||
url.searchParams.delete("session-watched")
|
||||
history.replaceState(null, "", url.toString())
|
||||
}
|
||||
}
|
||||
|
||||
new ContinuousControls(q("#continuous-stop"))
|
@ -1,6 +1,8 @@
|
||||
mixin video_list_item(className, video, instanceOrigin, options = {})
|
||||
div(class={[className]: true, "video-list-item--watched": video.watched})
|
||||
- let link = `/watch?v=${video.videoId}`
|
||||
if options.continuous
|
||||
- link += `&continuous=1&session-watched=${sessionWatchedNext}`
|
||||
a(href=link tabindex="-1").thumbnail
|
||||
img(src=`/vi/${video.videoId}/mqdefault.jpg` width=320 height=180 alt="").image
|
||||
if video.second__lengthText != undefined
|
||||
|
@ -9,16 +9,22 @@ block head
|
||||
else
|
||||
title Error - CloudTube
|
||||
script(type="module" src=getStaticURL("html", "/static/js/player.js"))
|
||||
script const data = !{JSON.stringify(video)}
|
||||
script const data = !{JSON.stringify({...video, continuous})}
|
||||
|
||||
block content
|
||||
unless error
|
||||
if continuous
|
||||
- const first = video.recommendedVideos[0]
|
||||
if first
|
||||
script(type="module" src=getStaticURL("html", "/static/js/continuous.js"))
|
||||
noscript
|
||||
meta(http-equiv="refresh" content=`${video.lengthSeconds+5};url=/watch?v=${first.videoId}&continuous=1`)
|
||||
main.video-page
|
||||
.main-video-section
|
||||
.video-container
|
||||
- const format = formats[0]
|
||||
if format
|
||||
video(controls preload="auto" width=format.second__width height=format.second__height data-itag=format.itag)#video.video
|
||||
video(controls preload="auto" width=format.second__width height=format.second__height data-itag=format.itag autoplay=continuous)#video.video
|
||||
source(src=format.url+mediaFragment type=format.type)
|
||||
each t in video.captions
|
||||
track(label=t.label kind="subtitles" srclang=t.languageCode src=t.url)
|
||||
@ -44,6 +50,15 @@ block content
|
||||
#live-event-notice
|
||||
#audio-loading-display
|
||||
|
||||
if continuous
|
||||
div#continuous-controls.continuous
|
||||
.continuous__description
|
||||
.continuous__title Continuous mode: next video autoplays
|
||||
noscript
|
||||
.continuous__script-warning Without JavaScript, it will trigger on a timer, not on video completion.
|
||||
.continuous__buttons
|
||||
a(href=`/watch?v=${video.videoId}`)#continuous-stop.border-look Turn off
|
||||
|
||||
.button-container
|
||||
+subscribe_button(video.authorId, subscribed, `/watch?v=${video.videoId}`).border-look
|
||||
//- button.border-look#theatre Theatre
|
||||
@ -60,11 +75,29 @@ block content
|
||||
|
||||
.description!= video.descriptionHtml
|
||||
|
||||
aside.related-videos
|
||||
//- Standard view
|
||||
aside(style=continuous ? "display: none" : "")#standard-related-videos.related-videos
|
||||
.related-cols
|
||||
h2.related-header Related videos
|
||||
.continuous-start
|
||||
a(href=`/watch?v=${video.videoId}&continuous=1` nofollow) Continuous mode
|
||||
each r in video.recommendedVideos
|
||||
+video_list_item("related-video", r, instanceOrigin)
|
||||
|
||||
//- Continuous view
|
||||
if continuous
|
||||
aside.related-videos#continuous-related-videos
|
||||
- let column = video.recommendedVideos.filter(v => !sessionWatched.includes(v.videoId))
|
||||
if column.length
|
||||
.related-cols
|
||||
h2.related-header Autoplay next
|
||||
+video_list_item("related-video", column.shift(), instanceOrigin, {continuous: true})
|
||||
if column.length
|
||||
.related-cols
|
||||
h2.related-header Related videos
|
||||
each r in column
|
||||
+video_list_item("related-video", r, instanceOrigin, {continuous: true}) // keep on continuous mode for all recommendations
|
||||
|
||||
else
|
||||
//- error
|
||||
main.video-error-page
|
||||
|
@ -8,6 +8,7 @@ $bg-accent-area: #44474b
|
||||
$fg-bright: #fff
|
||||
$fg-main: #ddd
|
||||
$fg-dim: #bbb
|
||||
$fg-warning: #ffb98f
|
||||
|
||||
$edge-grey: #808080
|
||||
|
||||
|
@ -69,6 +69,29 @@
|
||||
border-radius: 3px
|
||||
background: linear-gradient(to right, #1a1 var(--rating), #bbb var(--rating))
|
||||
|
||||
.continuous
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: space-between
|
||||
margin: 16px 4px
|
||||
padding: 12px
|
||||
border-radius: 4px
|
||||
background-color: c.$bg-darkest
|
||||
|
||||
&__description
|
||||
margin-left: 12px
|
||||
|
||||
&__title
|
||||
font-size: 20px
|
||||
|
||||
&__script-warning
|
||||
font-size: 15px
|
||||
color: c.$fg-warning
|
||||
|
||||
&__buttons
|
||||
display: flex
|
||||
flex-shrink: 0
|
||||
|
||||
.description
|
||||
font-size: 17px
|
||||
word-break: break-word
|
||||
@ -80,8 +103,17 @@
|
||||
.subscribe-form
|
||||
display: inline-block
|
||||
|
||||
.related-cols
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: space-between
|
||||
margin-bottom: 8px
|
||||
|
||||
.continuous-start
|
||||
font-size: 15px
|
||||
|
||||
.related-header
|
||||
margin: 4px 0px 12px 2px
|
||||
margin: 4px 0px 4px 2px
|
||||
font-weight: normal
|
||||
font-size: 26px
|
||||
|
||||
|
@ -7,7 +7,7 @@ let constants = {
|
||||
user_settings: {
|
||||
instance: {
|
||||
type: "string",
|
||||
default: "https://second.cadence.moe"
|
||||
default: "http://localhost:3000"
|
||||
},
|
||||
save_history: {
|
||||
type: "boolean",
|
||||
|
Loading…
Reference in New Issue
Block a user