Formatting

This commit is contained in:
rockerBOO 2025-04-30 20:41:51 -04:00
parent 1f7ce1890a
commit 70b36ed1a1
No known key found for this signature in database
GPG Key ID: 0D4EAF00DCABC97B
19 changed files with 4429 additions and 1583 deletions

View File

@ -1,254 +1,273 @@
'use strict';
"use strict";
// Contains only auxiliary methods
// May be included and executed unlimited number of times without any consequences
// Polyfills for IE11
Array.prototype.find = Array.prototype.find || function (condition) {
Array.prototype.find =
Array.prototype.find ||
function (condition) {
return this.filter(condition)[0];
};
};
Array.from = Array.from || function (source) {
Array.from =
Array.from ||
function (source) {
return Array.prototype.slice.call(source);
};
NodeList.prototype.forEach = NodeList.prototype.forEach || function (callback) {
};
NodeList.prototype.forEach =
NodeList.prototype.forEach ||
function (callback) {
Array.from(this).forEach(callback);
};
String.prototype.includes = String.prototype.includes || function (searchString) {
};
String.prototype.includes =
String.prototype.includes ||
function (searchString) {
return this.indexOf(searchString) >= 0;
};
String.prototype.startsWith = String.prototype.startsWith || function (prefix) {
};
String.prototype.startsWith =
String.prototype.startsWith ||
function (prefix) {
return this.substr(0, prefix.length) === prefix;
};
Math.sign = Math.sign || function(x) {
};
Math.sign =
Math.sign ||
function (x) {
x = +x;
if (!x) return x; // 0 and NaN
return x > 0 ? 1 : -1;
};
if (!window.hasOwnProperty('HTMLDetailsElement') && !window.hasOwnProperty('mockHTMLDetailsElement')) {
window.mockHTMLDetailsElement = true;
const style = 'details:not([open]) > :not(summary) {display: none}';
document.head.appendChild(document.createElement('style')).textContent = style;
};
if (
!window.hasOwnProperty("HTMLDetailsElement") &&
!window.hasOwnProperty("mockHTMLDetailsElement")
) {
window.mockHTMLDetailsElement = true;
const style = "details:not([open]) > :not(summary) {display: none}";
document.head.appendChild(document.createElement("style")).textContent =
style;
addEventListener('click', function (e) {
if (e.target.nodeName !== 'SUMMARY') return;
const details = e.target.parentElement;
if (details.hasAttribute('open'))
details.removeAttribute('open');
else
details.setAttribute('open', '');
});
addEventListener("click", function (e) {
if (e.target.nodeName !== "SUMMARY") return;
const details = e.target.parentElement;
if (details.hasAttribute("open")) details.removeAttribute("open");
else details.setAttribute("open", "");
});
}
// Monstrous global variable for handy code
// Includes: clamp, xhr, storage.{get,set,remove}
window.helpers = window.helpers || {
/**
* https://en.wikipedia.org/wiki/Clamping_(graphics)
* @param {Number} num Source number
* @param {Number} min Low border
* @param {Number} max High border
* @returns {Number} Clamped value
*/
clamp: function (num, min, max) {
if (max < min) {
var t = max; max = min; min = t; // swap max and min
/**
* https://en.wikipedia.org/wiki/Clamping_(graphics)
* @param {Number} num Source number
* @param {Number} min Low border
* @param {Number} max High border
* @returns {Number} Clamped value
*/
clamp: function (num, min, max) {
if (max < min) {
var t = max;
max = min;
min = t; // swap max and min
}
if (max < num) return max;
if (min > num) return min;
return num;
},
/** @private */
_xhr: function (method, url, options, callbacks) {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
// Default options
xhr.responseType = "json";
xhr.timeout = 10000;
// Default options redefining
if (options.responseType) xhr.responseType = options.responseType;
if (options.timeout) xhr.timeout = options.timeout;
if (method === "POST")
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// better than onreadystatechange because of 404 codes https://stackoverflow.com/a/36182963
xhr.onloadend = function () {
if (xhr.status === 200) {
if (callbacks.on200) {
// fix for IE11. It doesn't convert response to JSON
if (xhr.responseType === "" && typeof xhr.response === "string")
callbacks.on200(JSON.parse(xhr.response));
else callbacks.on200(xhr.response);
}
} else {
// handled by onerror
if (xhr.status === 0) return;
if (max < num)
return max;
if (min > num)
return min;
return num;
},
if (callbacks.onNon200) callbacks.onNon200(xhr);
}
};
/** @private */
_xhr: function (method, url, options, callbacks) {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.ontimeout = function () {
if (callbacks.onTimeout) callbacks.onTimeout(xhr);
};
// Default options
xhr.responseType = 'json';
xhr.timeout = 10000;
// Default options redefining
if (options.responseType)
xhr.responseType = options.responseType;
if (options.timeout)
xhr.timeout = options.timeout;
xhr.onerror = function () {
if (callbacks.onError) callbacks.onError(xhr);
};
if (method === 'POST')
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
if (options.payload) xhr.send(options.payload);
else xhr.send();
},
/** @private */
_xhrRetry: function (method, url, options, callbacks) {
if (options.retries <= 0) {
console.warn("Failed to pull", options.entity_name);
if (callbacks.onTotalFail) callbacks.onTotalFail();
return;
}
helpers._xhr(method, url, options, callbacks);
},
/**
* @callback callbackXhrOn200
* @param {Object} response - xhr.response
*/
/**
* @callback callbackXhrError
* @param {XMLHttpRequest} xhr
*/
/**
* @param {'GET'|'POST'} method - 'GET' or 'POST'
* @param {String} url - URL to send request to
* @param {Object} options - other XHR options
* @param {XMLHttpRequestBodyInit} [options.payload=null] - payload for POST-requests
* @param {'arraybuffer'|'blob'|'document'|'json'|'text'} [options.responseType=json]
* @param {Number} [options.timeout=10000]
* @param {Number} [options.retries=1]
* @param {String} [options.entity_name='unknown'] - string to log
* @param {Number} [options.retry_timeout=1000]
* @param {Object} callbacks - functions to execute on events fired
* @param {callbackXhrOn200} [callbacks.on200]
* @param {callbackXhrError} [callbacks.onNon200]
* @param {callbackXhrError} [callbacks.onTimeout]
* @param {callbackXhrError} [callbacks.onError]
* @param {callbackXhrError} [callbacks.onTotalFail] - if failed after all retries
*/
xhr: function (method, url, options, callbacks) {
if (!options.retries || options.retries <= 1) {
helpers._xhr(method, url, options, callbacks);
return;
}
// better than onreadystatechange because of 404 codes https://stackoverflow.com/a/36182963
xhr.onloadend = function () {
if (xhr.status === 200) {
if (callbacks.on200) {
// fix for IE11. It doesn't convert response to JSON
if (xhr.responseType === '' && typeof(xhr.response) === 'string')
callbacks.on200(JSON.parse(xhr.response));
else
callbacks.on200(xhr.response);
}
} else {
// handled by onerror
if (xhr.status === 0) return;
if (callbacks.onNon200)
callbacks.onNon200(xhr);
}
};
xhr.ontimeout = function () {
if (callbacks.onTimeout)
callbacks.onTimeout(xhr);
};
xhr.onerror = function () {
if (callbacks.onError)
callbacks.onError(xhr);
};
if (options.payload)
xhr.send(options.payload);
else
xhr.send();
},
/** @private */
_xhrRetry: function(method, url, options, callbacks) {
if (options.retries <= 0) {
console.warn('Failed to pull', options.entity_name);
if (callbacks.onTotalFail)
callbacks.onTotalFail();
return;
}
helpers._xhr(method, url, options, callbacks);
},
/**
* @callback callbackXhrOn200
* @param {Object} response - xhr.response
*/
/**
* @callback callbackXhrError
* @param {XMLHttpRequest} xhr
*/
/**
* @param {'GET'|'POST'} method - 'GET' or 'POST'
* @param {String} url - URL to send request to
* @param {Object} options - other XHR options
* @param {XMLHttpRequestBodyInit} [options.payload=null] - payload for POST-requests
* @param {'arraybuffer'|'blob'|'document'|'json'|'text'} [options.responseType=json]
* @param {Number} [options.timeout=10000]
* @param {Number} [options.retries=1]
* @param {String} [options.entity_name='unknown'] - string to log
* @param {Number} [options.retry_timeout=1000]
* @param {Object} callbacks - functions to execute on events fired
* @param {callbackXhrOn200} [callbacks.on200]
* @param {callbackXhrError} [callbacks.onNon200]
* @param {callbackXhrError} [callbacks.onTimeout]
* @param {callbackXhrError} [callbacks.onError]
* @param {callbackXhrError} [callbacks.onTotalFail] - if failed after all retries
*/
xhr: function(method, url, options, callbacks) {
if (!options.retries || options.retries <= 1) {
helpers._xhr(method, url, options, callbacks);
return;
}
if (!options.entity_name) options.entity_name = 'unknown';
if (!options.retry_timeout) options.retry_timeout = 1000;
const retries_total = options.retries;
let currentTry = 1;
const retry = function () {
console.warn('Pulling ' + options.entity_name + ' failed... ' + (currentTry++) + '/' + retries_total);
setTimeout(function () {
options.retries--;
helpers._xhrRetry(method, url, options, callbacks);
}, options.retry_timeout);
};
// Pack retry() call into error handlers
callbacks._onError = callbacks.onError;
callbacks.onError = function (xhr) {
if (callbacks._onError)
callbacks._onError(xhr);
retry();
};
callbacks._onTimeout = callbacks.onTimeout;
callbacks.onTimeout = function (xhr) {
if (callbacks._onTimeout)
callbacks._onTimeout(xhr);
retry();
};
if (!options.entity_name) options.entity_name = "unknown";
if (!options.retry_timeout) options.retry_timeout = 1000;
const retries_total = options.retries;
let currentTry = 1;
const retry = function () {
console.warn(
"Pulling " +
options.entity_name +
" failed... " +
currentTry++ +
"/" +
retries_total,
);
setTimeout(function () {
options.retries--;
helpers._xhrRetry(method, url, options, callbacks);
},
}, options.retry_timeout);
};
/**
* @typedef {Object} invidiousStorage
* @property {(key:String) => Object} get
* @property {(key:String, value:Object)} set
* @property {(key:String)} remove
*/
// Pack retry() call into error handlers
callbacks._onError = callbacks.onError;
callbacks.onError = function (xhr) {
if (callbacks._onError) callbacks._onError(xhr);
retry();
};
callbacks._onTimeout = callbacks.onTimeout;
callbacks.onTimeout = function (xhr) {
if (callbacks._onTimeout) callbacks._onTimeout(xhr);
retry();
};
/**
* Universal storage, stores and returns JS objects. Uses inside localStorage or cookies
* @type {invidiousStorage}
*/
storage: (function () {
// access to localStorage throws exception in Tor Browser, so try is needed
let localStorageIsUsable = false;
try{localStorageIsUsable = !!localStorage.setItem;}catch(e){}
helpers._xhrRetry(method, url, options, callbacks);
},
if (localStorageIsUsable) {
return {
get: function (key) {
let storageItem = localStorage.getItem(key)
if (!storageItem) return;
try {
return JSON.parse(decodeURIComponent(storageItem));
} catch(e) {
// Erase non parsable value
helpers.storage.remove(key);
}
},
set: function (key, value) {
let encoded_value = encodeURIComponent(JSON.stringify(value))
localStorage.setItem(key, encoded_value);
},
remove: function (key) { localStorage.removeItem(key); }
};
/**
* @typedef {Object} invidiousStorage
* @property {(key:String) => Object} get
* @property {(key:String, value:Object)} set
* @property {(key:String)} remove
*/
/**
* Universal storage, stores and returns JS objects. Uses inside localStorage or cookies
* @type {invidiousStorage}
*/
storage: (function () {
// access to localStorage throws exception in Tor Browser, so try is needed
let localStorageIsUsable = false;
try {
localStorageIsUsable = !!localStorage.setItem;
} catch (e) {}
if (localStorageIsUsable) {
return {
get: function (key) {
let storageItem = localStorage.getItem(key);
if (!storageItem) return;
try {
return JSON.parse(decodeURIComponent(storageItem));
} catch (e) {
// Erase non parsable value
helpers.storage.remove(key);
}
},
set: function (key, value) {
let encoded_value = encodeURIComponent(JSON.stringify(value));
localStorage.setItem(key, encoded_value);
},
remove: function (key) {
localStorage.removeItem(key);
},
};
}
// TODO: fire 'storage' event for cookies
console.info(
"Storage: localStorage is disabled or unaccessible. Cookies used as fallback",
);
return {
get: function (key) {
const cookiePrefix = key + "=";
function findCallback(cookie) {
return cookie.startsWith(cookiePrefix);
}
const matchedCookie = document.cookie.split("; ").find(findCallback);
if (matchedCookie) {
const cookieBody = matchedCookie.replace(cookiePrefix, "");
if (cookieBody.length === 0) return;
try {
return JSON.parse(decodeURIComponent(cookieBody));
} catch (e) {
// Erase non parsable value
helpers.storage.remove(key);
}
}
},
set: function (key, value) {
const cookie_data = encodeURIComponent(JSON.stringify(value));
// TODO: fire 'storage' event for cookies
console.info('Storage: localStorage is disabled or unaccessible. Cookies used as fallback');
return {
get: function (key) {
const cookiePrefix = key + '=';
function findCallback(cookie) {return cookie.startsWith(cookiePrefix);}
const matchedCookie = document.cookie.split('; ').find(findCallback);
if (matchedCookie) {
const cookieBody = matchedCookie.replace(cookiePrefix, '');
if (cookieBody.length === 0) return;
try {
return JSON.parse(decodeURIComponent(cookieBody));
} catch(e) {
// Erase non parsable value
helpers.storage.remove(key);
}
}
},
set: function (key, value) {
const cookie_data = encodeURIComponent(JSON.stringify(value));
// Set expiration in 2 year
const date = new Date();
date.setFullYear(date.getFullYear() + 2);
// Set expiration in 2 year
const date = new Date();
date.setFullYear(date.getFullYear()+2);
document.cookie = key + '=' + cookie_data + '; expires=' + date.toGMTString();
},
remove: function (key) {
document.cookie = key + '=; Max-Age=0';
}
};
})()
document.cookie =
key + "=" + cookie_data + "; expires=" + date.toGMTString();
},
remove: function (key) {
document.cookie = key + "=; Max-Age=0";
},
};
})(),
};

View File

@ -1,81 +1,91 @@
var video_data = JSON.parse(document.getElementById('video_data').textContent);
var video_data = JSON.parse(document.getElementById("video_data").textContent);
var spinnerHTML = '<div class="loading"><i class="icon ion-ios-refresh"></i></div>';
var spinnerHTMLwithHR = spinnerHTML + '<hr>';
var spinnerHTML =
'<div class="loading"><i class="icon ion-ios-refresh"></i></div>';
var spinnerHTMLwithHR = spinnerHTML + "<hr>";
String.prototype.supplant = function (o) {
return this.replace(/{([^{}]*)}/g, function (a, b) {
var r = o[b];
return typeof r === 'string' || typeof r === 'number' ? r : a;
});
return this.replace(/{([^{}]*)}/g, function (a, b) {
var r = o[b];
return typeof r === "string" || typeof r === "number" ? r : a;
});
};
function toggle_comments(event) {
const target = event.target;
const comments = document.querySelector(".comments");
if (comments.style.display === 'none') {
target.textContent = '';
comments.style.display = '';
} else {
target.textContent = '+';
comments.style.display = 'none';
}
const target = event.target;
const comments = document.querySelector(".comments");
if (comments.style.display === "none") {
target.textContent = "";
comments.style.display = "";
} else {
target.textContent = "+";
comments.style.display = "none";
}
}
function hide_youtube_replies(event) {
var target = event.target;
var target = event.target;
var sub_text = target.getAttribute('data-inner-text');
var inner_text = target.getAttribute('data-sub-text');
var sub_text = target.getAttribute("data-inner-text");
var inner_text = target.getAttribute("data-sub-text");
var body = target.parentNode.parentNode.children[1];
body.style.display = 'none';
var body = target.parentNode.parentNode.children[1];
body.style.display = "none";
target.textContent = sub_text;
target.onclick = show_youtube_replies;
target.setAttribute('data-inner-text', inner_text);
target.setAttribute('data-sub-text', sub_text);
target.textContent = sub_text;
target.onclick = show_youtube_replies;
target.setAttribute("data-inner-text", inner_text);
target.setAttribute("data-sub-text", sub_text);
}
function show_youtube_replies(event) {
var target = event.target;
console.log(target);
var target = event.target;
console.log(target);
var sub_text = target.getAttribute('data-inner-text');
var inner_text = target.getAttribute('data-sub-text');
var sub_text = target.getAttribute("data-inner-text");
var inner_text = target.getAttribute("data-sub-text");
var body = target.parentNode.parentNode.children[1];
body.style.display = '';
var body = target.parentNode.parentNode.children[1];
body.style.display = "";
target.textContent = sub_text;
target.onclick = hide_youtube_replies;
target.setAttribute('data-inner-text', inner_text);
target.setAttribute('data-sub-text', sub_text);
target.textContent = sub_text;
target.onclick = hide_youtube_replies;
target.setAttribute("data-inner-text", inner_text);
target.setAttribute("data-sub-text", sub_text);
}
function get_youtube_comments() {
var comments = document.getElementById('comments');
var comments = document.getElementById("comments");
var fallback = comments.innerHTML;
comments.innerHTML = spinnerHTML;
var fallback = comments.innerHTML;
comments.innerHTML = spinnerHTML;
var baseUrl = video_data.base_url || '/api/v1/comments/'+ video_data.id
var url = baseUrl +
'?format=html' +
'&hl=' + video_data.preferences.locale +
'&thin_mode=' + video_data.preferences.thin_mode;
var baseUrl = video_data.base_url || "/api/v1/comments/" + video_data.id;
var url =
baseUrl +
"?format=html" +
"&hl=" +
video_data.preferences.locale +
"&thin_mode=" +
video_data.preferences.thin_mode;
if (video_data.ucid) {
url += '&ucid=' + video_data.ucid
}
if (video_data.ucid) {
url += "&ucid=" + video_data.ucid;
}
var onNon200 = function (xhr) { comments.innerHTML = fallback; };
if (video_data.params.comments[1] === 'youtube')
onNon200 = function (xhr) {};
var onNon200 = function (xhr) {
comments.innerHTML = fallback;
};
if (video_data.params.comments[1] === "youtube") onNon200 = function (xhr) {};
helpers.xhr('GET', url, {retries: 5, entity_name: 'comments'}, {
on200: function (response) {
var commentInnerHtml = ' \
helpers.xhr(
"GET",
url,
{ retries: 5, entity_name: "comments" },
{
on200: function (response) {
var commentInnerHtml =
' \
<nav class="comments-header"> \
<ul> \
<li> \
@ -83,92 +93,104 @@ function get_youtube_comments() {
{commentsText} \
</li> \
\
<li>'
if (video_data.support_reddit) {
commentInnerHtml += ' <button data-comments="reddit"> \
<li>';
if (video_data.support_reddit) {
commentInnerHtml +=
' <button data-comments="reddit"> \
{redditComments} \
</button> \
'
}
commentInnerHtml += ' </li> \
';
}
commentInnerHtml +=
' </li> \
</ul> \
</nav> \
<div class="comments">{contentHtml}</div>'
commentInnerHtml = commentInnerHtml.supplant({
contentHtml: response.contentHtml,
redditComments: video_data.reddit_comments_text,
commentsText: video_data.comments_text.supplant({
// toLocaleString correctly splits number with local thousands separator. e.g.:
// '1,234,567.89' for user with English locale
// '1 234 567,89' for user with Russian locale
// '1.234.567,89' for user with Portuguese locale
commentCount: response.commentCount.toLocaleString()
})
});
comments.innerHTML = commentInnerHtml;
document.getElementById("toggle-comments").onclick = toggle_comments;
if (video_data.support_reddit) {
comments.children[1].children[1].onclick = swap_comments;
}
},
onNon200: onNon200, // declared above
onError: function (xhr) {
comments.innerHTML = spinnerHTML;
},
onTimeout: function (xhr) {
comments.innerHTML = spinnerHTML;
<div class="comments">{contentHtml}</div>';
commentInnerHtml = commentInnerHtml.supplant({
contentHtml: response.contentHtml,
redditComments: video_data.reddit_comments_text,
commentsText: video_data.comments_text.supplant({
// toLocaleString correctly splits number with local thousands separator. e.g.:
// '1,234,567.89' for user with English locale
// '1 234 567,89' for user with Russian locale
// '1.234.567,89' for user with Portuguese locale
commentCount: response.commentCount.toLocaleString(),
}),
});
comments.innerHTML = commentInnerHtml;
document.getElementById("toggle-comments").onclick = toggle_comments;
if (video_data.support_reddit) {
comments.children[1].children[1].onclick = swap_comments;
}
});
},
onNon200: onNon200, // declared above
onError: function (xhr) {
comments.innerHTML = spinnerHTML;
},
onTimeout: function (xhr) {
comments.innerHTML = spinnerHTML;
},
},
);
}
function get_youtube_replies(target, load_more, load_replies) {
var continuation = target.getAttribute('data-continuation');
var continuation = target.getAttribute("data-continuation");
var body = target.parentNode;
var fallback = body.innerHTML;
body.innerHTML = spinnerHTML;
var baseUrl = video_data.base_url || '/api/v1/comments/'+ video_data.id
var url = baseUrl +
'?format=html' +
'&hl=' + video_data.preferences.locale +
'&thin_mode=' + video_data.preferences.thin_mode +
'&continuation=' + continuation;
var body = target.parentNode;
var fallback = body.innerHTML;
body.innerHTML = spinnerHTML;
var baseUrl = video_data.base_url || "/api/v1/comments/" + video_data.id;
var url =
baseUrl +
"?format=html" +
"&hl=" +
video_data.preferences.locale +
"&thin_mode=" +
video_data.preferences.thin_mode +
"&continuation=" +
continuation;
if (video_data.ucid) {
url += '&ucid=' + video_data.ucid
}
if (load_replies) url += '&action=action_get_comment_replies';
if (video_data.ucid) {
url += "&ucid=" + video_data.ucid;
}
if (load_replies) url += "&action=action_get_comment_replies";
helpers.xhr('GET', url, {}, {
on200: function (response) {
if (load_more) {
body = body.parentNode;
body.removeChild(body.lastElementChild);
body.insertAdjacentHTML('beforeend', response.contentHtml);
} else {
body.removeChild(body.lastElementChild);
helpers.xhr(
"GET",
url,
{},
{
on200: function (response) {
if (load_more) {
body = body.parentNode;
body.removeChild(body.lastElementChild);
body.insertAdjacentHTML("beforeend", response.contentHtml);
} else {
body.removeChild(body.lastElementChild);
var div = document.createElement('div');
var button = document.createElement('button');
div.appendChild(button);
var div = document.createElement("div");
var button = document.createElement("button");
div.appendChild(button);
button.onclick = hide_youtube_replies;
button.setAttribute('data-sub-text', video_data.hide_replies_text);
button.setAttribute('data-inner-text', video_data.show_replies_text);
button.textContent = video_data.hide_replies_text;
button.onclick = hide_youtube_replies;
button.setAttribute("data-sub-text", video_data.hide_replies_text);
button.setAttribute("data-inner-text", video_data.show_replies_text);
button.textContent = video_data.hide_replies_text;
var div = document.createElement('div');
div.innerHTML = response.contentHtml;
var div = document.createElement("div");
div.innerHTML = response.contentHtml;
body.appendChild(div);
}
},
onNon200: function (xhr) {
body.innerHTML = fallback;
},
onTimeout: function (xhr) {
console.warn('Pulling comments failed');
body.innerHTML = fallback;
body.appendChild(div);
}
});
},
onNon200: function (xhr) {
body.innerHTML = fallback;
},
onTimeout: function (xhr) {
console.warn("Pulling comments failed");
body.innerHTML = fallback;
},
},
);
}

View File

@ -1,82 +1,94 @@
'use strict';
var community_data = JSON.parse(document.getElementById('community_data').textContent);
"use strict";
var community_data = JSON.parse(
document.getElementById("community_data").textContent,
);
function hide_youtube_replies(event) {
var target = event.target;
var target = event.target;
var sub_text = target.getAttribute('data-inner-text');
var inner_text = target.getAttribute('data-sub-text');
var sub_text = target.getAttribute("data-inner-text");
var inner_text = target.getAttribute("data-sub-text");
var body = target.parentNode.parentNode.children[1];
body.style.display = 'none';
var body = target.parentNode.parentNode.children[1];
body.style.display = "none";
target.innerHTML = sub_text;
target.onclick = show_youtube_replies;
target.setAttribute('data-inner-text', inner_text);
target.setAttribute('data-sub-text', sub_text);
target.innerHTML = sub_text;
target.onclick = show_youtube_replies;
target.setAttribute("data-inner-text", inner_text);
target.setAttribute("data-sub-text", sub_text);
}
function show_youtube_replies(event) {
var target = event.target;
var target = event.target;
var sub_text = target.getAttribute('data-inner-text');
var inner_text = target.getAttribute('data-sub-text');
var sub_text = target.getAttribute("data-inner-text");
var inner_text = target.getAttribute("data-sub-text");
var body = target.parentNode.parentNode.children[1];
body.style.display = '';
var body = target.parentNode.parentNode.children[1];
body.style.display = "";
target.innerHTML = sub_text;
target.onclick = hide_youtube_replies;
target.setAttribute('data-inner-text', inner_text);
target.setAttribute('data-sub-text', sub_text);
target.innerHTML = sub_text;
target.onclick = hide_youtube_replies;
target.setAttribute("data-inner-text", inner_text);
target.setAttribute("data-sub-text", sub_text);
}
function get_youtube_replies(target, load_more) {
var continuation = target.getAttribute('data-continuation');
var continuation = target.getAttribute("data-continuation");
var body = target.parentNode.parentNode;
var fallback = body.innerHTML;
body.innerHTML =
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3>';
var body = target.parentNode.parentNode;
var fallback = body.innerHTML;
body.innerHTML =
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3>';
var url = '/api/v1/channels/comments/' + community_data.ucid +
'?format=html' +
'&hl=' + community_data.preferences.locale +
'&thin_mode=' + community_data.preferences.thin_mode +
'&continuation=' + continuation;
var url =
"/api/v1/channels/comments/" +
community_data.ucid +
"?format=html" +
"&hl=" +
community_data.preferences.locale +
"&thin_mode=" +
community_data.preferences.thin_mode +
"&continuation=" +
continuation;
helpers.xhr('GET', url, {}, {
on200: function (response) {
if (load_more) {
body = body.parentNode.parentNode;
body.removeChild(body.lastElementChild);
body.innerHTML += response.contentHtml;
} else {
body.removeChild(body.lastElementChild);
helpers.xhr(
"GET",
url,
{},
{
on200: function (response) {
if (load_more) {
body = body.parentNode.parentNode;
body.removeChild(body.lastElementChild);
body.innerHTML += response.contentHtml;
} else {
body.removeChild(body.lastElementChild);
var p = document.createElement('p');
var a = document.createElement('a');
p.appendChild(a);
var p = document.createElement("p");
var a = document.createElement("a");
p.appendChild(a);
a.href = 'javascript:void(0)';
a.onclick = hide_youtube_replies;
a.setAttribute('data-sub-text', community_data.hide_replies_text);
a.setAttribute('data-inner-text', community_data.show_replies_text);
a.textContent = community_data.hide_replies_text;
a.href = "javascript:void(0)";
a.onclick = hide_youtube_replies;
a.setAttribute("data-sub-text", community_data.hide_replies_text);
a.setAttribute("data-inner-text", community_data.show_replies_text);
a.textContent = community_data.hide_replies_text;
var div = document.createElement('div');
div.innerHTML = response.contentHtml;
var div = document.createElement("div");
div.innerHTML = response.contentHtml;
body.appendChild(p);
body.appendChild(div);
}
},
onNon200: function (xhr) {
body.innerHTML = fallback;
},
onTimeout: function (xhr) {
console.warn('Pulling comments failed');
body.innerHTML = fallback;
body.appendChild(p);
body.appendChild(div);
}
});
},
onNon200: function (xhr) {
body.innerHTML = fallback;
},
onTimeout: function (xhr) {
console.warn("Pulling comments failed");
body.innerHTML = fallback;
},
},
);
}

View File

@ -1,64 +1,79 @@
'use strict';
var video_data = JSON.parse(document.getElementById('video_data').textContent);
"use strict";
var video_data = JSON.parse(document.getElementById("video_data").textContent);
function get_playlist(plid) {
var plid_url;
if (plid.startsWith('RD')) {
plid_url = '/api/v1/mixes/' + plid +
'?continuation=' + video_data.id +
'&format=html&hl=' + video_data.preferences.locale;
} else {
plid_url = '/api/v1/playlists/' + plid +
'?index=' + video_data.index +
'&continuation' + video_data.id +
'&format=html&hl=' + video_data.preferences.locale;
}
var plid_url;
if (plid.startsWith("RD")) {
plid_url =
"/api/v1/mixes/" +
plid +
"?continuation=" +
video_data.id +
"&format=html&hl=" +
video_data.preferences.locale;
} else {
plid_url =
"/api/v1/playlists/" +
plid +
"?index=" +
video_data.index +
"&continuation" +
video_data.id +
"&format=html&hl=" +
video_data.preferences.locale;
}
helpers.xhr('GET', plid_url, {retries: 5, entity_name: 'playlist'}, {
on200: function (response) {
if (!response.nextVideo)
return;
helpers.xhr(
"GET",
plid_url,
{ retries: 5, entity_name: "playlist" },
{
on200: function (response) {
if (!response.nextVideo) return;
player.on('ended', function () {
var url = new URL('https://example.com/embed/' + response.nextVideo);
player.on("ended", function () {
var url = new URL("https://example.com/embed/" + response.nextVideo);
url.searchParams.set('list', plid);
if (!plid.startsWith('RD'))
url.searchParams.set('index', response.index);
if (video_data.params.autoplay || video_data.params.continue_autoplay)
url.searchParams.set('autoplay', '1');
if (video_data.params.listen !== video_data.preferences.listen)
url.searchParams.set('listen', video_data.params.listen);
if (video_data.params.speed !== video_data.preferences.speed)
url.searchParams.set('speed', video_data.params.speed);
if (video_data.params.local !== video_data.preferences.local)
url.searchParams.set('local', video_data.params.local);
url.searchParams.set("list", plid);
if (!plid.startsWith("RD"))
url.searchParams.set("index", response.index);
if (video_data.params.autoplay || video_data.params.continue_autoplay)
url.searchParams.set("autoplay", "1");
if (video_data.params.listen !== video_data.preferences.listen)
url.searchParams.set("listen", video_data.params.listen);
if (video_data.params.speed !== video_data.preferences.speed)
url.searchParams.set("speed", video_data.params.speed);
if (video_data.params.local !== video_data.preferences.local)
url.searchParams.set("local", video_data.params.local);
location.assign(url.pathname + url.search);
});
}
});
location.assign(url.pathname + url.search);
});
},
},
);
}
addEventListener('load', function (e) {
if (video_data.plid) {
get_playlist(video_data.plid);
} else if (video_data.video_series) {
player.on('ended', function () {
var url = new URL('https://example.com/embed/' + video_data.video_series.shift());
addEventListener("load", function (e) {
if (video_data.plid) {
get_playlist(video_data.plid);
} else if (video_data.video_series) {
player.on("ended", function () {
var url = new URL(
"https://example.com/embed/" + video_data.video_series.shift(),
);
if (video_data.params.autoplay || video_data.params.continue_autoplay)
url.searchParams.set('autoplay', '1');
if (video_data.params.listen !== video_data.preferences.listen)
url.searchParams.set('listen', video_data.params.listen);
if (video_data.params.speed !== video_data.preferences.speed)
url.searchParams.set('speed', video_data.params.speed);
if (video_data.params.local !== video_data.preferences.local)
url.searchParams.set('local', video_data.params.local);
if (video_data.video_series.length !== 0)
url.searchParams.set('playlist', video_data.video_series.join(','));
if (video_data.params.autoplay || video_data.params.continue_autoplay)
url.searchParams.set("autoplay", "1");
if (video_data.params.listen !== video_data.preferences.listen)
url.searchParams.set("listen", video_data.params.listen);
if (video_data.params.speed !== video_data.preferences.speed)
url.searchParams.set("speed", video_data.params.speed);
if (video_data.params.local !== video_data.preferences.local)
url.searchParams.set("local", video_data.params.local);
if (video_data.video_series.length !== 0)
url.searchParams.set("playlist", video_data.video_series.join(","));
location.assign(url.pathname + url.search);
});
}
location.assign(url.pathname + url.search);
});
}
});

View File

@ -1,149 +1,220 @@
'use strict';
"use strict";
(function () {
var video_player = document.getElementById('player_html5_api');
if (video_player) {
video_player.onmouseenter = function () { video_player['data-title'] = video_player['title']; video_player['title'] = ''; };
video_player.onmouseleave = function () { video_player['title'] = video_player['data-title']; video_player['data-title'] = ''; };
video_player.oncontextmenu = function () { video_player['title'] = video_player['data-title']; };
var video_player = document.getElementById("player_html5_api");
if (video_player) {
video_player.onmouseenter = function () {
video_player["data-title"] = video_player["title"];
video_player["title"] = "";
};
video_player.onmouseleave = function () {
video_player["title"] = video_player["data-title"];
video_player["data-title"] = "";
};
video_player.oncontextmenu = function () {
video_player["title"] = video_player["data-title"];
};
}
// For dynamically inserted elements
addEventListener("click", function (e) {
if (!e || !e.target) return;
var t = e.target;
var handler_name = t.getAttribute("data-onclick");
switch (handler_name) {
case "jump_to_time":
e.preventDefault();
var time = t.getAttribute("data-jump-time");
player.currentTime(time);
break;
case "get_youtube_replies":
var load_more = t.getAttribute("data-load-more") !== null;
var load_replies = t.getAttribute("data-load-replies") !== null;
get_youtube_replies(t, load_more, load_replies);
break;
case "toggle_parent":
e.preventDefault();
toggle_parent(t);
break;
default:
break;
}
});
document
.querySelectorAll('[data-mouse="switch_classes"]')
.forEach(function (el) {
var classes = el.getAttribute("data-switch-classes").split(",");
var classOnEnter = classes[0];
var classOnLeave = classes[1];
function toggle_classes(toAdd, toRemove) {
el.classList.add(toAdd);
el.classList.remove(toRemove);
}
el.onmouseenter = function () {
toggle_classes(classOnEnter, classOnLeave);
};
el.onmouseleave = function () {
toggle_classes(classOnLeave, classOnEnter);
};
});
document
.querySelectorAll('[data-onsubmit="return_false"]')
.forEach(function (el) {
el.onsubmit = function () {
return false;
};
});
document
.querySelectorAll('[data-onclick="mark_watched"]')
.forEach(function (el) {
el.onclick = function () {
mark_watched(el);
};
});
document
.querySelectorAll('[data-onclick="mark_unwatched"]')
.forEach(function (el) {
el.onclick = function () {
mark_unwatched(el);
};
});
document
.querySelectorAll('[data-onclick="add_playlist_video"]')
.forEach(function (el) {
el.onclick = function (e) {
add_playlist_video(e);
};
});
document
.querySelectorAll('[data-onclick="add_playlist_item"]')
.forEach(function (el) {
el.onclick = function (e) {
add_playlist_item(e);
};
});
document
.querySelectorAll('[data-onclick="remove_playlist_item"]')
.forEach(function (el) {
el.onclick = function (e) {
remove_playlist_item(e);
};
});
document
.querySelectorAll('[data-onclick="revoke_token"]')
.forEach(function (el) {
el.onclick = function () {
revoke_token(el);
};
});
document
.querySelectorAll('[data-onclick="remove_subscription"]')
.forEach(function (el) {
el.onclick = function () {
remove_subscription(el);
};
});
document
.querySelectorAll('[data-onclick="notification_requestPermission"]')
.forEach(function (el) {
el.onclick = function () {
Notification.requestPermission();
};
});
document
.querySelectorAll('[data-onrange="update_volume_value"]')
.forEach(function (el) {
function update_volume_value() {
document.getElementById("volume-value").textContent = el.value;
}
el.oninput = update_volume_value;
el.onchange = update_volume_value;
});
function revoke_token(target) {
var row = target.parentNode.parentNode.parentNode.parentNode.parentNode;
row.style.display = "none";
var count = document.getElementById("count");
count.textContent--;
var url =
"/token_ajax?action=revoke_token&redirect=false" +
"&referer=" +
encodeURIComponent(location.href) +
"&session=" +
target.getAttribute("data-session");
var payload =
"csrf_token=" +
target.parentNode.querySelector('input[name="csrf_token"]').value;
helpers.xhr(
"POST",
url,
{ payload: payload },
{
onNon200: function (xhr) {
count.textContent++;
row.style.display = "";
},
},
);
}
function remove_subscription(target) {
var row = target.parentNode.parentNode.parentNode.parentNode.parentNode;
row.style.display = "none";
var count = document.getElementById("count");
count.textContent--;
var url =
"/subscription_ajax?action=remove_subscriptions&redirect=false" +
"&referer=" +
encodeURIComponent(location.href) +
"&c=" +
target.getAttribute("data-ucid");
var payload =
"csrf_token=" +
target.parentNode.querySelector('input[name="csrf_token"]').value;
helpers.xhr(
"POST",
url,
{ payload: payload },
{
onNon200: function (xhr) {
count.textContent++;
row.style.display = "";
},
},
);
}
// Handle keypresses
addEventListener("keydown", function (event) {
// Ignore modifier keys
if (event.ctrlKey || event.metaKey) return;
// Ignore shortcuts if any text input is focused
let focused_tag = document.activeElement.tagName.toLowerCase();
const allowed = /^(button|checkbox|file|radio|submit)$/;
if (focused_tag === "textarea") return;
if (focused_tag === "input") {
let focused_type = document.activeElement.type.toLowerCase();
if (!allowed.test(focused_type)) return;
}
// For dynamically inserted elements
addEventListener('click', function (e) {
if (!e || !e.target) return;
var t = e.target;
var handler_name = t.getAttribute('data-onclick');
switch (handler_name) {
case 'jump_to_time':
e.preventDefault();
var time = t.getAttribute('data-jump-time');
player.currentTime(time);
break;
case 'get_youtube_replies':
var load_more = t.getAttribute('data-load-more') !== null;
var load_replies = t.getAttribute('data-load-replies') !== null;
get_youtube_replies(t, load_more, load_replies);
break;
case 'toggle_parent':
e.preventDefault();
toggle_parent(t);
break;
default:
break;
}
});
document.querySelectorAll('[data-mouse="switch_classes"]').forEach(function (el) {
var classes = el.getAttribute('data-switch-classes').split(',');
var classOnEnter = classes[0];
var classOnLeave = classes[1];
function toggle_classes(toAdd, toRemove) {
el.classList.add(toAdd);
el.classList.remove(toRemove);
}
el.onmouseenter = function () { toggle_classes(classOnEnter, classOnLeave); };
el.onmouseleave = function () { toggle_classes(classOnLeave, classOnEnter); };
});
document.querySelectorAll('[data-onsubmit="return_false"]').forEach(function (el) {
el.onsubmit = function () { return false; };
});
document.querySelectorAll('[data-onclick="mark_watched"]').forEach(function (el) {
el.onclick = function () { mark_watched(el); };
});
document.querySelectorAll('[data-onclick="mark_unwatched"]').forEach(function (el) {
el.onclick = function () { mark_unwatched(el); };
});
document.querySelectorAll('[data-onclick="add_playlist_video"]').forEach(function (el) {
el.onclick = function (e) { add_playlist_video(e); };
});
document.querySelectorAll('[data-onclick="add_playlist_item"]').forEach(function (el) {
el.onclick = function (e) { add_playlist_item(e); };
});
document.querySelectorAll('[data-onclick="remove_playlist_item"]').forEach(function (el) {
el.onclick = function (e) { remove_playlist_item(e); };
});
document.querySelectorAll('[data-onclick="revoke_token"]').forEach(function (el) {
el.onclick = function () { revoke_token(el); };
});
document.querySelectorAll('[data-onclick="remove_subscription"]').forEach(function (el) {
el.onclick = function () { remove_subscription(el); };
});
document.querySelectorAll('[data-onclick="notification_requestPermission"]').forEach(function (el) {
el.onclick = function () { Notification.requestPermission(); };
});
document.querySelectorAll('[data-onrange="update_volume_value"]').forEach(function (el) {
function update_volume_value() {
document.getElementById('volume-value').textContent = el.value;
}
el.oninput = update_volume_value;
el.onchange = update_volume_value;
});
function revoke_token(target) {
var row = target.parentNode.parentNode.parentNode.parentNode.parentNode;
row.style.display = 'none';
var count = document.getElementById('count');
count.textContent--;
var url = '/token_ajax?action=revoke_token&redirect=false' +
'&referer=' + encodeURIComponent(location.href) +
'&session=' + target.getAttribute('data-session');
var payload = 'csrf_token=' + target.parentNode.querySelector('input[name="csrf_token"]').value;
helpers.xhr('POST', url, {payload: payload}, {
onNon200: function (xhr) {
count.textContent++;
row.style.display = '';
}
});
// Focus search bar on '/'
if (event.key === "/") {
document.getElementById("searchbox").focus();
event.preventDefault();
}
function remove_subscription(target) {
var row = target.parentNode.parentNode.parentNode.parentNode.parentNode;
row.style.display = 'none';
var count = document.getElementById('count');
count.textContent--;
var url = '/subscription_ajax?action=remove_subscriptions&redirect=false' +
'&referer=' + encodeURIComponent(location.href) +
'&c=' + target.getAttribute('data-ucid');
var payload = 'csrf_token=' + target.parentNode.querySelector('input[name="csrf_token"]').value;
helpers.xhr('POST', url, {payload: payload}, {
onNon200: function (xhr) {
count.textContent++;
row.style.display = '';
}
});
}
// Handle keypresses
addEventListener('keydown', function (event) {
// Ignore modifier keys
if (event.ctrlKey || event.metaKey) return;
// Ignore shortcuts if any text input is focused
let focused_tag = document.activeElement.tagName.toLowerCase();
const allowed = /^(button|checkbox|file|radio|submit)$/;
if (focused_tag === 'textarea') return;
if (focused_tag === 'input') {
let focused_type = document.activeElement.type.toLowerCase();
if (!allowed.test(focused_type)) return;
}
// Focus search bar on '/'
if (event.key === '/') {
document.getElementById('searchbox').focus();
event.preventDefault();
}
});
});
})();

View File

@ -31,7 +31,11 @@ async function get_subscriptions_call() {
}
// Start the retry mechanism
const get_subscriptions = exponential_backoff(get_subscriptions_call, 100, 1000);
const get_subscriptions = exponential_backoff(
get_subscriptions_call,
100,
1000,
);
function create_notification_stream(subscriptions) {
// sse.js can't be replaced to EventSource in place as it lack support of payload and headers
@ -96,7 +100,6 @@ function create_notification_stream(subscriptions) {
"Something went wrong with notifications, trying to reconnect...",
);
notifications = notifications_mock;
});
notifications.stream();
@ -177,7 +180,7 @@ function exponential_backoff(
return function tryFunction() {
fn()
.then((response) => {
attempt = 0;
attempt = 0;
})
.catch((error) => {
if (attempt < maxRetries) {
@ -193,5 +196,5 @@ function exponential_backoff(
console.log("Max retries reached. Operation failed:", error);
}
});
}
};
}

View File

@ -1,93 +1,103 @@
'use strict';
"use strict";
const CURRENT_CONTINUATION = (new URL(document.location)).searchParams.get("continuation");
const CURRENT_CONTINUATION = new URL(document.location).searchParams.get(
"continuation",
);
const CONT_CACHE_KEY = `continuation_cache_${encodeURIComponent(window.location.pathname)}`;
function get_data(){
return JSON.parse(sessionStorage.getItem(CONT_CACHE_KEY)) || [];
function get_data() {
return JSON.parse(sessionStorage.getItem(CONT_CACHE_KEY)) || [];
}
function save_data(){
const prev_data = get_data();
prev_data.push(CURRENT_CONTINUATION);
function save_data() {
const prev_data = get_data();
prev_data.push(CURRENT_CONTINUATION);
sessionStorage.setItem(CONT_CACHE_KEY, JSON.stringify(prev_data));
sessionStorage.setItem(CONT_CACHE_KEY, JSON.stringify(prev_data));
}
function button_press(){
let prev_data = get_data();
if (!prev_data.length) return null;
function button_press() {
let prev_data = get_data();
if (!prev_data.length) return null;
// Sanity check. Nowhere should the current continuation token exist in the cache
// but it can happen when using the browser's back feature. As such we'd need to travel
// back to the point where the current continuation token first appears in order to
// account for the rewind.
const conflict_at = prev_data.indexOf(CURRENT_CONTINUATION);
if (conflict_at != -1) {
prev_data.length = conflict_at;
}
// Sanity check. Nowhere should the current continuation token exist in the cache
// but it can happen when using the browser's back feature. As such we'd need to travel
// back to the point where the current continuation token first appears in order to
// account for the rewind.
const conflict_at = prev_data.indexOf(CURRENT_CONTINUATION);
if (conflict_at != -1) {
prev_data.length = conflict_at;
}
const prev_ctoken = prev_data.pop();
// On the first page, the stored continuation token is null.
if (prev_ctoken === null) {
sessionStorage.removeItem(CONT_CACHE_KEY);
let url = set_continuation();
window.location.href = url;
return;
}
sessionStorage.setItem(CONT_CACHE_KEY, JSON.stringify(prev_data));
let url = set_continuation(prev_ctoken);
const prev_ctoken = prev_data.pop();
// On the first page, the stored continuation token is null.
if (prev_ctoken === null) {
sessionStorage.removeItem(CONT_CACHE_KEY);
let url = set_continuation();
window.location.href = url;
};
return;
}
sessionStorage.setItem(CONT_CACHE_KEY, JSON.stringify(prev_data));
let url = set_continuation(prev_ctoken);
window.location.href = url;
}
// Method to set the current page's continuation token
// Removes the continuation parameter when a continuation token is not given
function set_continuation(prev_ctoken = null){
let url = window.location.href.split('?')[0];
let params = window.location.href.split('?')[1];
let url_params = new URLSearchParams(params);
function set_continuation(prev_ctoken = null) {
let url = window.location.href.split("?")[0];
let params = window.location.href.split("?")[1];
let url_params = new URLSearchParams(params);
if (prev_ctoken) {
url_params.set("continuation", prev_ctoken);
} else {
url_params.delete('continuation');
};
if (prev_ctoken) {
url_params.set("continuation", prev_ctoken);
} else {
url_params.delete("continuation");
}
if(Array.from(url_params).length > 0){
return `${url}?${url_params.toString()}`;
} else {
return url;
}
if (Array.from(url_params).length > 0) {
return `${url}?${url_params.toString()}`;
} else {
return url;
}
}
addEventListener('DOMContentLoaded', function(){
const pagination_data = JSON.parse(document.getElementById('pagination-data').textContent);
const next_page_containers = document.getElementsByClassName("page-next-container");
addEventListener("DOMContentLoaded", function () {
const pagination_data = JSON.parse(
document.getElementById("pagination-data").textContent,
);
const next_page_containers = document.getElementsByClassName(
"page-next-container",
);
for (let container of next_page_containers){
const next_page_button = container.getElementsByClassName("pure-button")
for (let container of next_page_containers) {
const next_page_button = container.getElementsByClassName("pure-button");
// exists?
if (next_page_button.length > 0){
next_page_button[0].addEventListener("click", save_data);
}
// exists?
if (next_page_button.length > 0) {
next_page_button[0].addEventListener("click", save_data);
}
}
// Only add previous page buttons when not on the first page
if (CURRENT_CONTINUATION) {
const prev_page_containers = document.getElementsByClassName("page-prev-container")
// Only add previous page buttons when not on the first page
if (CURRENT_CONTINUATION) {
const prev_page_containers = document.getElementsByClassName(
"page-prev-container",
);
for (let container of prev_page_containers) {
if (pagination_data.is_rtl) {
container.innerHTML = `<button class="pure-button pure-button-secondary">${pagination_data.prev_page}&nbsp;&nbsp;<i class="icon ion-ios-arrow-forward"></i></button>`
} else {
container.innerHTML = `<button class="pure-button pure-button-secondary"><i class="icon ion-ios-arrow-back"></i>&nbsp;&nbsp;${pagination_data.prev_page}</button>`
}
container.getElementsByClassName("pure-button")[0].addEventListener("click", button_press);
}
for (let container of prev_page_containers) {
if (pagination_data.is_rtl) {
container.innerHTML = `<button class="pure-button pure-button-secondary">${pagination_data.prev_page}&nbsp;&nbsp;<i class="icon ion-ios-arrow-forward"></i></button>`;
} else {
container.innerHTML = `<button class="pure-button pure-button-secondary"><i class="icon ion-ios-arrow-back"></i>&nbsp;&nbsp;${pagination_data.prev_page}</button>`;
}
container
.getElementsByClassName("pure-button")[0]
.addEventListener("click", button_press);
}
}
});

File diff suppressed because it is too large Load Diff

View File

@ -1,55 +1,83 @@
'use strict';
var playlist_data = JSON.parse(document.getElementById('playlist_data').textContent);
var payload = 'csrf_token=' + playlist_data.csrf_token;
"use strict";
var playlist_data = JSON.parse(
document.getElementById("playlist_data").textContent,
);
var payload = "csrf_token=" + playlist_data.csrf_token;
function add_playlist_video(event) {
const target = event.target;
var select = document.querySelector("#playlists");
var option = select.children[select.selectedIndex];
const target = event.target;
var select = document.querySelector("#playlists");
var option = select.children[select.selectedIndex];
var url = '/playlist_ajax?action=add_video&redirect=false' +
'&video_id=' + target.getAttribute('data-id') +
'&playlist_id=' + option.getAttribute('data-plid');
var url =
"/playlist_ajax?action=add_video&redirect=false" +
"&video_id=" +
target.getAttribute("data-id") +
"&playlist_id=" +
option.getAttribute("data-plid");
helpers.xhr('POST', url, {payload: payload}, {
on200: function (response) {
option.textContent = '✓ ' + option.textContent;
}
});
helpers.xhr(
"POST",
url,
{ payload: payload },
{
on200: function (response) {
option.textContent = "✓ " + option.textContent;
},
},
);
}
function add_playlist_item(event) {
event.preventDefault();
const target = event.target;
const video_id = target.getAttribute('data-id');
var card = document.querySelector(`#video-card-${video_id}`);
card.classList.add("hide");
event.preventDefault();
const target = event.target;
const video_id = target.getAttribute("data-id");
var card = document.querySelector(`#video-card-${video_id}`);
card.classList.add("hide");
var url = '/playlist_ajax?action=add_video&redirect=false' +
'&video_id=' + target.getAttribute('data-id') +
'&playlist_id=' + target.getAttribute('data-plid');
var url =
"/playlist_ajax?action=add_video&redirect=false" +
"&video_id=" +
target.getAttribute("data-id") +
"&playlist_id=" +
target.getAttribute("data-plid");
helpers.xhr('POST', url, {payload: payload}, {
onNon200: function (xhr) {
card.classList.remove("hide");
}
});
helpers.xhr(
"POST",
url,
{ payload: payload },
{
onNon200: function (xhr) {
card.classList.remove("hide");
},
},
);
}
function remove_playlist_item(event) {
event.preventDefault();
const target = event.target;
const video_index = target.getAttribute('data-index');
const card = document.querySelector(`.video-card [data-index="${video_index}"]`)
card.classList.add("hide");
event.preventDefault();
const target = event.target;
const video_index = target.getAttribute("data-index");
const card = document.querySelector(
`.video-card [data-index="${video_index}"]`,
);
card.classList.add("hide");
var url = '/playlist_ajax?action=remove_video&redirect=false' +
'&set_video_id=' + target.getAttribute('data-index') +
'&playlist_id=' + target.getAttribute('data-plid');
var url =
"/playlist_ajax?action=remove_video&redirect=false" +
"&set_video_id=" +
target.getAttribute("data-index") +
"&playlist_id=" +
target.getAttribute("data-plid");
helpers.xhr('POST', url, {payload: payload}, {
onNon200: function (xhr) {
card.classList.remove("hide");
}
});
helpers.xhr(
"POST",
url,
{ payload: payload },
{
onNon200: function (xhr) {
card.classList.remove("hide");
},
},
);
}

View File

@ -1,3 +1,3 @@
addEventListener('load', function (e) {
get_youtube_comments();
addEventListener("load", function (e) {
get_youtube_comments();
});

File diff suppressed because one or more lines are too long

View File

@ -17,18 +17,18 @@ var SSE = function (url, options) {
options = options || {};
this.headers = options.headers || {};
this.payload = options.payload !== undefined ? options.payload : '';
this.method = options.method || (this.payload && 'POST' || 'GET');
this.payload = options.payload !== undefined ? options.payload : "";
this.method = options.method || (this.payload && "POST") || "GET";
this.FIELD_SEPARATOR = ':';
this.FIELD_SEPARATOR = ":";
this.listeners = {};
this.xhr = null;
this.readyState = this.INITIALIZING;
this.progress = 0;
this.chunk = '';
this.chunk = "";
this.addEventListener = function(type, listener) {
this.addEventListener = function (type, listener) {
if (this.listeners[type] === undefined) {
this.listeners[type] = [];
}
@ -38,13 +38,13 @@ var SSE = function (url, options) {
}
};
this.removeEventListener = function(type, listener) {
this.removeEventListener = function (type, listener) {
if (this.listeners[type] === undefined) {
return;
}
var filtered = [];
this.listeners[type].forEach(function(element) {
this.listeners[type].forEach(function (element) {
if (element !== listener) {
filtered.push(element);
}
@ -56,14 +56,14 @@ var SSE = function (url, options) {
}
};
this.dispatchEvent = function(e) {
this.dispatchEvent = function (e) {
if (!e) {
return true;
}
e.source = this;
var onHandler = 'on' + e.type;
var onHandler = "on" + e.type;
if (this.hasOwnProperty(onHandler)) {
this[onHandler].call(this, e);
if (e.defaultPrevented) {
@ -72,7 +72,7 @@ var SSE = function (url, options) {
}
if (this.listeners[e.type]) {
return this.listeners[e.type].every(function(callback) {
return this.listeners[e.type].every(function (callback) {
callback(e);
return !e.defaultPrevented;
});
@ -82,78 +82,82 @@ var SSE = function (url, options) {
};
this._setReadyState = function (state) {
var event = new CustomEvent('readystatechange');
var event = new CustomEvent("readystatechange");
event.readyState = state;
this.readyState = state;
this.dispatchEvent(event);
};
this._onStreamFailure = function(e) {
this.dispatchEvent(new CustomEvent('error'));
this._onStreamFailure = function (e) {
this.dispatchEvent(new CustomEvent("error"));
this.close();
}
};
this._onStreamProgress = function(e) {
this._onStreamProgress = function (e) {
if (this.xhr.status !== 200 && this.readyState !== this.CLOSED) {
this._onStreamFailure(e);
return;
}
if (this.readyState == this.CONNECTING) {
this.dispatchEvent(new CustomEvent('open'));
this.dispatchEvent(new CustomEvent("open"));
this._setReadyState(this.OPEN);
}
var data = this.xhr.responseText.substring(this.progress);
this.progress += data.length;
data.split(/(\r\n|\r|\n){2}/g).forEach(function(part) {
if (part.trim().length === 0) {
this.dispatchEvent(this._parseEventChunk(this.chunk.trim()));
this.chunk = '';
} else {
this.chunk += part;
}
}.bind(this));
data.split(/(\r\n|\r|\n){2}/g).forEach(
function (part) {
if (part.trim().length === 0) {
this.dispatchEvent(this._parseEventChunk(this.chunk.trim()));
this.chunk = "";
} else {
this.chunk += part;
}
}.bind(this),
);
};
this._onStreamLoaded = function(e) {
this._onStreamLoaded = function (e) {
this._onStreamProgress(e);
// Parse the last chunk.
this.dispatchEvent(this._parseEventChunk(this.chunk));
this.chunk = '';
this.chunk = "";
};
/**
* Parse a received SSE event chunk into a constructed event object.
*/
this._parseEventChunk = function(chunk) {
this._parseEventChunk = function (chunk) {
if (!chunk || chunk.length === 0) {
return null;
}
var e = {'id': null, 'retry': null, 'data': '', 'event': 'message'};
chunk.split(/\n|\r\n|\r/).forEach(function(line) {
line = line.trimRight();
var index = line.indexOf(this.FIELD_SEPARATOR);
if (index <= 0) {
// Line was either empty, or started with a separator and is a comment.
// Either way, ignore.
return;
}
var e = { id: null, retry: null, data: "", event: "message" };
chunk.split(/\n|\r\n|\r/).forEach(
function (line) {
line = line.trimRight();
var index = line.indexOf(this.FIELD_SEPARATOR);
if (index <= 0) {
// Line was either empty, or started with a separator and is a comment.
// Either way, ignore.
return;
}
var field = line.substring(0, index);
if (!(field in e)) {
return;
}
var field = line.substring(0, index);
if (!(field in e)) {
return;
}
var value = line.substring(index + 1).trimLeft();
if (field === 'data') {
e[field] += value;
} else {
e[field] = value;
}
}.bind(this));
var value = line.substring(index + 1).trimLeft();
if (field === "data") {
e[field] += value;
} else {
e[field] = value;
}
}.bind(this),
);
var event = new CustomEvent(e.event);
event.data = e.data;
@ -161,21 +165,24 @@ var SSE = function (url, options) {
return event;
};
this._checkStreamClosed = function() {
this._checkStreamClosed = function () {
if (this.xhr.readyState === XMLHttpRequest.DONE) {
this._setReadyState(this.CLOSED);
}
};
this.stream = function() {
this.stream = function () {
this._setReadyState(this.CONNECTING);
this.xhr = new XMLHttpRequest();
this.xhr.addEventListener('progress', this._onStreamProgress.bind(this));
this.xhr.addEventListener('load', this._onStreamLoaded.bind(this));
this.xhr.addEventListener('readystatechange', this._checkStreamClosed.bind(this));
this.xhr.addEventListener('error', this._onStreamFailure.bind(this));
this.xhr.addEventListener('abort', this._onStreamFailure.bind(this));
this.xhr.addEventListener("progress", this._onStreamProgress.bind(this));
this.xhr.addEventListener("load", this._onStreamLoaded.bind(this));
this.xhr.addEventListener(
"readystatechange",
this._checkStreamClosed.bind(this),
);
this.xhr.addEventListener("error", this._onStreamFailure.bind(this));
this.xhr.addEventListener("abort", this._onStreamFailure.bind(this));
this.xhr.open(this.method, this.url);
for (var header in this.headers) {
this.xhr.setRequestHeader(header, this.headers[header]);
@ -183,7 +190,7 @@ var SSE = function (url, options) {
this.xhr.send(this.payload);
};
this.close = function() {
this.close = function () {
if (this.readyState === this.CLOSED) {
return;
}
@ -195,6 +202,6 @@ var SSE = function (url, options) {
};
// Export our SSE module for npm.js
if (typeof exports !== 'undefined') {
if (typeof exports !== "undefined") {
exports.SSE = SSE;
}

View File

@ -1,62 +1,80 @@
'use strict';
var subscribe_data = JSON.parse(document.getElementById('subscribe_data').textContent);
var payload = 'csrf_token=' + subscribe_data.csrf_token;
"use strict";
var subscribe_data = JSON.parse(
document.getElementById("subscribe_data").textContent,
);
var payload = "csrf_token=" + subscribe_data.csrf_token;
var subscribe_button = document.getElementById('subscribe');
var subscribe_button = document.getElementById("subscribe");
if (subscribe_button.getAttribute('data-type') === 'subscribe') {
subscribe_button.onclick = subscribe;
if (subscribe_button.getAttribute("data-type") === "subscribe") {
subscribe_button.onclick = subscribe;
} else {
subscribe_button.onclick = unsubscribe;
subscribe_button.onclick = unsubscribe;
}
function toggleSubscribeButton() {
subscribe_button.classList.remove("primary");
subscribe_button.classList.remove("secondary");
subscribe_button.classList.remove("unsubscribe");
subscribe_button.classList.remove("subscribe");
subscribe_button.classList.remove("primary");
subscribe_button.classList.remove("secondary");
subscribe_button.classList.remove("unsubscribe");
subscribe_button.classList.remove("subscribe");
if (subscribe_button.getAttribute('data-type') === 'subscribe') {
subscribe_button.textContent = subscribe_data.unsubscribe_text + ' | ' + subscribe_data.sub_count_text;
subscribe_button.onclick = unsubscribe;
subscribe_button.classList.add("secondary");
subscribe_button.classList.add("unsubscribe");
} else {
subscribe_button.textContent = subscribe_data.subscribe_text + ' | ' + subscribe_data.sub_count_text;
subscribe_button.onclick = subscribe;
subscribe_button.classList.add("primary");
subscribe_button.classList.add("subscribe");
}
if (subscribe_button.getAttribute("data-type") === "subscribe") {
subscribe_button.textContent =
subscribe_data.unsubscribe_text + " | " + subscribe_data.sub_count_text;
subscribe_button.onclick = unsubscribe;
subscribe_button.classList.add("secondary");
subscribe_button.classList.add("unsubscribe");
} else {
subscribe_button.textContent =
subscribe_data.subscribe_text + " | " + subscribe_data.sub_count_text;
subscribe_button.onclick = subscribe;
subscribe_button.classList.add("primary");
subscribe_button.classList.add("subscribe");
}
}
function subscribe(e) {
e.preventDefault();
var fallback = subscribe_button.textContent;
toggleSubscribeButton();
e.preventDefault();
var fallback = subscribe_button.textContent;
toggleSubscribeButton();
var url = '/subscription_ajax?action=create_subscription_to_channel&redirect=false' +
'&c=' + subscribe_data.ucid;
var url =
"/subscription_ajax?action=create_subscription_to_channel&redirect=false" +
"&c=" +
subscribe_data.ucid;
helpers.xhr('POST', url, {payload: payload, retries: 5, entity_name: 'subscribe request'}, {
onNon200: function (xhr) {
subscribe_button.onclick = subscribe;
subscribe_button.textContent = fallback;
}
});
helpers.xhr(
"POST",
url,
{ payload: payload, retries: 5, entity_name: "subscribe request" },
{
onNon200: function (xhr) {
subscribe_button.onclick = subscribe;
subscribe_button.textContent = fallback;
},
},
);
}
function unsubscribe(e) {
e.preventDefault();
var fallback = subscribe_button.textContent;
toggleSubscribeButton();
e.preventDefault();
var fallback = subscribe_button.textContent;
toggleSubscribeButton();
var url = '/subscription_ajax?action=remove_subscriptions&redirect=false' +
'&c=' + subscribe_data.ucid;
var url =
"/subscription_ajax?action=remove_subscriptions&redirect=false" +
"&c=" +
subscribe_data.ucid;
helpers.xhr('POST', url, {payload: payload, retries: 5, entity_name: 'unsubscribe request'}, {
onNon200: function (xhr) {
subscribe_button.onclick = unsubscribe;
subscribe_button.textContent = fallback;
}
});
helpers.xhr(
"POST",
url,
{ payload: payload, retries: 5, entity_name: "unsubscribe request" },
{
onNon200: function (xhr) {
subscribe_button.onclick = unsubscribe;
subscribe_button.textContent = fallback;
},
},
);
}

View File

@ -1,46 +1,46 @@
'use strict';
var toggle_theme = document.getElementById('toggle_theme');
"use strict";
var toggle_theme = document.getElementById("toggle_theme");
const STORAGE_KEY_THEME = 'dark_mode';
const THEME_DARK = 'dark';
const THEME_LIGHT = 'light';
const STORAGE_KEY_THEME = "dark_mode";
const THEME_DARK = "dark";
const THEME_LIGHT = "light";
// TODO: theme state controlled by system
toggle_theme.addEventListener('click', function (e) {
e.preventDefault();
const isDarkTheme = helpers.storage.get(STORAGE_KEY_THEME) === THEME_DARK;
const newTheme = isDarkTheme ? THEME_LIGHT : THEME_DARK;
setTheme(newTheme);
helpers.storage.set(STORAGE_KEY_THEME, newTheme);
helpers.xhr('GET', '/toggle_theme?redirect=false', {}, {});
toggle_theme.addEventListener("click", function (e) {
e.preventDefault();
const isDarkTheme = helpers.storage.get(STORAGE_KEY_THEME) === THEME_DARK;
const newTheme = isDarkTheme ? THEME_LIGHT : THEME_DARK;
setTheme(newTheme);
helpers.storage.set(STORAGE_KEY_THEME, newTheme);
helpers.xhr("GET", "/toggle_theme?redirect=false", {}, {});
});
/** @param {THEME_DARK|THEME_LIGHT} theme */
function setTheme(theme) {
// By default body element has .no-theme class that uses OS theme via CSS @media rules
// It rewrites using hard className below
if (theme === THEME_DARK) {
toggle_theme.children[0].className = 'icon ion-ios-sunny';
document.body.className = 'dark-theme';
} else if (theme === THEME_LIGHT) {
toggle_theme.children[0].className = 'icon ion-ios-moon';
document.body.className = 'light-theme';
} else {
document.body.className = 'no-theme';
}
// By default body element has .no-theme class that uses OS theme via CSS @media rules
// It rewrites using hard className below
if (theme === THEME_DARK) {
toggle_theme.children[0].className = "icon ion-ios-sunny";
document.body.className = "dark-theme";
} else if (theme === THEME_LIGHT) {
toggle_theme.children[0].className = "icon ion-ios-moon";
document.body.className = "light-theme";
} else {
document.body.className = "no-theme";
}
}
// Handles theme change event caused by other tab
addEventListener('storage', function (e) {
if (e.key === STORAGE_KEY_THEME)
setTheme(helpers.storage.get(STORAGE_KEY_THEME));
addEventListener("storage", function (e) {
if (e.key === STORAGE_KEY_THEME)
setTheme(helpers.storage.get(STORAGE_KEY_THEME));
});
// Set theme from preferences on page load
addEventListener('DOMContentLoaded', function () {
const prefTheme = document.getElementById('dark_mode_pref').textContent;
if (prefTheme) {
setTheme(prefTheme);
helpers.storage.set(STORAGE_KEY_THEME, prefTheme);
}
addEventListener("DOMContentLoaded", function () {
const prefTheme = document.getElementById("dark_mode_pref").textContent;
if (prefTheme) {
setTheme(prefTheme);
helpers.storage.set(STORAGE_KEY_THEME, prefTheme);
}
});

File diff suppressed because one or more lines are too long

View File

@ -1,135 +1,159 @@
'use strict';
"use strict";
function toggle_parent(target) {
var body = target.parentNode.parentNode.children[1];
if (body.style.display === 'none') {
target.textContent = '[ ]';
body.style.display = '';
} else {
target.textContent = '[ + ]';
body.style.display = 'none';
}
var body = target.parentNode.parentNode.children[1];
if (body.style.display === "none") {
target.textContent = "[ ]";
body.style.display = "";
} else {
target.textContent = "[ + ]";
body.style.display = "none";
}
}
function swap_comments(event) {
var source = event.target.getAttribute('data-comments');
var source = event.target.getAttribute("data-comments");
if (source === 'youtube') {
get_youtube_comments();
} else if (source === 'reddit') {
get_reddit_comments();
}
if (source === "youtube") {
get_youtube_comments();
} else if (source === "reddit") {
get_reddit_comments();
}
}
var continue_button = document.getElementById('continue');
var continue_button = document.getElementById("continue");
if (continue_button) {
continue_button.onclick = continue_autoplay;
continue_button.onclick = continue_autoplay;
}
function next_video() {
var url = new URL('https://example.com/watch?v=' + video_data.next_video);
var url = new URL("https://example.com/watch?v=" + video_data.next_video);
if (video_data.params.autoplay || video_data.params.continue_autoplay)
url.searchParams.set('autoplay', '1');
if (video_data.params.listen !== video_data.preferences.listen)
url.searchParams.set('listen', video_data.params.listen);
if (video_data.params.speed !== video_data.preferences.speed)
url.searchParams.set('speed', video_data.params.speed);
if (video_data.params.local !== video_data.preferences.local)
url.searchParams.set('local', video_data.params.local);
url.searchParams.set('continue', '1');
if (video_data.params.autoplay || video_data.params.continue_autoplay)
url.searchParams.set("autoplay", "1");
if (video_data.params.listen !== video_data.preferences.listen)
url.searchParams.set("listen", video_data.params.listen);
if (video_data.params.speed !== video_data.preferences.speed)
url.searchParams.set("speed", video_data.params.speed);
if (video_data.params.local !== video_data.preferences.local)
url.searchParams.set("local", video_data.params.local);
url.searchParams.set("continue", "1");
location.assign(url.pathname + url.search);
location.assign(url.pathname + url.search);
}
function continue_autoplay(event) {
if (event.target.checked) {
player.on('ended', next_video);
} else {
player.off('ended');
}
if (event.target.checked) {
player.on("ended", next_video);
} else {
player.off("ended");
}
}
function get_playlist(plid) {
var playlist = document.getElementById('playlist');
var playlist = document.getElementById("playlist");
playlist.innerHTML = spinnerHTMLwithHR;
playlist.innerHTML = spinnerHTMLwithHR;
var plid_url;
if (plid.startsWith('RD')) {
plid_url = '/api/v1/mixes/' + plid +
'?continuation=' + video_data.id +
'&format=html&hl=' + video_data.preferences.locale;
} else {
plid_url = '/api/v1/playlists/' + plid +
'?index=' + video_data.index +
'&continuation=' + video_data.id +
'&format=html&hl=' + video_data.preferences.locale;
}
var plid_url;
if (plid.startsWith("RD")) {
plid_url =
"/api/v1/mixes/" +
plid +
"?continuation=" +
video_data.id +
"&format=html&hl=" +
video_data.preferences.locale;
} else {
plid_url =
"/api/v1/playlists/" +
plid +
"?index=" +
video_data.index +
"&continuation=" +
video_data.id +
"&format=html&hl=" +
video_data.preferences.locale;
}
if (video_data.params.listen) {
plid_url += '&listen=1'
}
if (video_data.params.listen) {
plid_url += "&listen=1";
}
helpers.xhr('GET', plid_url, {retries: 5, entity_name: 'playlist'}, {
on200: function (response) {
if (response === null) return;
helpers.xhr(
"GET",
plid_url,
{ retries: 5, entity_name: "playlist" },
{
on200: function (response) {
if (response === null) return;
playlist.innerHTML = response.playlistHtml;
playlist.innerHTML = response.playlistHtml;
if (!response.nextVideo) return;
if (!response.nextVideo) return;
var nextVideo = document.getElementById(response.nextVideo);
nextVideo.parentNode.parentNode.scrollTop = nextVideo.offsetTop;
var nextVideo = document.getElementById(response.nextVideo);
nextVideo.parentNode.parentNode.scrollTop = nextVideo.offsetTop;
player.on('ended', function () {
var url = new URL('https://example.com/watch?v=' + response.nextVideo);
player.on("ended", function () {
var url = new URL(
"https://example.com/watch?v=" + response.nextVideo,
);
url.searchParams.set('list', plid);
if (!plid.startsWith('RD'))
url.searchParams.set('index', response.index);
if (video_data.params.autoplay || video_data.params.continue_autoplay)
url.searchParams.set('autoplay', '1');
if (video_data.params.listen !== video_data.preferences.listen)
url.searchParams.set('listen', video_data.params.listen);
if (video_data.params.speed !== video_data.preferences.speed)
url.searchParams.set('speed', video_data.params.speed);
if (video_data.params.local !== video_data.preferences.local)
url.searchParams.set('local', video_data.params.local);
url.searchParams.set("list", plid);
if (!plid.startsWith("RD"))
url.searchParams.set("index", response.index);
if (video_data.params.autoplay || video_data.params.continue_autoplay)
url.searchParams.set("autoplay", "1");
if (video_data.params.listen !== video_data.preferences.listen)
url.searchParams.set("listen", video_data.params.listen);
if (video_data.params.speed !== video_data.preferences.speed)
url.searchParams.set("speed", video_data.params.speed);
if (video_data.params.local !== video_data.preferences.local)
url.searchParams.set("local", video_data.params.local);
location.assign(url.pathname + url.search);
});
},
onNon200: function (xhr) {
playlist.innerHTML = '';
document.getElementById('continue').style.display = '';
},
onError: function (xhr) {
playlist.innerHTML = spinnerHTMLwithHR;
},
onTimeout: function (xhr) {
playlist.innerHTML = spinnerHTMLwithHR;
}
});
location.assign(url.pathname + url.search);
});
},
onNon200: function (xhr) {
playlist.innerHTML = "";
document.getElementById("continue").style.display = "";
},
onError: function (xhr) {
playlist.innerHTML = spinnerHTMLwithHR;
},
onTimeout: function (xhr) {
playlist.innerHTML = spinnerHTMLwithHR;
},
},
);
}
function get_reddit_comments() {
var comments = document.getElementById('comments');
var comments = document.getElementById("comments");
var fallback = comments.innerHTML;
comments.innerHTML = spinnerHTML;
var fallback = comments.innerHTML;
comments.innerHTML = spinnerHTML;
var url = '/api/v1/comments/' + video_data.id +
'?source=reddit&format=html' +
'&hl=' + video_data.preferences.locale;
var url =
"/api/v1/comments/" +
video_data.id +
"?source=reddit&format=html" +
"&hl=" +
video_data.preferences.locale;
var onNon200 = function (xhr) { comments.innerHTML = fallback; };
if (video_data.params.comments[1] === 'youtube')
onNon200 = function (xhr) {};
var onNon200 = function (xhr) {
comments.innerHTML = fallback;
};
if (video_data.params.comments[1] === "youtube") onNon200 = function (xhr) {};
helpers.xhr('GET', url, {retries: 5, entity_name: ''}, {
on200: function (response) {
comments.innerHTML = ' \
helpers.xhr(
"GET",
url,
{ retries: 5, entity_name: "" },
{
on200: function (response) {
comments.innerHTML = ' \
<div> \
<h3> \
<a href="javascript:void(0)">[ ]</a> \
@ -148,52 +172,52 @@ function get_reddit_comments() {
</div> \
<div>{contentHtml}</div> \
<hr>'.supplant({
title: response.title,
youtubeCommentsText: video_data.youtube_comments_text,
redditPermalinkText: video_data.reddit_permalink_text,
permalink: response.permalink,
contentHtml: response.contentHtml
});
title: response.title,
youtubeCommentsText: video_data.youtube_comments_text,
redditPermalinkText: video_data.reddit_permalink_text,
permalink: response.permalink,
contentHtml: response.contentHtml,
});
comments.children[0].children[0].children[0].onclick = toggle_comments;
comments.children[0].children[1].children[0].onclick = swap_comments;
},
onNon200: onNon200, // declared above
});
comments.children[0].children[0].children[0].onclick = toggle_comments;
comments.children[0].children[1].children[0].onclick = swap_comments;
},
onNon200: onNon200, // declared above
},
);
}
if (video_data.play_next) {
player.on('ended', function () {
var url = new URL('https://example.com/watch?v=' + video_data.next_video);
player.on("ended", function () {
var url = new URL("https://example.com/watch?v=" + video_data.next_video);
if (video_data.params.autoplay || video_data.params.continue_autoplay)
url.searchParams.set('autoplay', '1');
if (video_data.params.listen !== video_data.preferences.listen)
url.searchParams.set('listen', video_data.params.listen);
if (video_data.params.speed !== video_data.preferences.speed)
url.searchParams.set('speed', video_data.params.speed);
if (video_data.params.local !== video_data.preferences.local)
url.searchParams.set('local', video_data.params.local);
url.searchParams.set('continue', '1');
if (video_data.params.autoplay || video_data.params.continue_autoplay)
url.searchParams.set("autoplay", "1");
if (video_data.params.listen !== video_data.preferences.listen)
url.searchParams.set("listen", video_data.params.listen);
if (video_data.params.speed !== video_data.preferences.speed)
url.searchParams.set("speed", video_data.params.speed);
if (video_data.params.local !== video_data.preferences.local)
url.searchParams.set("local", video_data.params.local);
url.searchParams.set("continue", "1");
location.assign(url.pathname + url.search);
});
location.assign(url.pathname + url.search);
});
}
addEventListener('load', function (e) {
if (video_data.plid)
get_playlist(video_data.plid);
addEventListener("load", function (e) {
if (video_data.plid) get_playlist(video_data.plid);
if (video_data.params.comments[0] === 'youtube') {
get_youtube_comments();
} else if (video_data.params.comments[0] === 'reddit') {
get_reddit_comments();
} else if (video_data.params.comments[1] === 'youtube') {
get_youtube_comments();
} else if (video_data.params.comments[1] === 'reddit') {
get_reddit_comments();
} else {
var comments = document.getElementById('comments');
comments.innerHTML = '';
}
if (video_data.params.comments[0] === "youtube") {
get_youtube_comments();
} else if (video_data.params.comments[0] === "reddit") {
get_reddit_comments();
} else if (video_data.params.comments[1] === "youtube") {
get_youtube_comments();
} else if (video_data.params.comments[1] === "reddit") {
get_reddit_comments();
} else {
var comments = document.getElementById("comments");
comments.innerHTML = "";
}
});

View File

@ -1,24 +1,24 @@
'use strict';
var save_player_pos_key = 'save_player_pos';
"use strict";
var save_player_pos_key = "save_player_pos";
function get_all_video_times() {
return helpers.storage.get(save_player_pos_key) || {};
return helpers.storage.get(save_player_pos_key) || {};
}
document.querySelectorAll('.watched-indicator').forEach(function (indicator) {
var watched_part = get_all_video_times()[indicator.dataset.id];
var total = parseInt(indicator.dataset.length, 10);
if (watched_part === undefined) {
watched_part = total;
}
var percentage = Math.round((watched_part / total) * 100);
document.querySelectorAll(".watched-indicator").forEach(function (indicator) {
var watched_part = get_all_video_times()[indicator.dataset.id];
var total = parseInt(indicator.dataset.length, 10);
if (watched_part === undefined) {
watched_part = total;
}
var percentage = Math.round((watched_part / total) * 100);
if (percentage < 5) {
percentage = 5;
}
if (percentage > 90) {
percentage = 100;
}
if (percentage < 5) {
percentage = 5;
}
if (percentage > 90) {
percentage = 100;
}
indicator.style.width = percentage + '%';
indicator.style.width = percentage + "%";
});

View File

@ -1,34 +1,50 @@
'use strict';
var watched_data = JSON.parse(document.getElementById('watched_data').textContent);
var payload = 'csrf_token=' + watched_data.csrf_token;
"use strict";
var watched_data = JSON.parse(
document.getElementById("watched_data").textContent,
);
var payload = "csrf_token=" + watched_data.csrf_token;
function mark_watched(target) {
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
tile.style.display = 'none';
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
tile.style.display = "none";
var url = '/watch_ajax?action=mark_watched&redirect=false' +
'&id=' + target.getAttribute('data-id');
var url =
"/watch_ajax?action=mark_watched&redirect=false" +
"&id=" +
target.getAttribute("data-id");
helpers.xhr('POST', url, {payload: payload}, {
onNon200: function (xhr) {
tile.style.display = '';
}
});
helpers.xhr(
"POST",
url,
{ payload: payload },
{
onNon200: function (xhr) {
tile.style.display = "";
},
},
);
}
function mark_unwatched(target) {
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
tile.style.display = 'none';
var count = document.getElementById('count');
count.textContent--;
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
tile.style.display = "none";
var count = document.getElementById("count");
count.textContent--;
var url = '/watch_ajax?action=mark_unwatched&redirect=false' +
'&id=' + target.getAttribute('data-id');
var url =
"/watch_ajax?action=mark_unwatched&redirect=false" +
"&id=" +
target.getAttribute("data-id");
helpers.xhr('POST', url, {payload: payload}, {
onNon200: function (xhr) {
count.textContent++;
tile.style.display = '';
}
});
helpers.xhr(
"POST",
url,
{ payload: payload },
{
onNon200: function (xhr) {
count.textContent++;
tile.style.display = "";
},
},
);
}

View File

@ -89,13 +89,6 @@ module Invidious::Frontend::Pagination
end
def nav_ctoken(locale : String?, *, base_url : String | URI, ctoken : String?, first_page : Bool, params : URI::Params)
return String.build do |str|
if !ctoken.nil?
str << %(<nav class="pagination">\n<ul>\n)
str << %(<li>)
params_next = URI::Params{"continuation" => ctoken}
url_next = HttpServer::Utils.add_params_to_url(base_url, params_next)
return String.build do |str|
str << %(<nav class="pagination">\n<ul>\n)
str << %(<li>)
@ -106,13 +99,13 @@ module Invidious::Frontend::Pagination
if !ctoken.nil?
params["continuation"] = ctoken
url_next = HttpServer::Utils.add_params_to_url(base_url, params)
self.next_page(str, locale, url_next.to_s)
str << %(</li>\n)
str << %(</ul>\n</nav>\n)
end
self.next_page(str, locale, url_next.to_s)
str << %(</li>\n)
str << %(</ul>\n</nav>\n)
end
end
end