mirror of
				https://git.sr.ht/~cadence/cloudtube
				synced 2025-10-31 20:28:02 +00:00 
			
		
		
		
	Highlight current chapter in video description
This commit is contained in:
		
							parent
							
								
									eb111a44c4
								
							
						
					
					
						commit
						f62fce4fea
					
				| @ -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")) | ||||
|  | ||||
							
								
								
									
										53
									
								
								html/static/js/chapter-highlight.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								html/static/js/chapter-highlight.js
									
									
									
									
									
										Normal file
									
								
							| @ -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) | ||||
| @ -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") | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user