aboutsummaryrefslogtreecommitdiffstats
path: root/youtube
diff options
context:
space:
mode:
authorJesús <heckyel@hyperbola.info>2021-08-29 22:43:10 -0500
committerJesús <heckyel@hyperbola.info>2021-08-29 22:43:10 -0500
commit309ff409436a5a016c33f71f8b483d9ed226aaaf (patch)
treebd42edc063787b274e317e6dd98a0ee909879322 /youtube
parent56b17c634ce629b6d84a4118de14b426cc7955ba (diff)
downloadyt-local-309ff409436a5a016c33f71f8b483d9ed226aaaf.tar.lz
yt-local-309ff409436a5a016c33f71f8b483d9ed226aaaf.tar.xz
yt-local-309ff409436a5a016c33f71f8b483d9ed226aaaf.zip
watch.html: Move loose inline javascript into watch.js
The number of inline code blocks and the dependencies between them became unmanageable. From 9d96c07a3c2e68f1893634574c3be64e41a2c041 Mon Sep 17 00:00:00 2001 From: James Taylor <user234683@users.noreply.github.com>
Diffstat (limited to 'youtube')
-rw-r--r--youtube/static/js/av-merge.js7
-rw-r--r--youtube/static/js/speedyplay.js13
-rw-r--r--youtube/static/js/watch.js201
-rw-r--r--youtube/templates/watch.html219
-rw-r--r--youtube/watch.py5
5 files changed, 209 insertions, 236 deletions
diff --git a/youtube/static/js/av-merge.js b/youtube/static/js/av-merge.js
index 3831bcc..f6ea007 100644
--- a/youtube/static/js/av-merge.js
+++ b/youtube/static/js/av-merge.js
@@ -19,13 +19,6 @@
// TODO: Call abort to cancel in-progress appends?
-
-var avMerge;
-
-function avInitialize(...args){
- avMerge = new AVMerge(...args);
-}
-
function AVMerge(video, srcPair, startTime){
this.videoSource = srcPair[0];
this.audioSource = srcPair[1];
diff --git a/youtube/static/js/speedyplay.js b/youtube/static/js/speedyplay.js
deleted file mode 100644
index 58b5d33..0000000
--- a/youtube/static/js/speedyplay.js
+++ /dev/null
@@ -1,13 +0,0 @@
-(function main() {
- 'use strict';
- const video = document.getElementById('js-video-player');
- const speedInput = document.getElementById('speed-control');
- speedInput.addEventListener('keyup', (event) => {
- if (event.key === 'Enter') {
- let speed = parseFloat(speedInput.value);
- if(!isNaN(speed)){
- video.playbackRate = speed;
- }
- }
- });
-}());
diff --git a/youtube/static/js/watch.js b/youtube/static/js/watch.js
new file mode 100644
index 0000000..38aab3f
--- /dev/null
+++ b/youtube/static/js/watch.js
@@ -0,0 +1,201 @@
+var video = document.getElementById('js-video-player');
+
+function changeQuality(selection) {
+ var currentVideoTime = video.currentTime;
+ var videoPaused = video.paused;
+ var videoSpeed = video.playbackRate;
+ var videoSource;
+ if (avMerge)
+ avMerge.close();
+ if (selection.type == 'uni'){
+ videoSource = data['uni_sources'][selection.index];
+ video.src = videoSource.url;
+ } else {
+ let srcPair = data['pair_sources'][selection.index];
+ videoSource = srcPair[0];
+ avMerge = new AVMerge(video, srcPair, currentVideoTime);
+ }
+ video.currentTime = currentVideoTime;
+ if (!videoPaused){
+ video.play();
+ }
+ video.playbackRate = videoSpeed;
+}
+
+// Initialize av-merge
+var avMerge;
+if (data.using_pair_sources) {
+ var srcPair = data['pair_sources'][data['pair_idx']];
+ var videoSource = srcPair[0];
+ // Do it dynamically rather than as the default in jinja
+ // in case javascript is disabled
+ avMerge = new AVMerge(video, srcPair, 0);
+}
+
+// Quality selector
+document.getElementById('quality-select').addEventListener(
+ 'change', function(e) {
+ changeQuality(JSON.parse(this.value))
+ }
+);
+
+// Set up video start time from &t parameter
+if (data.time_start != 0 && video)
+ video.currentTime = data.time_start;
+
+// External video speed control
+var speedInput = document.getElementById('speed-control');
+speedInput.addEventListener('keyup', (event) => {
+ if (event.key === 'Enter') {
+ var speed = parseFloat(speedInput.value);
+ if(!isNaN(speed)){
+ video.playbackRate = speed;
+ }
+ }
+});
+
+
+// Playlist lazy image loading
+if (data.playlist && data.playlist['id'] !== null) {
+ // lazy load playlist images
+ // copied almost verbatim from
+ // https://css-tricks.com/tips-for-rolling-your-own-lazy-loading/
+ // IntersectionObserver isn't supported in pre-quantum
+ // firefox versions, but the alternative of making it
+ // manually is a performance drain, so oh well
+ var observer = new IntersectionObserver(lazyLoad, {
+
+ // where in relation to the edge of the viewport, we are observing
+ rootMargin: "100px",
+
+ // how much of the element needs to have intersected
+ // in order to fire our loading function
+ threshold: 1.0
+
+ });
+
+ function lazyLoad(elements) {
+ elements.forEach(item => {
+ if (item.intersectionRatio > 0) {
+
+ // set the src attribute to trigger a load
+ item.target.src = item.target.dataset.src;
+
+ // stop observing this element. Our work here is done!
+ observer.unobserve(item.target);
+ };
+ });
+ };
+
+ // Tell our observer to observe all img elements with a "lazy" class
+ var lazyImages = document.querySelectorAll('img.lazy');
+ lazyImages.forEach(img => {
+ observer.observe(img);
+ });
+}
+
+
+// Autoplay
+if (data.settings.related_videos_mode !== 0 || data.playlist !== null) {
+ let playability_error = !!data.playability_error;
+ let isPlaylist = false;
+ if (data.playlist !== null && data.playlist['current_index'] !== null)
+ isPlaylist = true;
+
+ // read cookies on whether to autoplay
+ // https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie
+ let cookieValue;
+ let playlist_id;
+ if (isPlaylist) {
+ // from https://stackoverflow.com/a/6969486
+ function escapeRegExp(string) {
+ // $& means the whole matched string
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ }
+ playlist_id = data.playlist['id'];
+ playlist_id = escapeRegExp(playlist_id);
+
+ cookieValue = document.cookie.replace(new RegExp(
+ '(?:(?:^|.*;\\s*)autoplay_'
+ + playlist_id + '\\s*\\=\\s*([^;]*).*$)|^.*$'
+ ), '$1');
+ } else {
+ cookieValue = document.cookie.replace(new RegExp(
+ '(?:(?:^|.*;\\s*)autoplay\\s*\\=\\s*([^;]*).*$)|^.*$'
+ ),'$1');
+ }
+
+ let autoplayEnabled = 0;
+ if(cookieValue.length === 0){
+ autoplayEnabled = 0;
+ } else {
+ autoplayEnabled = Number(cookieValue);
+ }
+
+ // check the checkbox if autoplay is on
+ let checkbox = document.querySelector('.autoplay-toggle');
+ if(autoplayEnabled){
+ checkbox.checked = true;
+ }
+
+ // listen for checkbox to turn autoplay on and off
+ let cookie = 'autoplay'
+ if (isPlaylist)
+ cookie += '_' + playlist_id;
+
+ checkbox.addEventListener( 'change', function() {
+ if(this.checked) {
+ autoplayEnabled = 1;
+ document.cookie = cookie + '=1; SameSite=Strict';
+ } else {
+ autoplayEnabled = 0;
+ document.cookie = cookie + '=0; SameSite=Strict';
+ }
+ });
+
+ if(!playability_error){
+ // play the video if autoplay is on
+ if(autoplayEnabled){
+ video.play();
+ }
+ }
+
+ // determine next video url
+ let nextVideoUrl;
+ if (isPlaylist) {
+ let currentIndex = data.playlist['current_index'];
+ if (data.playlist['current_index']+1 == data.playlist['items'].length)
+ nextVideoUrl = null;
+ else
+ nextVideoUrl = data.playlist['items'][data.playlist['current_index']+1]['url'];
+
+ // scroll playlist to proper position
+ // item height + gap == 100
+ let pl = document.querySelector('.playlist-videos');
+ pl.scrollTop = 100*currentIndex;
+ } else {
+ if (data.related.length === 0)
+ nextVideoUrl = null;
+ else
+ nextVideoUrl = data.related[0]['url'];
+ }
+ let nextVideoDelay = 1000;
+
+ // go to next video when video ends
+ // https://stackoverflow.com/a/2880950
+ if (nextVideoUrl) {
+ if(playability_error){
+ videoEnded();
+ } else {
+ video.addEventListener('ended', videoEnded, false);
+ }
+ function nextVideo(){
+ if(autoplayEnabled){
+ window.location.href = nextVideoUrl;
+ }
+ }
+ function videoEnded(e) {
+ window.setTimeout(nextVideo, nextVideoDelay);
+ }
+ }
+}
diff --git a/youtube/templates/watch.html b/youtube/templates/watch.html
index 4b2aa50..5b0fce5 100644
--- a/youtube/templates/watch.html
+++ b/youtube/templates/watch.html
@@ -54,49 +54,6 @@
{% endfor %}
</video>
</figure>
-
- <script src="/youtube.com/static/js/av-merge.js"></script>
- <script>
- function changeQuality(selection) {
- var video = document.getElementById('js-video-player');
- var currentVideoTime = video.currentTime;
- var videoPaused = video.paused;
- var videoSpeed = video.playbackRate;
- var videoSource;
- if (avMerge)
- avMerge.close();
- if (selection.type == 'uni'){
- videoSource = data['uni_sources'][selection.index];
- video.src = videoSource.url;
- } else {
- let srcPair = data['pair_sources'][selection.index];
- videoSource = srcPair[0];
- avInitialize(video, srcPair, currentVideoTime);
- }
- video.currentTime = currentVideoTime;
- if (!videoPaused){
- video.play();
- }
- video.playbackRate = videoSpeed;
- }
- </script>
- {% if using_pair_sources %}
- <!-- Initialize av-merge -->
- <script>
- var srcPair = data['pair_sources'][data['pair_idx']];
- var video = document.getElementById('js-video-player');
- var videoSource = srcPair[0];
- // Do it dynamically rather than as the default in jinja
- // in case javascript is disabled
- avInitialize(video, srcPair, 0);
- </script>
- {% endif %}
-
- {% if time_start != 0 %}
- <script>
- document.getElementById('js-video-player').currentTime = {{ time_start|tojson }};
- </script>
- {% endif %}
{% endif %}
<div class="sc-info">
@@ -125,7 +82,6 @@
<div class="external-player-controls">
<input class="speed" id="speed-control" type="text" title="Video speed">
- <script src="/youtube.com/static/js/speedyplay.js"></script>
<select id="quality-select" autocomplete="off">
{% for src in uni_sources %}
<option value='{"type": "uni", "index": {{ loop.index0 }}}' {{ 'selected' if loop.index0 == uni_idx and not using_pair_sources else '' }} >{{ src['quality_string'] }}</option>
@@ -134,13 +90,6 @@
<option value='{"type": "pair", "index": {{ loop.index0}}}' {{ 'selected' if loop.index0 == pair_idx and using_pair_sources else '' }} >{{ src_pair[0]['quality_string'] }}, {{ src_pair[1]['quality_string'] }}</option>
{% endfor %}
</select>
- <script>
- document.getElementById('quality-select').addEventListener(
- 'change', function(e) {
- changeQuality(JSON.parse(this.value))
- }
- );
- </script>
</div>
<input class="v-checkbox" name="video_info_list" value="{{ video_info }}" form="playlist-edit" type="checkbox">
@@ -212,7 +161,7 @@
<div class="playlist-header">
<a href="{{ playlist['url'] }}" title="{{ playlist['title'] }}"><h3>{{ playlist['title'] }}</h3></a>
<ul class="playlist-metadata">
- <li><label for="playlist-autoplay-toggle">Autoplay: </label><input type="checkbox" id="playlist-autoplay-toggle"></li>
+ <li><label for="playlist-autoplay-toggle">Autoplay: </label><input type="checkbox" class="autoplay-toggle"></li>
{% if playlist['current_index'] is none %}
<li>[Error!]/{{ playlist['video_count'] }}</li>
{% else %}
@@ -233,172 +182,10 @@
{% endif %}
{% endfor %}
</nav>
- {% if playlist['id'] is not none %}
- <script>
- // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
- // lazy load playlist images
- // copied almost verbatim from
- // https://css-tricks.com/tips-for-rolling-your-own-lazy-loading/
- // IntersectionObserver isn't supported in pre-quantum
- // firefox versions, but the alternative of making it
- // manually is a performance drain, so oh well
- let observer = new IntersectionObserver(lazyLoad, {
-
- // where in relation to the edge of the viewport, we are observing
- rootMargin: "100px",
- // how much of the element needs to have intersected
- // in order to fire our loading function
- threshold: 1.0
- });
-
- function lazyLoad(elements) {
- elements.forEach(item => {
- if (item.intersectionRatio > 0) {
- // set the src attribute to trigger a load
- item.target.src = item.target.dataset.src;
- // stop observing this element. Our work here is done!
- observer.unobserve(item.target);
- };
- });
- };
-
- // Tell our observer to observe all img elements with a "lazy" class
- let lazyImages = document.querySelectorAll('img.lazy');
- lazyImages.forEach(img => {
- observer.observe(img);
- });
- // @license-end
- </script>
- {% endif %}
</div>
{% elif settings.related_videos_mode != 0 %}
- <div class="related-autoplay"><label for="related-autoplay-toggle">Autoplay: </label><input type="checkbox" id="related-autoplay-toggle"></div>
- {% endif %}
-
- {% if settings.related_videos_mode != 0 or playlist %}
- <script>
- // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
- let playability_error = {{ 'true' if playability_error else 'false' }};
- {% if playlist and playlist['current_index'] is not none %}
- {% set isPlaylist = true %}
- {% endif %}
-
- {% if isPlaylist %}
- // from https://stackoverflow.com/a/6969486
- function escapeRegExp(string) {
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
- }
- let playlist_id = {{ playlist['id']|tojson }};
- playlist_id = escapeRegExp(playlist_id);
- {% endif %}
-
- // read cookies on whether to autoplay
- // pain in the ass:
- // https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie
- {% if isPlaylist %}
- let cookieValue = document.cookie.replace(new RegExp(
- '(?:(?:^|.*;\\s*)autoplay_' + playlist_id + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1');
- {% else %}
- let cookieValue = document.cookie.replace(new RegExp(
- '(?:(?:^|.*;\\s*)autoplay\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1');
- {% endif %}
-
- let autoplayEnabled = 0;
- if(cookieValue.length === 0){
- autoplayEnabled = 0;
- } else {
- autoplayEnabled = Number(cookieValue);
- }
-
- // check the autoplay checkbox if autoplay is on
- {% if isPlaylist %}
- let PlaylistAutoplayCheck = document.getElementById('playlist-autoplay-toggle');
- if(autoplayEnabled){
- PlaylistAutoplayCheck.checked = true;
- }
- {% else %}
- let RelatedAutoplayCheck = document.getElementById('related-autoplay-toggle');
- if(autoplayEnabled){
- RelatedAutoplayCheck.checked = true;
- }
- {% endif %}
-
- // listen for checkbox to turn autoplay on and off
- let cookie = 'autoplay'
- {% if isPlaylist %}
- cookie += '_' + playlist_id;
- PlaylistAutoplayCheck.addEventListener( 'change', function() {
- if(this.checked) {
- autoplayEnabled = 1;
- document.cookie = cookie + '=1; SameSite=Strict';
- } else {
- autoplayEnabled = 0;
- document.cookie = cookie + '=0; SameSite=Strict';
- }
- });
- {% else %}
- RelatedAutoplayCheck.addEventListener( 'change', function() {
- if(this.checked) {
- autoplayEnabled = 1;
- document.cookie = cookie + '=1; SameSite=Strict';
- } else {
- autoplayEnabled = 0;
- document.cookie = cookie + '=0; SameSite=Strict';
- }
- });
- {% endif %}
-
- const vid = document.getElementById('js-video-player');
- if(!playability_error){
- // play the video if autoplay is on
- if(autoplayEnabled){
- vid.play();
- }
- }
-
- // determine next video url
- {% if isPlaylist %}
- let currentIndex = {{ playlist['current_index']|tojson }};
- {% if playlist['current_index']+1 == playlist['items']|length %}
- let nextVideoUrl = null;
- {% else %}
- let nextVideoUrl = {{ (playlist['items'][playlist['current_index']+1]['url'])|tojson }};
- {% endif %}
-
- // scroll playlist to proper position
- // item height + gap == 100
- let pl = document.querySelector('.playlist-videos');
- pl.scrollTop = 100*currentIndex;
- {% else %}
- {% if related|length == 0 %}
- let nextVideoUrl = null;
- {% else %}
- let nextVideoUrl = {{ (related[0]['url'])|tojson }};
- {% endif %}
- {% endif %}
- let nextVideoDelay = 1000;
-
- // go to next video when video ends
- // https://stackoverflow.com/a/2880950
- if (nextVideoUrl) {
- if(playability_error){
- videoEnded();
- } else {
- vid.addEventListener('ended', videoEnded, false);
- }
- function nextVideo(){
- if(autoplayEnabled){
- window.location.href = nextVideoUrl;
- }
- }
- function videoEnded(e) {
- window.setTimeout(nextVideo, nextVideoDelay);
- }
- }
- // @license-end
- </script>
+ <div class="related-autoplay"><label for="related-autoplay-toggle">Autoplay: </label><input type="checkbox" class="autoplay-toggle"></div>
{% endif %}
- <!-- /playlist -->
{% if subtitle_sources %}
<details id="transcript-details">
@@ -448,6 +235,8 @@
</div>
+ <script src="/youtube.com/static/js/av-merge.js"></script>
+ <script src="/youtube.com/static/js/watch.js"></script>
<script src="/youtube.com/static/js/common.js"></script>
<script src="/youtube.com/static/js/transcript-table.js"></script>
{% if settings.use_video_player == 2 %}
diff --git a/youtube/watch.py b/youtube/watch.py
index e397574..5bb3341 100644
--- a/youtube/watch.py
+++ b/youtube/watch.py
@@ -654,7 +654,6 @@ def get_watch_page(video_id=None):
invidious_reload_button = info['invidious_reload_button'],
video_url = util.URL_ORIGIN + '/watch?v=' + video_id,
video_id = video_id,
- time_start = time_start,
js_data = {
'video_id': info['id'],
@@ -663,6 +662,10 @@ def get_watch_page(video_id=None):
'has_manual_captions': any(s.get('on') for s in subtitle_sources),
**source_info,
'using_pair_sources': using_pair_sources,
+ 'time_start': time_start,
+ 'playlist': info['playlist'],
+ 'related': info['related_videos'],
+ 'playability_error': info['playability_error'],
},
font_family=youtube.font_choices[settings.font],
**source_info,