diff --git a/js&css/extension/init.js b/js&css/extension/init.js
index a7801f0c9..121d96596 100644
--- a/js&css/extension/init.js
+++ b/js&css/extension/init.js
@@ -1,251 +1,287 @@
/*--------------------------------------------------------------
>>> INITIALIZATION
--------------------------------------------------------------*/
-extension.features.youtubeHomePage('init');
+extension.features.youtubeHomePage("init");
-document.documentElement.setAttribute('it-pathname', location.pathname);
+document.documentElement.setAttribute("it-pathname", location.pathname);
-window.addEventListener('yt-navigate-finish', function () {
- document.documentElement.setAttribute('it-pathname', location.pathname);
+window.addEventListener("yt-navigate-finish", function () {
+ document.documentElement.setAttribute("it-pathname", location.pathname);
- extension.features.trackWatchedVideos();
- extension.features.thumbnailsQuality();
+ extension.features.trackWatchedVideos();
+ extension.features.thumbnailsQuality();
});
extension.messages.create();
extension.messages.listener();
-extension.events.on('init', function (resolve) {
- extension.storage.listener();
- extension.storage.load(function () {
- resolve();
- });
-}, {
- async: true
-});
-
-function bodyReady () {
- if (extension.ready && extension.domReady) {
- extension.features.addScrollToTop();
- extension.features.font();
- extension.features.changeThumbnailsPerRow?.();
- extension.features.clickableLinksInVideoDescriptions();
- }
+extension.events.on(
+ "init",
+ function (resolve) {
+ extension.storage.listener();
+ extension.storage.load(function () {
+ resolve();
+ });
+ },
+ {
+ async: true,
+ }
+);
+
+function bodyReady() {
+ if (extension.ready && extension.domReady) {
+ extension.features.addScrollToTop();
+ extension.features.font();
+ extension.features.changeThumbnailsPerRow?.();
+ extension.features.clickableLinksInVideoDescriptions();
+ }
}
-extension.events.on('init', function () {
- extension.features.bluelight();
- extension.features.dim();
- extension.features.youtubeHomePage();
- extension.features.collapseOfSubscriptionSections();
- extension.features.confirmationBeforeClosing();
- extension.features.defaultContentCountry();
- extension.features.popupWindowButtons();
- extension.features.disableThumbnailPlayback();
- extension.features.markWatchedVideos();
- extension.features.relatedVideos();
- extension.features.comments();
- extension.features.openNewTab();
- extension.features.removeListParamOnNewTab();
- bodyReady();
-});
-
-chrome.runtime.sendMessage({
- action: 'tab-connected'
-}, function (response) {
- if (response) {
- extension.tabId = response.tabId;
- }
+extension.events.on("init", function () {
+ extension.features.bluelight();
+ extension.features.dim();
+ extension.features.youtubeHomePage();
+ extension.features.collapseOfSubscriptionSections();
+ extension.features.confirmationBeforeClosing();
+ extension.features.defaultContentCountry();
+ extension.features.popupWindowButtons();
+ extension.features.disableThumbnailPlayback();
+ extension.features.markWatchedVideos();
+ extension.features.relatedVideos();
+ extension.features.comments();
+ extension.features.openNewTab();
+ extension.features.removeListParamOnNewTab();
+ bodyReady();
});
-extension.inject([
- '/js&css/web-accessible/core.js',
- '/js&css/web-accessible/functions.js',
- '/js&css/web-accessible/www.youtube.com/appearance.js',
- '/js&css/web-accessible/www.youtube.com/themes.js',
- '/js&css/web-accessible/www.youtube.com/player.js',
- '/js&css/web-accessible/www.youtube.com/playlist.js',
- '/js&css/web-accessible/www.youtube.com/channel.js',
- '/js&css/web-accessible/www.youtube.com/shortcuts.js',
- '/js&css/web-accessible/www.youtube.com/blocklist.js',
- '/js&css/web-accessible/www.youtube.com/settings.js',
- '/js&css/web-accessible/init.js'
-], function () {
- extension.ready = true;
-
- extension.events.trigger('init');
-});
-
-document.addEventListener('DOMContentLoaded', function () {
- extension.domReady = true;
-
- bodyReady();
+chrome.runtime.sendMessage(
+ {
+ action: "tab-connected",
+ },
+ function (response) {
+ if (response) {
+ extension.tabId = response.tabId;
+ }
+ }
+);
+
+extension.inject(
+ [
+ "/js&css/web-accessible/core.js",
+ "/js&css/web-accessible/functions.js",
+ "/js&css/web-accessible/www.youtube.com/appearance.js",
+ "/js&css/web-accessible/www.youtube.com/themes.js",
+ "/js&css/web-accessible/www.youtube.com/player.js",
+ "/js&css/web-accessible/www.youtube.com/playlist.js",
+ "/js&css/web-accessible/www.youtube.com/channel.js",
+ "/js&css/web-accessible/www.youtube.com/shortcuts.js",
+ "/js&css/web-accessible/www.youtube.com/blocklist.js",
+ "/js&css/web-accessible/www.youtube.com/settings.js",
+ "/js&css/web-accessible/init.js",
+ ],
+ function () {
+ extension.ready = true;
+
+ extension.events.trigger("init");
+ }
+);
+
+document.addEventListener("DOMContentLoaded", function () {
+ extension.domReady = true;
+
+ bodyReady();
});
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
- if (request.action === 'focus') {
- extension.messages.send({
- focus: true
- });
- } else if (request.action === 'blur') {
- extension.messages.send({
- blur: true
- });
- } else if (request.action === 'pause') {
- extension.messages.send({
- pause: true
- });
- } else if (request.action === 'set-volume') {
- extension.messages.send({
- setVolume: request.value
- });
- } else if (request.action === 'set-playback-speed') {
- extension.messages.send({
- setPlaybackSpeed: request.value
- });
- } else if (request.action === 'mixer') {
- extension.messages.send({
- mixer: true
- }, sendResponse, 'mixer');
-
- return true;
- } else if (request.action === 'delete-youtube-cookies') {
- extension.messages.send({
- deleteCookies: true
- });
- } else if (request.action === "another-video-started-playing") {
- extension.features.onlyOnePlayerInstancePlaying();
- }
+ if (request.action === "focus") {
+ extension.messages.send({
+ focus: true,
+ });
+ } else if (request.action === "blur") {
+ extension.messages.send({
+ blur: true,
+ });
+ } else if (request.action === "pause") {
+ extension.messages.send({
+ pause: true,
+ });
+ } else if (request.action === "set-volume") {
+ extension.messages.send({
+ setVolume: request.value,
+ });
+ } else if (request.action === "set-playback-speed") {
+ extension.messages.send({
+ setPlaybackSpeed: request.value,
+ });
+ } else if (request.action === "mixer") {
+ extension.messages.send(
+ {
+ mixer: true,
+ },
+ sendResponse,
+ "mixer"
+ );
+
+ return true;
+ } else if (request.action === "delete-youtube-cookies") {
+ extension.messages.send({
+ deleteCookies: true,
+ });
+ } else if (request.action === "another-video-started-playing") {
+ extension.features.onlyOnePlayerInstancePlaying();
+ }
});
-document.addEventListener('it-message-from-youtube', function () {
- var provider = document.querySelector('#it-messages-from-youtube');
-
- if (provider) {
- var message = provider.textContent;
-
- document.dispatchEvent(new CustomEvent('it-message-from-youtube--readed'));
-
- try {
- message = JSON.parse(message);
- } catch (error) {
- console.log(error);
- }
-
- //console.log(message);
-
- if (message.requestOptionsUrl === true) {
- extension.messages.send({
- responseOptionsUrl: chrome.runtime.getURL('menu/index.html')
- });
- } else if (message.onlyOnePlayer === true) {
- chrome.runtime.sendMessage({
- name: 'only-one-player'
- });
- } else if (message.action === 'fixPopup') {
- chrome.runtime.sendMessage({
- action: 'fixPopup',
- width: message.width,
- height: message.height,
- title: message.title,
- });
- } else if (message.action === 'analyzer') {
- if (extension.storage.data.analyzer_activation === true) {
- var data = message.name,
- date = new Date().toDateString(),
- hours = new Date().getHours() + ':00';
-
- if (!extension.storage.data.analyzer) {
- extension.storage.data.analyzer = {};
- }
-
- if (!extension.storage.data.analyzer[date]) {
- extension.storage.data.analyzer[date] = {};
- }
-
- if (!extension.storage.data.analyzer[date][hours]) {
- extension.storage.data.analyzer[date][hours] = {};
- }
-
- if (!extension.storage.data.analyzer[date][hours][data]) {
- extension.storage.data.analyzer[date][hours][data] = 0;
- }
-
- extension.storage.data.analyzer[date][hours][data]++;
-
- chrome.storage.local.set({
- analyzer: extension.storage.data.analyzer
- });
- }
- } else if (message.action === 'blocklist') {
- if (!extension.storage.data.blocklist || typeof extension.storage.data.blocklist !== 'object') {
- extension.storage.data.blocklist = {videos: {}, channels: {}};
- }
-
- switch (message.type) {
- case 'channel':
- if (!extension.storage.data.blocklist.channels || typeof extension.storage.data.blocklist.channels !== 'object') {
- extension.storage.data.blocklist.channels = {};
- }
- if (message.added) {
- extension.storage.data.blocklist.channels[message.id] = {
- title: message.title,
- preview: message.preview,
- when: message.when
- }
- } else {
- delete extension.storage.data.blocklist.channels[message.id];
- }
- break
-
- case 'video':
- if (!extension.storage.data.blocklist.videos || typeof extension.storage.data.blocklist.videos !== 'object') {
- extension.storage.data.blocklist.videos = {};
- }
- if (message.added) {
- extension.storage.data.blocklist.videos[message.id] = {
- title: message.title,
- when: message.when
- }
- } else {
- delete extension.storage.data.blocklist.videos[message.id];
- }
- break
- }
-
- chrome.storage.local.set({
- blocklist: extension.storage.data.blocklist
- });
- } else if (message.action === 'watched') {
- if (!extension.storage.data.watched || typeof extension.storage.data.watched !== 'object') {
- extension.storage.data.watched = {};
- }
-
- if (message.type === 'add') {
- extension.storage.data.watched[message.id] = {
- title: message.title
- };
- }
-
- if (message.type === 'remove') {
- delete extension.storage.data.watched[message.id];
- }
-
- chrome.storage.local.set({
- watched: extension.storage.data.watched
- });
- } else if (message.action === 'set') {
- if (message.value) {
- chrome.storage.local.set({[message.key]: message.value});
- } else {
- chrome.storage.local.remove([message.key]);
- }
- }
- }
+document.addEventListener("it-message-from-youtube", function () {
+ var provider = document.querySelector("#it-messages-from-youtube");
+
+ if (provider) {
+ var message = provider.textContent;
+
+ document.dispatchEvent(new CustomEvent("it-message-from-youtube--readed"));
+
+ try {
+ message = JSON.parse(message);
+ } catch (error) {
+ console.log(error);
+ }
+
+ //console.log(message);
+
+ if (message.requestOptionsUrl === true) {
+ extension.messages.send({
+ responseOptionsUrl: chrome.runtime.getURL("menu/index.html"),
+ });
+ } else if (message.onlyOnePlayer === true) {
+ chrome.runtime.sendMessage({
+ name: "only-one-player",
+ });
+ } else if (message.action === "fixPopup") {
+ chrome.runtime.sendMessage({
+ action: "fixPopup",
+ width: message.width,
+ height: message.height,
+ title: message.title,
+ });
+ } else if (message.action === "analyzer") {
+ if (extension.storage.data.analyzer_activation === true) {
+ var data = message.name,
+ date = new Date().toDateString(),
+ hours = new Date().getHours() + ":00";
+
+ if (!extension.storage.data.analyzer) {
+ extension.storage.data.analyzer = {};
+ }
+
+ if (!extension.storage.data.analyzer[date]) {
+ extension.storage.data.analyzer[date] = {};
+ }
+
+ if (!extension.storage.data.analyzer[date][hours]) {
+ extension.storage.data.analyzer[date][hours] = {};
+ }
+
+ if (!extension.storage.data.analyzer[date][hours][data]) {
+ extension.storage.data.analyzer[date][hours][data] = 0;
+ }
+
+ extension.storage.data.analyzer[date][hours][data]++;
+
+ chrome.storage.local.set({
+ analyzer: extension.storage.data.analyzer,
+ });
+ }
+ } else if (message.action === "blocklist") {
+ if (
+ !extension.storage.data.blocklist ||
+ typeof extension.storage.data.blocklist !== "object"
+ ) {
+ extension.storage.data.blocklist = { videos: {}, channels: {} };
+ }
+
+ switch (message.type) {
+ case "channel":
+ if (
+ !extension.storage.data.blocklist.channels ||
+ typeof extension.storage.data.blocklist.channels !== "object"
+ ) {
+ extension.storage.data.blocklist.channels = {};
+ }
+ if (message.added) {
+ extension.storage.data.blocklist.channels[message.id] = {
+ title: message.title,
+ preview: message.preview,
+ when: message.when,
+ };
+ } else {
+ delete extension.storage.data.blocklist.channels[message.id];
+ }
+ break;
+
+ case "video":
+ if (
+ !extension.storage.data.blocklist.videos ||
+ typeof extension.storage.data.blocklist.videos !== "object"
+ ) {
+ extension.storage.data.blocklist.videos = {};
+ }
+ if (message.added) {
+ extension.storage.data.blocklist.videos[message.id] = {
+ title: message.title,
+ when: message.when,
+ };
+ } else {
+ delete extension.storage.data.blocklist.videos[message.id];
+ }
+ break;
+ }
+
+ chrome.storage.local.set({
+ blocklist: extension.storage.data.blocklist,
+ });
+ } else if (message.action === "watched") {
+ if (
+ !extension.storage.data.watched ||
+ typeof extension.storage.data.watched !== "object"
+ ) {
+ extension.storage.data.watched = {};
+ }
+
+ if (message.type === "add") {
+ extension.storage.data.watched[message.id] = {
+ title: message.title,
+ };
+ }
+
+ if (message.type === "remove") {
+ delete extension.storage.data.watched[message.id];
+ }
+
+ chrome.storage.local.set({
+ watched: extension.storage.data.watched,
+ });
+ } else if (message.action === "set") {
+ if (message.value) {
+ chrome.storage.local.set({ [message.key]: message.value });
+ } else {
+ chrome.storage.local.remove([message.key]);
+ }
+ }
+ }
});
-document.addEventListener('it-play', function () {
- // var videos = document.querySelectorAll('video');
- try {chrome.runtime.sendMessage({action: 'play'})
- } catch (error) {console.log(error); setTimeout(function () { try { chrome.runtime.sendMessage({action: 'play'}, function (response) { console.log(response) } ); } catch { } }, 321) }
-});
\ No newline at end of file
+document.addEventListener("it-play", function () {
+ // var videos = document.querySelectorAll('video');
+ try {
+ chrome.runtime.sendMessage({ action: "play" });
+ } catch (error) {
+ console.log(error);
+ setTimeout(function () {
+ try {
+ chrome.runtime.sendMessage({ action: "play" }, function (response) {
+ console.log(response);
+ });
+ } catch {}
+ }, 321);
+ }
+});
diff --git a/js&css/web-accessible/functions.js b/js&css/web-accessible/functions.js
index b2808b708..ba8165767 100644
--- a/js&css/web-accessible/functions.js
+++ b/js&css/web-accessible/functions.js
@@ -2,19 +2,29 @@
>>> FUNCTIONS
--------------------------------------------------------------*/
ImprovedTube.childHandler = function (node) {
- //console.log(node.nodeName);
- if (node.nodeName === 'SCRIPT' || node.nodeName === 'iron-iconset-svg' || node.nodeName === 'svg' || node.nodeName === 'SPAN' || node.nodeName === '#text' || node.nodeName === '#comment' || node.nodeName === 'yt-icon-shape' || node.nodeName === 'DOM-IF' || node.nodeName === 'DOM-REPEAT') {
- return
- }
- var children = node.children;
- this.ytElementsHandler(node);
-
- if (children) {
- for (var i = 0, l = children.length; i < l; i++) {
- ImprovedTube.childHandler(children[i]);
- }
- }
-}
+ //console.log(node.nodeName);
+ if (
+ node.nodeName === "SCRIPT" ||
+ node.nodeName === "iron-iconset-svg" ||
+ node.nodeName === "svg" ||
+ node.nodeName === "SPAN" ||
+ node.nodeName === "#text" ||
+ node.nodeName === "#comment" ||
+ node.nodeName === "yt-icon-shape" ||
+ node.nodeName === "DOM-IF" ||
+ node.nodeName === "DOM-REPEAT"
+ ) {
+ return;
+ }
+ var children = node.children;
+ this.ytElementsHandler(node);
+
+ if (children) {
+ for (var i = 0, l = children.length; i < l; i++) {
+ ImprovedTube.childHandler(children[i]);
+ }
+ }
+};
/*
const DOM_filter = /^(SCRIPT|DOM-IF|DOM-REPEAT|svg|SPAN|#text|#comment|yt-icon-shape|iron-iconset-svg)$/;
@@ -33,457 +43,593 @@ ImprovedTube.childHandler = function (node) { //console.log(node.nodeName);
}; */
ImprovedTube.ytElementsHandler = function (node) {
- const name = node.nodeName,
- id = node.id;
-
- if (name === 'A') {
- if (node.href) {
- this.channelDefaultTab(node);
- }
- if (this.storage.blocklist_activate) {
- // we are interested in thumbnails and video-previews, skip ones with 'button.it-add-to-blocklist' already
- if (((node.href && node.classList.contains('ytd-thumbnail')) || node.classList.contains('ytd-video-preview'))
- && !node.querySelector("button.it-add-to-blocklist")) {
- this.blocklistNode(node);
- }
- }
- } else if (name === 'YTD-TOGGLE-BUTTON-RENDERER' || name === 'YTD-PLAYLIST-LOOP-BUTTON-RENDERER') {
- //can be precise previously node.parentComponent & node.parentComponent.parentComponent
- if (node.closest("YTD-MENU-RENDERER")
- && node.closest("YTD-PLAYLIST-PANEL-RENDERER")) {
-
- var index = Array.prototype.indexOf.call(node.parentNode.children, node);
- if (index === 0) {
- if (this.storage.playlist_reverse === true) {
- //can be precise:
- try {this.elements.playlist.actions = node.parentNode.parentNode.parentNode.parentNode;}
- catch {try {this.elements.playlist.actions = node.parentNode.parentNode.parentNode;}
- catch {try {this.elements.playlist.actions = node.parentNode.parentNode;}
- catch {try {this.elements.playlist.actions = node.parentNode;}
- catch {try {this.elements.playlist.actions = node;} catch {}}
- }
- }
- }
- }
- this.playlistReverse();
- } else if (index === 1) {
- this.elements.playlist.shuffle_button = node;
-
- this.playlistShuffle();
-
- if (this.storage.playlist_reverse === true) {
- //can be precise:
- try {this.elements.playlist.actions = node.parentNode.parentNode.parentNode.parentNode;}
- catch {try {this.elements.playlist.actions = node.parentNode.parentNode.parentNode;}
- catch {try {this.elements.playlist.actions = node.parentNode.parentNode;}
- catch {try {this.elements.playlist.actions = node.parentNode;}
- catch {try {this.elements.playlist.actions = node;} catch {}}
- }
- }
- }
- }
- this.playlistReverse();
- }
- }
- } else if (name === 'YTD-GUIDE-SECTION-RENDERER') {
- if (!this.elements.sidebar_section) {
- this.elements.sidebar_section = node;
-
- this.improvedtubeYoutubeIcon();
- }
- } else if (name === 'YTD-VIDEO-PRIMARY-INFO-RENDERER') {
- this.elements.video_title = node.querySelector('.title.ytd-video-primary-info-renderer');
-
- this.improvedtubeYoutubeIcon();
- this.improvedtubeYoutubeButtonsUnderPlayer();
+ const name = node.nodeName,
+ id = node.id;
- } else if (name === 'YTD-VIDEO-SECONDARY-INFO-RENDERER') {
- this.elements.yt_channel_name = node.querySelector('ytd-channel-name');
- this.elements.yt_channel_link = node.querySelector('ytd-channel-name a');
+ if (name === "A") {
+ if (node.href) {
+ this.channelDefaultTab(node);
+ }
+ if (this.storage.blocklist_activate) {
+ // we are interested in thumbnails and video-previews, skip ones with 'button.it-add-to-blocklist' already
+ if (
+ ((node.href && node.classList.contains("ytd-thumbnail")) ||
+ node.classList.contains("ytd-video-preview")) &&
+ !node.querySelector("button.it-add-to-blocklist")
+ ) {
+ this.blocklistNode(node);
+ }
+ }
+ } else if (
+ name === "YTD-TOGGLE-BUTTON-RENDERER" ||
+ name === "YTD-PLAYLIST-LOOP-BUTTON-RENDERER"
+ ) {
+ //can be precise previously node.parentComponent & node.parentComponent.parentComponent
+ if (
+ node.closest("YTD-MENU-RENDERER") &&
+ node.closest("YTD-PLAYLIST-PANEL-RENDERER")
+ ) {
+ var index = Array.prototype.indexOf.call(node.parentNode.children, node);
+ if (index === 0) {
+ if (this.storage.playlist_reverse === true) {
+ //can be precise:
+ try {
+ this.elements.playlist.actions =
+ node.parentNode.parentNode.parentNode.parentNode;
+ } catch {
+ try {
+ this.elements.playlist.actions =
+ node.parentNode.parentNode.parentNode;
+ } catch {
+ try {
+ this.elements.playlist.actions = node.parentNode.parentNode;
+ } catch {
+ try {
+ this.elements.playlist.actions = node.parentNode;
+ } catch {
+ try {
+ this.elements.playlist.actions = node;
+ } catch {}
+ }
+ }
+ }
+ }
+ }
+ this.playlistReverse();
+ } else if (index === 1) {
+ this.elements.playlist.shuffle_button = node;
+
+ this.playlistShuffle();
+
+ if (this.storage.playlist_reverse === true) {
+ //can be precise:
+ try {
+ this.elements.playlist.actions =
+ node.parentNode.parentNode.parentNode.parentNode;
+ } catch {
+ try {
+ this.elements.playlist.actions =
+ node.parentNode.parentNode.parentNode;
+ } catch {
+ try {
+ this.elements.playlist.actions = node.parentNode.parentNode;
+ } catch {
+ try {
+ this.elements.playlist.actions = node.parentNode;
+ } catch {
+ try {
+ this.elements.playlist.actions = node;
+ } catch {}
+ }
+ }
+ }
+ }
+ }
+ this.playlistReverse();
+ }
+ }
+ } else if (name === "YTD-GUIDE-SECTION-RENDERER") {
+ if (!this.elements.sidebar_section) {
+ this.elements.sidebar_section = node;
- if (document.documentElement.dataset.pageType === 'video') {
- this.howLongAgoTheVideoWasUploaded();
- this.channelVideosCount();
- this.exactUploadDate();
- }
- //} else if (name === 'YTD-MENU-RENDERER' && node.classList.contains('ytd-video-primary-info-renderer')) {
- // if (document.documentElement.dataset.pageType === 'video') {
- // this.hideDetailButton(node.querySelector('#flexible-item-buttons').children);
- // }
- } else if (name === 'YTD-PLAYLIST-HEADER-RENDERER' || (name === 'YTD-MENU-RENDERER' && node.classList.contains('ytd-playlist-panel-renderer'))) {
- this.playlistPopup();
- } else if (name === 'YTD-SUBSCRIBE-BUTTON-RENDERER'
- || name === 'YT-SUBSCRIBE-BUTTON-VIEW-MODEL'
- || (name === 'YTD-BUTTON-RENDERER' && node.classList.contains('ytd-c4-tabbed-header-renderer'))) {
- ImprovedTube.blocklistChannel(node);
- ImprovedTube.elements.subscribe_button = node;
- } else if (id === 'chat-messages') {
- this.elements.livechat.button = document.querySelector('[aria-label="Close"]');
- // console.log(document.querySelector('[aria-label="Close"]'))
- this.livechat();
- } else if (name === 'YTD-MASTHEAD') {
- if (!this.elements.masthead) {
- this.elements.masthead = {start: node.querySelector('#start'),
- end: node.querySelector('#end'),
- logo: node.querySelector('a#logo')
- };
-
- this.improvedtubeYoutubeIcon();
- }
- } else if (name === 'TP-YT-APP-DRAWER') {
- if (!this.elements.app_drawer) {
- this.elements.app_drawer = {start: node.querySelector('div#header'),
- logo: node.querySelector('a#logo')
- };
+ this.improvedtubeYoutubeIcon();
+ }
+ } else if (name === "YTD-VIDEO-PRIMARY-INFO-RENDERER") {
+ this.elements.video_title = node.querySelector(
+ ".title.ytd-video-primary-info-renderer"
+ );
+
+ this.improvedtubeYoutubeIcon();
+ this.improvedtubeYoutubeButtonsUnderPlayer();
+ } else if (name === "YTD-VIDEO-SECONDARY-INFO-RENDERER") {
+ this.elements.yt_channel_name = node.querySelector("ytd-channel-name");
+ this.elements.yt_channel_link = node.querySelector("ytd-channel-name a");
+
+ if (document.documentElement.dataset.pageType === "video") {
+ this.howLongAgoTheVideoWasUploaded();
+ this.channelVideosCount();
+ this.exactUploadDate();
+ }
+ //} else if (name === 'YTD-MENU-RENDERER' && node.classList.contains('ytd-video-primary-info-renderer')) {
+ // if (document.documentElement.dataset.pageType === 'video') {
+ // this.hideDetailButton(node.querySelector('#flexible-item-buttons').children);
+ // }
+ } else if (
+ name === "YTD-PLAYLIST-HEADER-RENDERER" ||
+ (name === "YTD-MENU-RENDERER" &&
+ node.classList.contains("ytd-playlist-panel-renderer"))
+ ) {
+ this.playlistPopup();
+ } else if (
+ name === "YTD-SUBSCRIBE-BUTTON-RENDERER" ||
+ name === "YT-SUBSCRIBE-BUTTON-VIEW-MODEL" ||
+ (name === "YTD-BUTTON-RENDERER" &&
+ node.classList.contains("ytd-c4-tabbed-header-renderer"))
+ ) {
+ ImprovedTube.blocklistChannel(node);
+ ImprovedTube.elements.subscribe_button = node;
+ } else if (id === "chat-messages") {
+ this.elements.livechat.button = document.querySelector(
+ '[aria-label="Close"]'
+ );
+ // console.log(document.querySelector('[aria-label="Close"]'))
+ this.livechat();
+ } else if (name === "YTD-MASTHEAD") {
+ if (!this.elements.masthead) {
+ this.elements.masthead = {
+ start: node.querySelector("#start"),
+ end: node.querySelector("#end"),
+ logo: node.querySelector("a#logo"),
+ };
+
+ this.improvedtubeYoutubeIcon();
+ }
+ } else if (name === "TP-YT-APP-DRAWER") {
+ if (!this.elements.app_drawer) {
+ this.elements.app_drawer = {
+ start: node.querySelector("div#header"),
+ logo: node.querySelector("a#logo"),
+ };
+
+ this.improvedtubeYoutubeIcon();
+ }
+ } else if (name === "YTD-PLAYER") {
+ if (!this.elements.ytd_player) {
+ ImprovedTube.elements.ytd_player = node;
+ }
+ } else if (id === "shorts-player") {
+ if (!this.elements.shorts_player) {
+ ImprovedTube.elements.shorts_player = node;
+ }
+ } else if (id === "movie_player") {
+ if (!this.elements.player) {
+ ImprovedTube.elements.player = node;
+ ImprovedTube._mutedAdsObserverInitialized = false;
+
+ if (ImprovedTube.storage.ads === "mute_ads") {
+ ImprovedTube.muteAds();
+ }
+
+ // if (this.storage.player_autoplay === false) { ImprovedTube.elements.player.stopVideo(); }
+ ImprovedTube.elements.video = node.querySelector("video");
+ ImprovedTube.elements.player_left_controls =
+ node.querySelector(".ytp-left-controls");
+ ImprovedTube.elements.player_right_controls = node.querySelector(
+ ".ytp-right-controls"
+ );
+ ImprovedTube.elements.player_thumbnail = node.querySelector(
+ ".ytp-cued-thumbnail-overlay-image"
+ );
+ ImprovedTube.elements.player_subtitles_button = node.querySelector(
+ ".ytp-subtitles-button"
+ );
+ ImprovedTube.playerSize();
+ if (
+ typeof this.storage.ads !== "undefined" &&
+ this.storage.ads !== "all_videos"
+ ) {
+ new MutationObserver(function (mutationList) {
+ for (var i = 0, l = mutationList.length; i < l; i++) {
+ var mutation = mutationList[i];
+
+ if (mutation.type === "childList") {
+ for (var j = 0, k = mutation.addedNodes.length; j < k; j++) {
+ var node = mutation.addedNodes[j];
+
+ if (
+ node instanceof Element &&
+ node.querySelector(
+ 'ytp-ad-player-overlay, .ytp-ad-text, .ytp-ad-overlay-close-container, ytd-button-renderer#dismiss-button, *[id^="ad-text"], *[id^="skip-button"], .ytp-ad-skip-button.ytp-button, .ytp-ad-skip-button-modern.ytp-button'
+ ) !== null
+ ) {
+ ImprovedTube.playerAds(node);
+ }
+ }
+ }
+ if (
+ mutation.type === "attributes" &&
+ mutation.attributeName === "id" &&
+ mutation.target.querySelector(
+ '*[id^="ad-text"], *[id^="skip-button"], .ytp-ad-skip-button-modern.ytp-button'
+ )
+ ) {
+ ImprovedTube.playerAds(node);
+ }
+ }
+ }).observe(node, {
+ childList: true, // attributes: true,
+ subtree: true,
+ });
+ }
- this.improvedtubeYoutubeIcon();
- }
- } else if (name === 'YTD-PLAYER') {
- if (!this.elements.ytd_player) {
- ImprovedTube.elements.ytd_player = node;
- }
- } else if (id === 'shorts-player') {
- if (!this.elements.shorts_player) {
- ImprovedTube.elements.shorts_player = node;
- }
- }else if (id === 'movie_player') {
- if (!this.elements.player) {
- ImprovedTube.elements.player = node;
- // if (this.storage.player_autoplay === false) { ImprovedTube.elements.player.stopVideo(); }
- ImprovedTube.elements.video = node.querySelector('video');
- ImprovedTube.elements.player_left_controls = node.querySelector('.ytp-left-controls');
- ImprovedTube.elements.player_right_controls = node.querySelector('.ytp-right-controls');
- ImprovedTube.elements.player_thumbnail = node.querySelector('.ytp-cued-thumbnail-overlay-image');
- ImprovedTube.elements.player_subtitles_button = node.querySelector('.ytp-subtitles-button');
- ImprovedTube.playerSize();
- if (typeof this.storage.ads !== 'undefined' && this.storage.ads !== "all_videos") {
- new MutationObserver(function (mutationList) {
- for (var i = 0, l = mutationList.length; i < l; i++) {
- var mutation = mutationList[i];
-
- if (mutation.type === 'childList') {
- for (var j = 0, k = mutation.addedNodes.length; j < k; j++) {
- var node = mutation.addedNodes[j];
-
- if (node instanceof Element
- && node.querySelector('ytp-ad-player-overlay, .ytp-ad-text, .ytp-ad-overlay-close-container, ytd-button-renderer#dismiss-button, *[id^="ad-text"], *[id^="skip-button"], .ytp-ad-skip-button.ytp-button, .ytp-ad-skip-button-modern.ytp-button') !== null) {
- ImprovedTube.playerAds(node);
- }
- }
- }
- if (mutation.type === 'attributes' && mutation.attributeName === 'id' && mutation.target.querySelector('*[id^="ad-text"], *[id^="skip-button"], .ytp-ad-skip-button-modern.ytp-button',)) {
- ImprovedTube.playerAds(node);
- }
- }
- }).observe(node, {childList: true, // attributes: true,
- subtree: true
- });
- }
+ new MutationObserver(function (mutationList) {
+ for (var i = 0, l = mutationList.length; i < l; i++) {
+ var mutation = mutationList[i];
- new MutationObserver(function (mutationList) {
- for (var i = 0, l = mutationList.length; i < l; i++) {
- var mutation = mutationList[i];
+ if (mutation.type === "attributes") {
+ if (mutation.attributeName === "style") {
+ ImprovedTube.playerHdThumbnail();
+ }
+ }
+ }
+ }).observe(ImprovedTube.elements.player_thumbnail, {
+ attributes: true,
+ attributeFilter: ["style"],
+ childList: false,
+ subtree: false,
+ });
+ }
+ } else if (name === "YTD-WATCH-FLEXY") {
+ this.elements.ytd_watch = node;
+
+ if (
+ this.isset(this.storage.player_size) &&
+ this.storage.player_size !== "do_not_change"
+ ) {
+ node.calculateCurrentPlayerSize_ = function () {
+ if (!this.theater && ImprovedTube.elements.player) {
+ if (this.updateStyles) {
+ this.updateStyles({
+ "--ytd-watch-flexy-width-ratio": 1,
+ "--ytd-watch-flexy-height-ratio": 0.5625,
+ });
- if (mutation.type === 'attributes') {
- if (mutation.attributeName === 'style') {
- ImprovedTube.playerHdThumbnail();
- }
- }
- }
- }).observe(ImprovedTube.elements.player_thumbnail, {attributes: true,
- attributeFilter: ['style'],
- childList: false,
- subtree: false
- });
- }
- } else if (name === 'YTD-WATCH-FLEXY') {
- this.elements.ytd_watch = node;
-
- if (
- this.isset(this.storage.player_size) &&
- this.storage.player_size !== 'do_not_change'
- ) {
- node.calculateCurrentPlayerSize_ = function () {
- if (!this.theater && ImprovedTube.elements.player) {
- if (this.updateStyles) {
- this.updateStyles({'--ytd-watch-flexy-width-ratio': 1,
- '--ytd-watch-flexy-height-ratio': 0.5625
- });
-
- this.updateStyles({'--ytd-watch-width-ratio': 1,
- '--ytd-watch-height-ratio': 0.5625
- });
- }
-
- return {width: ImprovedTube.elements.player.offsetWidth,
- height: Math.round(ImprovedTube.elements.player.offsetWidth / (16 / 9))
- };
- }
+ this.updateStyles({
+ "--ytd-watch-width-ratio": 1,
+ "--ytd-watch-height-ratio": 0.5625,
+ });
+ }
+
+ return {
+ width: ImprovedTube.elements.player.offsetWidth,
+ height: Math.round(
+ ImprovedTube.elements.player.offsetWidth / (16 / 9)
+ ),
+ };
+ }
- return {width: NaN, // ??
- height: NaN
- };
- };
+ return {
+ width: NaN, // ??
+ height: NaN,
+ };
+ };
- node.calculateNormalPlayerSize_ = node.calculateCurrentPlayerSize_; // ??
- }
- } else if (document.documentElement.dataset.pageType === 'video') {
- if (id === 'description-inline-expander' || id === 'description-inner') {
- setTimeout(function () {ImprovedTube.expandDescription(node);}, 300);
- } else if (id === 'meta') {setTimeout(function () {ImprovedTube.expandDescription(node.querySelector('#more'));}, 200);
- // } else if (id === 'below') { setTimeout(function () {}, 0);
- } else if (id === 'panels') { setTimeout(function () { ImprovedTube.transcript(node); ImprovedTube.chapters(node);ImprovedTube.elements.panels = node;}, 200);
- } /* else if (name === 'TP-YT-PAPER-BUTTON') {
+ node.calculateNormalPlayerSize_ = node.calculateCurrentPlayerSize_; // ??
+ }
+ } else if (document.documentElement.dataset.pageType === "video") {
+ if (id === "description-inline-expander" || id === "description-inner") {
+ setTimeout(function () {
+ ImprovedTube.expandDescription(node);
+ }, 300);
+ } else if (id === "meta") {
+ setTimeout(function () {
+ ImprovedTube.expandDescription(node.querySelector("#more"));
+ }, 200);
+ // } else if (id === 'below') { setTimeout(function () {}, 0);
+ } else if (id === "panels") {
+ setTimeout(function () {
+ ImprovedTube.transcript(node);
+ ImprovedTube.chapters(node);
+ ImprovedTube.elements.panels = node;
+ }, 200);
+ } /* else if (name === 'TP-YT-PAPER-BUTTON') {
if ( (id === 'expand-sizer' || id === 'expand') && node.parentNode.id === 'description-inline-expander') {
setTimeout(function () {
ImprovedTube.expandDescription(node); console.log("EXPAND DESCRIPTION, OLD WAY")
}, 750);
}} */
- } else if (id === 'panels') {
- ImprovedTube.elements.panels = node;
- }
+ } else if (id === "panels") {
+ ImprovedTube.elements.panels = node;
+ }
};
ImprovedTube.pageType = function () {
- if (/\/watch\?|\/live\//.test(location.href)) {
- document.documentElement.dataset.pageType = 'video';
- } else if (location.pathname === '/') {
- document.documentElement.dataset.pageType = 'home';
- } else if (/\/subscriptions\?/.test(location.href)) {
- document.documentElement.dataset.pageType = 'subscriptions';
- } else if (/\/@|(\/(channel|user|c)\/)[^/]+(?!\/videos)/.test(location.href)) {
- document.documentElement.dataset.pageType = 'channel';
- } else if (/\/shorts\//.test(location.href)) {
- document.documentElement.dataset.pageType = 'shorts';
- } else {
- document.documentElement.dataset.pageType = 'other';
- }
+ if (/\/watch\?|\/live\//.test(location.href)) {
+ document.documentElement.dataset.pageType = "video";
+ } else if (location.pathname === "/") {
+ document.documentElement.dataset.pageType = "home";
+ } else if (/\/subscriptions\?/.test(location.href)) {
+ document.documentElement.dataset.pageType = "subscriptions";
+ } else if (
+ /\/@|(\/(channel|user|c)\/)[^/]+(?!\/videos)/.test(location.href)
+ ) {
+ document.documentElement.dataset.pageType = "channel";
+ } else if (/\/shorts\//.test(location.href)) {
+ document.documentElement.dataset.pageType = "shorts";
+ } else {
+ document.documentElement.dataset.pageType = "other";
+ }
};
ImprovedTube.pageOnFocus = function () {
- ImprovedTube.playerAutopauseWhenSwitchingTabs();
- ImprovedTube.playerAutoPip();
- ImprovedTube.playerQualityWithoutFocus();
+ ImprovedTube.playerAutopauseWhenSwitchingTabs();
+ ImprovedTube.playerAutoPip();
+ ImprovedTube.playerQualityWithoutFocus();
+};
+ImprovedTube.stop_shorts_autoloop = function () {
+ if (document.documentElement.dataset.pageType === "shorts") {
+ const video = ImprovedTube.elements.shorts_player.querySelector("video");
+ video.removeAttribute("loop");
+ const observer = new MutationObserver((mutations) => {
+ mutations.forEach((mutation) => {
+ if (
+ mutation.type === "attributes" &&
+ mutation.attributeName === "loop"
+ ) {
+ video.removeAttribute("loop");
+ }
+ });
+ });
+ observer.observe(video, { attributes: true });
+ }
};
-ImprovedTube.stop_shorts_autoloop =function(){
- if(document.documentElement.dataset.pageType === 'shorts'){
- const video = ImprovedTube.elements.shorts_player.querySelector('video')
- video.removeAttribute('loop');
- const observer = new MutationObserver((mutations) => {
- mutations.forEach((mutation) => {
- if (mutation.type === 'attributes' && mutation.attributeName === 'loop') {
- video.removeAttribute('loop');
- }
- });
- });
- observer.observe(video, { attributes: true });
- }
-}
ImprovedTube.videoPageUpdate = function () {
- if (document.documentElement.dataset.pageType === 'video') {
- var video_id = this.getParam(new URL(location.href).search.substr(1), 'v');
-
- if (this.storage.track_watched_videos === true && video_id) {
- ImprovedTube.messages.send({action: 'watched',
- type: 'add',
- id: video_id,
- title: document.title
- });
- }
+ if (document.documentElement.dataset.pageType === "video") {
+ var video_id = this.getParam(new URL(location.href).search.substr(1), "v");
+
+ if (this.storage.track_watched_videos === true && video_id) {
+ ImprovedTube.messages.send({
+ action: "watched",
+ type: "add",
+ id: video_id,
+ title: document.title,
+ });
+ }
- this.initialVideoUpdateDone = true;
-
- ImprovedTube.howLongAgoTheVideoWasUploaded();
- ImprovedTube.dayOfWeek();
- ImprovedTube.exactUploadDate();
- ImprovedTube.channelVideosCount();
- ImprovedTube.upNextAutoplay();
- ImprovedTube.playerAutofullscreen();
- ImprovedTube.playerSize();
- if (this.storage.player_always_repeat === true) { ImprovedTube.playerRepeat(); };
- ImprovedTube.playerScreenshotButton();
- ImprovedTube.playerRepeatButton();
- ImprovedTube.playerRotateButton();
- ImprovedTube.playerPopupButton();
- ImprovedTube.playerFitToWinButton();
- ImprovedTube.playerRewindAndForwardButtons()
- ImprovedTube.playerCinemaModeButton();
- ImprovedTube.playerHamburgerButton();
- ImprovedTube.playerControls();
- }
+ this.initialVideoUpdateDone = true;
+
+ ImprovedTube.howLongAgoTheVideoWasUploaded();
+ ImprovedTube.dayOfWeek();
+ ImprovedTube.exactUploadDate();
+ ImprovedTube.channelVideosCount();
+ ImprovedTube.upNextAutoplay();
+ ImprovedTube.playerAutofullscreen();
+ ImprovedTube.playerSize();
+ if (this.storage.player_always_repeat === true) {
+ ImprovedTube.playerRepeat();
+ }
+ ImprovedTube.playerScreenshotButton();
+ ImprovedTube.playerRepeatButton();
+ ImprovedTube.playerRotateButton();
+ ImprovedTube.playerPopupButton();
+ ImprovedTube.playerFitToWinButton();
+ ImprovedTube.playerRewindAndForwardButtons();
+ ImprovedTube.playerCinemaModeButton();
+ ImprovedTube.playerHamburgerButton();
+ ImprovedTube.playerControls();
+ }
};
ImprovedTube.playerOnPlay = function () {
- HTMLMediaElement.prototype.play = (function (original) {
- return function () {
- if (!this.closest('#inline-preview-player')) {
- this.removeEventListener('loadedmetadata', ImprovedTube.playerOnLoadedMetadata);
- this.addEventListener('loadedmetadata', ImprovedTube.playerOnLoadedMetadata);
-
- this.removeEventListener('timeupdate', ImprovedTube.playerOnTimeUpdate);
- this.addEventListener('timeupdate', ImprovedTube.playerOnTimeUpdate);
-
- this.removeEventListener('pause', ImprovedTube.playerOnPause, true);
- this.addEventListener('pause', ImprovedTube.playerOnPause, true);
- this.onpause = () => {
- console.log('this.onpause');
- };
-
- this.removeEventListener('ended', ImprovedTube.playerOnEnded, true);
- this.addEventListener('ended', ImprovedTube.playerOnEnded, true);
- ImprovedTube.autoplayDisable(this);
- ImprovedTube.playerLoudnessNormalization();
- ImprovedTube.playerCinemaModeEnable();
- }
- return original.apply(this, arguments);
- }
- })(HTMLMediaElement.prototype.play);
+ HTMLMediaElement.prototype.play = (function (original) {
+ return function () {
+ if (!this.closest("#inline-preview-player")) {
+ this.removeEventListener(
+ "loadedmetadata",
+ ImprovedTube.playerOnLoadedMetadata
+ );
+ this.addEventListener(
+ "loadedmetadata",
+ ImprovedTube.playerOnLoadedMetadata
+ );
+
+ this.removeEventListener("timeupdate", ImprovedTube.playerOnTimeUpdate);
+ this.addEventListener("timeupdate", ImprovedTube.playerOnTimeUpdate);
+
+ this.removeEventListener("pause", ImprovedTube.playerOnPause, true);
+ this.addEventListener("pause", ImprovedTube.playerOnPause, true);
+ this.onpause = () => {
+ console.log("this.onpause");
+ };
+
+ this.removeEventListener("ended", ImprovedTube.playerOnEnded, true);
+ this.addEventListener("ended", ImprovedTube.playerOnEnded, true);
+ ImprovedTube.autoplayDisable(this);
+ ImprovedTube.playerLoudnessNormalization();
+ ImprovedTube.playerCinemaModeEnable();
+ }
+ return original.apply(this, arguments);
+ };
+ })(HTMLMediaElement.prototype.play);
};
ImprovedTube.initPlayer = function () {
- if (ImprovedTube.elements.player && ImprovedTube.video_url !== location.href) {
- ImprovedTube.video_url = location.href;
- ImprovedTube.user_interacted = false;
- ImprovedTube.played_before_blur = false;
-
- delete ImprovedTube.elements.player.dataset.defaultQuality;
-
- ImprovedTube.forcedPlayVideoFromTheBeginning();
- ImprovedTube.playerPlaybackSpeed();
- ImprovedTube.playerSubtitles();
- ImprovedTube.subtitlesLanguage();
- ImprovedTube.subtitlesUserSettings();
- ImprovedTube.subtitlesDisableLyrics();
- ImprovedTube.playerQuality();
- ImprovedTube.batteryFeatures();
- ImprovedTube.playerVolume();
- if (this.storage.player_always_repeat === true) { ImprovedTube.playerRepeat(); }
-
- ImprovedTube.playerScreenshotButton();
- ImprovedTube.playerRepeatButton();
- ImprovedTube.playerRotateButton();
- ImprovedTube.playerPopupButton();
- ImprovedTube.playerFitToWinButton();
- ImprovedTube.playerRewindAndForwardButtons()
- ImprovedTube.playerHamburgerButton();
- ImprovedTube.playerControls();
- ImprovedTube.playerHideProgressPreview();
- ImprovedTube.expandDescription();
- setTimeout(function () {ImprovedTube.forcedTheaterMode(); }, 150);
- if (location.href.indexOf('/embed/') === -1) { ImprovedTube.miniPlayer(); }
- if (ImprovedTube.storage.disable_auto_dubbing === true) { ImprovedTube.disableAutoDubbing(); }
- }
+ if (
+ ImprovedTube.elements.player &&
+ ImprovedTube.video_url !== location.href
+ ) {
+ ImprovedTube.video_url = location.href;
+ ImprovedTube.user_interacted = false;
+ ImprovedTube.played_before_blur = false;
+
+ delete ImprovedTube.elements.player.dataset.defaultQuality;
+
+ ImprovedTube.forcedPlayVideoFromTheBeginning();
+ ImprovedTube.playerPlaybackSpeed();
+ ImprovedTube.playerSubtitles();
+ ImprovedTube.subtitlesLanguage();
+ ImprovedTube.subtitlesUserSettings();
+ ImprovedTube.subtitlesDisableLyrics();
+ ImprovedTube.playerQuality();
+ ImprovedTube.batteryFeatures();
+ ImprovedTube.playerVolume();
+ if (this.storage.player_always_repeat === true) {
+ ImprovedTube.playerRepeat();
+ }
+
+ ImprovedTube.playerScreenshotButton();
+ ImprovedTube.playerRepeatButton();
+ ImprovedTube.playerRotateButton();
+ ImprovedTube.playerPopupButton();
+ ImprovedTube.playerFitToWinButton();
+ ImprovedTube.playerRewindAndForwardButtons();
+ ImprovedTube.playerHamburgerButton();
+ ImprovedTube.playerControls();
+ ImprovedTube.playerHideProgressPreview();
+ ImprovedTube.expandDescription();
+ setTimeout(function () {
+ ImprovedTube.forcedTheaterMode();
+ }, 150);
+ if (location.href.indexOf("/embed/") === -1) {
+ ImprovedTube.miniPlayer();
+ }
+ if (ImprovedTube.storage.disable_auto_dubbing === true) {
+ ImprovedTube.disableAutoDubbing();
+ }
+ }
};
var timeUpdateInterval = null;
var noTimeUpdate = null;
ImprovedTube.playerOnTimeUpdate = function () {
- if (!timeUpdateInterval) {
- timeUpdateInterval = setInterval(function () {
- if (ImprovedTube.video_src !== this.src) {
- ImprovedTube.video_src = this.src;
-
- if (ImprovedTube.initialVideoUpdateDone !== true) {
- ImprovedTube.playerQuality();
- ImprovedTube.playerVolume();
- ImprovedTube.playerPlaybackSpeed();
- }
- } else if (ImprovedTube.latestVideoDuration !== this.duration) {
- ImprovedTube.latestVideoDuration = this.duration;
-
- ImprovedTube.playerQuality();
- ImprovedTube.playerVolume();
- ImprovedTube.playerPlaybackSpeed();
- }
-
- if (ImprovedTube.storage.always_show_progress_bar === true) {ImprovedTube.showProgressBar();}
- if (ImprovedTube.storage.player_remaining_duration === true) {ImprovedTube.playerRemainingDuration();}
- ImprovedTube.played_time += .5;
-//Counting time of the player playing for the analyzer feature. (not equal to video time if playback speed isnt 1.00)
-//We can also allow to measure session times too and HID times.
- }, 500);
- }
- clearInterval(noTimeUpdate);
- noTimeUpdate = setTimeout(function () {
- clearInterval(timeUpdateInterval);
- timeUpdateInterval = null;
- }, 987);
+ if (!timeUpdateInterval) {
+ timeUpdateInterval = setInterval(function () {
+ if (ImprovedTube.video_src !== this.src) {
+ ImprovedTube.video_src = this.src;
+
+ if (ImprovedTube.initialVideoUpdateDone !== true) {
+ ImprovedTube.playerQuality();
+ ImprovedTube.playerVolume();
+ ImprovedTube.playerPlaybackSpeed();
+ }
+ } else if (ImprovedTube.latestVideoDuration !== this.duration) {
+ ImprovedTube.latestVideoDuration = this.duration;
+
+ ImprovedTube.playerQuality();
+ ImprovedTube.playerVolume();
+ ImprovedTube.playerPlaybackSpeed();
+ }
+
+ if (ImprovedTube.storage.always_show_progress_bar === true) {
+ ImprovedTube.showProgressBar();
+ }
+ if (ImprovedTube.storage.player_remaining_duration === true) {
+ ImprovedTube.playerRemainingDuration();
+ }
+ ImprovedTube.played_time += 0.5;
+ //Counting time of the player playing for the analyzer feature. (not equal to video time if playback speed isnt 1.00)
+ //We can also allow to measure session times too and HID times.
+ }, 500);
+ }
+ clearInterval(noTimeUpdate);
+ noTimeUpdate = setTimeout(function () {
+ clearInterval(timeUpdateInterval);
+ timeUpdateInterval = null;
+ }, 987);
};
ImprovedTube.playerOnLoadedMetadata = function () {
- setTimeout(function () {ImprovedTube.playerSize();}, 100);
- setTimeout(function () { if (ImprovedTube.elements.panels) { ImprovedTube.transcript(ImprovedTube.elements.panels); ImprovedTube.chapters(ImprovedTube.elements.panels);}}, 250);
+ setTimeout(function () {
+ ImprovedTube.playerSize();
+ }, 100);
+ setTimeout(function () {
+ if (ImprovedTube.elements.panels) {
+ ImprovedTube.transcript(ImprovedTube.elements.panels);
+ ImprovedTube.chapters(ImprovedTube.elements.panels);
+ }
+ }, 250);
};
ImprovedTube.playerOnPause = function (event) {
- ImprovedTube.playlistUpNextAutoplay(event);
-
- if (ImprovedTube.elements.yt_channel_name) {
- ImprovedTube.messages.send({action: 'analyzer',
- name: ImprovedTube.elements.yt_channel_name.__data.tooltipText,
- time: ImprovedTube.played_time
- });
- }
- ImprovedTube.played_time = 0;
- ImprovedTube.playerControls();
- ImprovedTube.playerCinemaModeDisable();
-
+ ImprovedTube.playlistUpNextAutoplay(event);
+
+ if (ImprovedTube.elements.yt_channel_name) {
+ ImprovedTube.messages.send({
+ action: "analyzer",
+ name: ImprovedTube.elements.yt_channel_name.__data.tooltipText,
+ time: ImprovedTube.played_time,
+ });
+ }
+ ImprovedTube.played_time = 0;
+ ImprovedTube.playerControls();
+ ImprovedTube.playerCinemaModeDisable();
};
// if ( document.documentElement.dataset.pageType === 'video'
-// && (ImprovedTube.storage.description === "expanded" || ImprovedTube.storage.transcript === true || ImprovedTube.storage.chapters === true )) {
+// && (ImprovedTube.storage.description === "expanded" || ImprovedTube.storage.transcript === true || ImprovedTube.storage.chapters === true )) {
// ImprovedTube.forbidFocus = function (ms)
/*--------------------------------------------------------------
# HIDE PROGRESS BAR PREVIEW
--------------------------------------------------------------*/
ImprovedTube.playerHideProgressPreview = function () {
- const shouldHide = this.storage.player_hide_progress_preview === true;
-
- if (shouldHide) {
- document.documentElement.setAttribute('it-hide-progress-preview', 'true');
-
- // Force refresh the player UI
- if (this.elements.player) {
- this.elements.player.dispatchEvent(new Event('mousemove'));
- // Also try to force hide any existing tooltips
- const tooltips = document.querySelectorAll('.ytp-tooltip, .ytp-preview, .ytp-tooltip-text-wrapper');
- tooltips.forEach(tooltip => {
- tooltip.style.display = 'none';
- tooltip.style.opacity = '0';
- tooltip.style.visibility = 'hidden';
- });
- }
- } else {
- document.documentElement.removeAttribute('it-hide-progress-preview');
+ const shouldHide = this.storage.player_hide_progress_preview === true;
+
+ if (shouldHide) {
+ document.documentElement.setAttribute("it-hide-progress-preview", "true");
+
+ // Force refresh the player UI
+ if (this.elements.player) {
+ this.elements.player.dispatchEvent(new Event("mousemove"));
+ // Also try to force hide any existing tooltips
+ const tooltips = document.querySelectorAll(
+ ".ytp-tooltip, .ytp-preview, .ytp-tooltip-text-wrapper"
+ );
+ tooltips.forEach((tooltip) => {
+ tooltip.style.display = "none";
+ tooltip.style.opacity = "0";
+ tooltip.style.visibility = "hidden";
+ });
}
+ } else {
+ document.documentElement.removeAttribute("it-hide-progress-preview");
+ }
};
ImprovedTube.playerOnEnded = function (event) {
- ImprovedTube.playlistUpNextAutoplay(event);
+ ImprovedTube.playlistUpNextAutoplay(event);
- ImprovedTube.messages.send({action: 'analyzer',
- //adding "?" (not a fix)
- name: ImprovedTube.elements.yt_channel_name?.__data.tooltipText,
- time: ImprovedTube.played_time
- });
+ ImprovedTube.messages.send({
+ action: "analyzer",
+ //adding "?" (not a fix)
+ name: ImprovedTube.elements.yt_channel_name?.__data.tooltipText,
+ time: ImprovedTube.played_time,
+ });
- ImprovedTube.played_time = 0;
+ ImprovedTube.played_time = 0;
};
// https://github.com/code-charity/youtube/pull/2431
ImprovedTube.onkeydown = function () {
- ImprovedTube.pauseWhileTypingOnYoutube()
- window.addEventListener('keydown', function () {
- ImprovedTube.user_interacted = true; // = event.key
- }, true);
+ ImprovedTube.pauseWhileTypingOnYoutube();
+ window.addEventListener(
+ "keydown",
+ function () {
+ ImprovedTube.user_interacted = true; // = event.key
+ },
+ true
+ );
};
ImprovedTube.onmousedown = function (event) {
- window.addEventListener('mousedown', function (event) {
- ImprovedTube.user_interacted = true; // = mousedown
- }, true);
+ window.addEventListener(
+ "mousedown",
+ function (event) {
+ ImprovedTube.user_interacted = true; // = mousedown
+ },
+ true
+ );
};
/*
@@ -518,216 +664,290 @@ ImprovedTube.onmousedown = function () {
*/
ImprovedTube.getParam = function (query, name) {
- var params = query.split('&'),
- param = false;
+ var params = query.split("&"),
+ param = false;
- for (var i = 0; i < params.length; i++) {
- params[i] = params[i].split('=');
+ for (var i = 0; i < params.length; i++) {
+ params[i] = params[i].split("=");
- if (params[i][0] == name) {
- param = params[i][1];
- }
- }
+ if (params[i][0] == name) {
+ param = params[i][1];
+ }
+ }
- if (param) {
- return param;
- } else {
- return false;
- }
+ if (param) {
+ return param;
+ } else {
+ return false;
+ }
};
ImprovedTube.getParams = function (query) {
- var params = query.split('&'),
- result = {};
+ var params = query.split("&"),
+ result = {};
- for (var i = 0, l = params.length; i < l; i++) {
- params[i] = params[i].split('=');
+ for (var i = 0, l = params.length; i < l; i++) {
+ params[i] = params[i].split("=");
- result[params[i][0]] = params[i][1];
- }
+ result[params[i][0]] = params[i][1];
+ }
- return result;
+ return result;
};
ImprovedTube.getCookieValueByName = function (name) {
- var match = document.cookie.match(new RegExp('([; ]' + name + '|^' + name + ')([^\\s;]*)', 'g'));
+ var match = document.cookie.match(
+ new RegExp("([; ]" + name + "|^" + name + ")([^\\s;]*)", "g")
+ );
- if (match) {
- var cookie = match[0];
+ if (match) {
+ var cookie = match[0];
- return cookie.replace(name + '=', '').replace(' ', '');
- } else return '';
+ return cookie.replace(name + "=", "").replace(" ", "");
+ } else return "";
};
ImprovedTube.getPrefCookieValueByName = function (name) {
- let prefs = this.getParams(this.getCookieValueByName('PREF'));
- return prefs[name];
+ let prefs = this.getParams(this.getCookieValueByName("PREF"));
+ return prefs[name];
};
// set PREF cookie name=value or delete name if value == null
ImprovedTube.setPrefCookieValueByName = function (name, value) {
- let originalPref = this.getCookieValueByName('PREF');
- let prefs = this.getParams(originalPref);
- let newPrefs = '';
- let ampersant = '';
-
- if (name == 'f6' && prefs[name] & 1) {
- // f6 holds other settings, possible values 80000 80001 400 401 1 none
- // make sure we remember 1 bit
- prefs[name] = value | 1;
- } else {
- prefs[name] = value;
- }
-
- for (let pref in prefs) {
- if (prefs[pref]) {
- newPrefs += ampersant + pref + '=' + prefs[pref];
- ampersant = '&';
- }
- }
- // only write cookie if its different from the old one
- if (originalPref != newPrefs) {
- this.setCookie('PREF', newPrefs);
- }
+ let originalPref = this.getCookieValueByName("PREF");
+ let prefs = this.getParams(originalPref);
+ let newPrefs = "";
+ let ampersant = "";
+
+ if (name == "f6" && prefs[name] & 1) {
+ // f6 holds other settings, possible values 80000 80001 400 401 1 none
+ // make sure we remember 1 bit
+ prefs[name] = value | 1;
+ } else {
+ prefs[name] = value;
+ }
+
+ for (let pref in prefs) {
+ if (prefs[pref]) {
+ newPrefs += ampersant + pref + "=" + prefs[pref];
+ ampersant = "&";
+ }
+ }
+ // only write cookie if its different from the old one
+ if (originalPref != newPrefs) {
+ this.setCookie("PREF", newPrefs);
+ }
};
ImprovedTube.setCookie = function (name, value) {
- var date = new Date();
+ var date = new Date();
- date.setTime(date.getTime() + 3.154e+10);
+ date.setTime(date.getTime() + 3.154e10);
- document.cookie = name + '=' + value + '; path=/; domain=.youtube.com; expires=' + date.toGMTString();
+ document.cookie =
+ name +
+ "=" +
+ value +
+ "; path=/; domain=.youtube.com; expires=" +
+ date.toGMTString();
};
ImprovedTube.createIconButton = function (options) {
- const button = options.href ? document.createElement('a') : document.createElement('button'),
- svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
- path = document.createElementNS('http://www.w3.org/2000/svg', 'path'),
- type = this.button_icons[options.type];
-
- for (const attr of type.svg) svg.setAttribute(attr[0], attr[1]);
- for (const attr of type.path) path.setAttribute(attr[0], attr[1]);
-
- svg.appendChild(path);
- button.appendChild(svg);
-
- if (options.className) button.className = options.className;
- if (options.id) button.id = options.id;
- if (options.text) button.appendChild(document.createTextNode(options.text));
- if (options.href) button.href = options.href;
- if (options.onclick) {
- if (!options.propagate) {
- //we fully own all click events landing on this button
- button.onclick = function (event) {
- event.preventDefault();
- event.stopPropagation();
- options.onclick.apply(this, arguments);
- }
- } else {
- button.onclick = options.onclick;
- }
- }
- return button;
+ const button = options.href
+ ? document.createElement("a")
+ : document.createElement("button"),
+ svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"),
+ path = document.createElementNS("http://www.w3.org/2000/svg", "path"),
+ type = this.button_icons[options.type];
+
+ for (const attr of type.svg) svg.setAttribute(attr[0], attr[1]);
+ for (const attr of type.path) path.setAttribute(attr[0], attr[1]);
+
+ svg.appendChild(path);
+ button.appendChild(svg);
+
+ if (options.className) button.className = options.className;
+ if (options.id) button.id = options.id;
+ if (options.text) button.appendChild(document.createTextNode(options.text));
+ if (options.href) button.href = options.href;
+ if (options.onclick) {
+ if (!options.propagate) {
+ //we fully own all click events landing on this button
+ button.onclick = function (event) {
+ event.preventDefault();
+ event.stopPropagation();
+ options.onclick.apply(this, arguments);
+ };
+ } else {
+ button.onclick = options.onclick;
+ }
+ }
+ return button;
};
ImprovedTube.createPlayerButton = function (options) {
- var controls = options.position == "right" ? this.elements.player_right_controls : this.elements.player_left_controls;
- if (controls) {
- var button = document.createElement('button');
+ var controls =
+ options.position == "right"
+ ? this.elements.player_right_controls
+ : this.elements.player_left_controls;
+ if (controls) {
+ var button = document.createElement("button");
- button.className = 'ytp-button it-player-button';
+ button.className = "ytp-button it-player-button";
- button.dataset.title = options.title;
+ button.dataset.title = options.title;
- button.addEventListener('mouseover', function () {
- var tooltip = document.createElement('div'),
- rect = this.getBoundingClientRect();
+ button.addEventListener("mouseover", function () {
+ var tooltip = document.createElement("div"),
+ rect = this.getBoundingClientRect();
- tooltip.className = 'it-player-button--tooltip';
+ tooltip.className = "it-player-button--tooltip";
- tooltip.style.left = rect.left + rect.width / 2 + 'px';
- tooltip.style.top = rect.top - 8 + 'px';
+ tooltip.style.left = rect.left + rect.width / 2 + "px";
+ tooltip.style.top = rect.top - 8 + "px";
- tooltip.textContent = this.dataset.title;
- if (this.storage && (this.storage.player_cinema_mode_button || this.storage.player_auto_hide_cinema_mode_when_paused || this.storage.player_auto_cinema_mode)) {
- tooltip.style.zIndex = 10001;} // needed for cinema mode
- function mouseleave () {
- tooltip.remove();
+ tooltip.textContent = this.dataset.title;
+ if (
+ this.storage &&
+ (this.storage.player_cinema_mode_button ||
+ this.storage.player_auto_hide_cinema_mode_when_paused ||
+ this.storage.player_auto_cinema_mode)
+ ) {
+ tooltip.style.zIndex = 10001;
+ } // needed for cinema mode
+ function mouseleave() {
+ tooltip.remove();
- this.removeEventListener('mouseleave', mouseleave);
- }
+ this.removeEventListener("mouseleave", mouseleave);
+ }
- this.addEventListener('mouseleave', mouseleave);
+ this.addEventListener("mouseleave", mouseleave);
- document.body.appendChild(tooltip);
- });
+ document.body.appendChild(tooltip);
+ });
- if (options.id) {
- if (this.elements.buttons[options.id]) {
- this.elements.buttons[options.id].remove();
- }
+ if (options.id) {
+ if (this.elements.buttons[options.id]) {
+ this.elements.buttons[options.id].remove();
+ }
- button.id = options.id;
+ button.id = options.id;
- this.elements.buttons[options.id] = button;
- }
+ this.elements.buttons[options.id] = button;
+ }
- if (options.child) {
- button.appendChild(options.child);
- }
+ if (options.child) {
+ button.appendChild(options.child);
+ }
- button.style.opacity = options.opacity || .5;
+ button.style.opacity = options.opacity || 0.5;
- if (options.onclick) {
- button.onclick = options.onclick;
- }
+ if (options.onclick) {
+ button.onclick = options.onclick;
+ }
- controls.insertBefore(button, controls.childNodes[3]);
- return button;
- }
+ controls.insertBefore(button, controls.childNodes[3]);
+ return button;
+ }
};
-ImprovedTube.empty = function (element) {for (var i = element.childNodes.length - 1; i > -1; i--) { element.childNodes[i].remove(); }};
-ImprovedTube.isset = function (variable) {return !(typeof variable === 'undefined' || variable === null || variable === 'null');};
+ImprovedTube.empty = function (element) {
+ for (var i = element.childNodes.length - 1; i > -1; i--) {
+ element.childNodes[i].remove();
+ }
+};
+ImprovedTube.isset = function (variable) {
+ return !(
+ typeof variable === "undefined" ||
+ variable === null ||
+ variable === "null"
+ );
+};
ImprovedTube.showStatus = function (value) {
- if (!this.elements.status) {
- this.elements.status = document.createElement('div');
+ if (!this.elements.status) {
+ this.elements.status = document.createElement("div");
- this.elements.status.id = 'it-status';
- }
+ this.elements.status.id = "it-status";
+ }
- if (typeof value === 'number') {
- value = value.toFixed(2);
- }
+ if (typeof value === "number") {
+ value = value.toFixed(2);
+ }
- this.elements.status.textContent = value;
+ this.elements.status.textContent = value;
- if (ImprovedTube.status_timer) {
- clearTimeout(ImprovedTube.status_timer);
- }
+ if (ImprovedTube.status_timer) {
+ clearTimeout(ImprovedTube.status_timer);
+ }
- ImprovedTube.status_timer = setTimeout(function () {ImprovedTube.elements.status.remove();}, 500);
+ ImprovedTube.status_timer = setTimeout(function () {
+ ImprovedTube.elements.status.remove();
+ }, 500);
- this.elements.player.appendChild(this.elements.status);
+ this.elements.player.appendChild(this.elements.status);
};
-ImprovedTube.videoId = (url = document.URL) => url.match(ImprovedTube.regex.video_id)?.[1] || new URL(url).searchParams.get('v') || movie_player?.getVideoData?.().video_id || (console.log('No VIDEO ID URL MATCH match: Regex & url are:', ImprovedTube.regex.video_id, url), undefined);
-ImprovedTube.videoTitle = function () {return document.title?.replace(/\s*-\s*YouTube$/, '') || movie_player.getVideoData().title || document.querySelector('#title > h1 > *')?.textContent};
+ImprovedTube.videoId = (url = document.URL) =>
+ url.match(ImprovedTube.regex.video_id)?.[1] ||
+ new URL(url).searchParams.get("v") ||
+ movie_player?.getVideoData?.().video_id ||
+ (console.log(
+ "No VIDEO ID URL MATCH match: Regex & url are:",
+ ImprovedTube.regex.video_id,
+ url
+ ),
+ undefined);
+ImprovedTube.videoTitle = function () {
+ return (
+ document.title?.replace(/\s*-\s*YouTube$/, "") ||
+ movie_player.getVideoData().title ||
+ document.querySelector("#title > h1 > *")?.textContent
+ );
+};
// Function to extract and store the number of subscribers
ImprovedTube.extractSubscriberCount = function (subscriberCountNode) {
- if (!subscriberCountNode) {subscriberCountNode = document.getElementById('owner-sub-count');}
- if (subscriberCountNode) {
- // Extract the subscriber count and store it for further use
- var subscriberCountText = subscriberCountNode.textContent.trim();
- var subscriberCount = parseFloat(subscriberCountText.replace(/[^0-9.]/g, ''));
-
- if (subscriberCountText.includes('K')) {
- subscriberCount *= 1000;
- } else if (subscriberCountText.includes('M')) {
- subscriberCount *= 1000000;
- }
+ if (!subscriberCountNode) {
+ subscriberCountNode = document.getElementById("owner-sub-count");
+ }
+ if (subscriberCountNode) {
+ // Extract the subscriber count and store it for further use
+ var subscriberCountText = subscriberCountNode.textContent.trim();
+ var subscriberCount = parseFloat(
+ subscriberCountText.replace(/[^0-9.]/g, "")
+ );
+
+ if (subscriberCountText.includes("K")) {
+ subscriberCount *= 1000;
+ } else if (subscriberCountText.includes("M")) {
+ subscriberCount *= 1000000;
+ }
- ImprovedTube.subscriberCount = subscriberCount;
- }
+ ImprovedTube.subscriberCount = subscriberCount;
+ }
};
+
+(function tryInitMuteAds(attempt = 0) {
+ if (
+ ImprovedTube.storage.ads === "mute_ads" &&
+ !ImprovedTube._mutedAdsObserverInitialized
+ ) {
+ const player = document.getElementById("movie_player");
+ const video = document.querySelector(".video-stream.html5-main-video");
+
+ if (player && video) {
+ ImprovedTube.elements.player = player;
+ ImprovedTube.elements.video = video;
+ ImprovedTube.muteAds();
+ return;
+ }
+
+ if (attempt < 20) {
+ setTimeout(() => tryInitMuteAds(attempt + 1), 300); // retry every 300ms
+ } else {
+ console.warn(
+ "[tryInitMuteAds] Gave up after 6 seconds — player not found"
+ );
+ }
+ }
+})();
diff --git a/js&css/web-accessible/www.youtube.com/player.js b/js&css/web-accessible/www.youtube.com/player.js
index 9ddfefb8e..d30a07f7e 100644
--- a/js&css/web-accessible/www.youtube.com/player.js
+++ b/js&css/web-accessible/www.youtube.com/player.js
@@ -2,248 +2,487 @@
AUTOPLAY DISABLE
------------------------------------------------------------------------------*/
ImprovedTube.autoplayDisable = function (videoElement) {
- if (this.storage.player_autoplay_disable
- || this.storage.playlist_autoplay === false
- || this.storage.channel_trailer_autoplay === false) {
- const player = this.elements.player || videoElement.closest('.html5-video-player') || videoElement.closest('#movie_player'); // #movie_player: outdated since 2024?
-
- if (this.video_url !== location.href) { this.user_interacted = false; }
-
- //if (there is a player) and (no user clicks) and (no ads playing)
- // and( ((auto play is off and it is not in a playlist)
- // or (playlist auto play is off and in a playlist))
- // or (we are in a channel and the channel trailer autoplay is off) )
-
- if (player && !this.user_interacted // (=user didnt click or type)
- && !player.classList.contains('ad-showing') // (=no ads playing, needs an update?)
- && ((location.href.includes('/watch?') // #1703 // (=video page)
- // player_autoplay_disable & not playlist
- && (this.storage.player_autoplay_disable && !location.href.includes('list='))
- // !playlist_autoplay & playlist
- || (this.storage.playlist_autoplay === false && location.href.includes('list=')))
- // channel homepage & !channel_trailer_autoplay
- || (this.storage.channel_trailer_autoplay === false && this.regex.channel.test(location.href)))) {
-
- setTimeout(function () {
- try { player.pauseVideo(); } catch (error) { console.log("autoplayDisable: Pausing"); videoElement.pause(); }
- });
- } else {
- document.dispatchEvent(new CustomEvent('it-play'));
- }
- } else {
- document.dispatchEvent(new CustomEvent('it-play'));
- }
+ if (
+ this.storage.player_autoplay_disable ||
+ this.storage.playlist_autoplay === false ||
+ this.storage.channel_trailer_autoplay === false
+ ) {
+ const player =
+ this.elements.player ||
+ videoElement.closest(".html5-video-player") ||
+ videoElement.closest("#movie_player"); // #movie_player: outdated since 2024?
+
+ if (this.video_url !== location.href) {
+ this.user_interacted = false;
+ }
+
+ //if (there is a player) and (no user clicks) and (no ads playing)
+ // and( ((auto play is off and it is not in a playlist)
+ // or (playlist auto play is off and in a playlist))
+ // or (we are in a channel and the channel trailer autoplay is off) )
+
+ if (
+ player &&
+ !this.user_interacted && // (=user didnt click or type)
+ !player.classList.contains("ad-showing") && // (=no ads playing, needs an update?)
+ ((location.href.includes("/watch?") && // #1703 // (=video page)
+ // player_autoplay_disable & not playlist
+ this.storage.player_autoplay_disable &&
+ !location.href.includes("list=")) ||
+ // !playlist_autoplay & playlist
+ (this.storage.playlist_autoplay === false &&
+ location.href.includes("list=")) ||
+ // channel homepage & !channel_trailer_autoplay
+ (this.storage.channel_trailer_autoplay === false &&
+ this.regex.channel.test(location.href)))
+ ) {
+ setTimeout(function () {
+ try {
+ player.pauseVideo();
+ } catch (error) {
+ console.log("autoplayDisable: Pausing");
+ videoElement.pause();
+ }
+ });
+ } else {
+ document.dispatchEvent(new CustomEvent("it-play"));
+ }
+ } else {
+ document.dispatchEvent(new CustomEvent("it-play"));
+ }
};
/*------------------------------------------------------------------------------
FORCED PLAY VIDEO FROM THE BEGINNING
------------------------------------------------------------------------------*/
ImprovedTube.forcedPlayVideoFromTheBeginning = function () {
- const player = this.elements.player,
- video = this.elements.video,
- paused = video?.paused;
-
- if (player && video && this.storage.forced_play_video_from_the_beginning && location.pathname == '/watch') {
- player.seekTo(0);
- // restore previous paused state
- if (paused) { player.pauseVideo(); }
- }
+ const player = this.elements.player,
+ video = this.elements.video,
+ paused = video?.paused;
+
+ if (
+ player &&
+ video &&
+ this.storage.forced_play_video_from_the_beginning &&
+ location.pathname == "/watch"
+ ) {
+ player.seekTo(0);
+ // restore previous paused state
+ if (paused) {
+ player.pauseVideo();
+ }
+ }
};
/*------------------------------------------------------------------------------
AUTOPAUSE WHEN SWITCHING TABS
------------------------------------------------------------------------------*/
ImprovedTube.playerAutopauseWhenSwitchingTabs = function () {
- const player = this.elements.player;
-
- if (this.storage.player_autopause_when_switching_tabs && player) {
- if (this.focus && this.played_before_blur && this.elements.video.paused) {
- player.playVideo();
- } else {
- this.played_before_blur = !this.elements.video.paused;
- if (!this.elements.video.paused) {
- player.pauseVideo();
- }
- }
- }
+ const player = this.elements.player;
+
+ if (this.storage.player_autopause_when_switching_tabs && player) {
+ if (this.focus && this.played_before_blur && this.elements.video.paused) {
+ player.playVideo();
+ } else {
+ this.played_before_blur = !this.elements.video.paused;
+ if (!this.elements.video.paused) {
+ player.pauseVideo();
+ }
+ }
+ }
};
/*------------------------------------------------------------------------------
PICTURE IN PICTURE (PIP)
------------------------------------------------------------------------------*/
ImprovedTube.enterPip = function (disable) {
- const video = this.elements.video;
-
- if (!disable
- && video
- && document.pictureInPictureEnabled
- && typeof video.requestPictureInPicture == 'function') {
-
- video.requestPictureInPicture().then(() => {
- if (video.paused) {
- // manually send Play message to "Auto-pause while I'm not in the tab", paused PiP wont do it automatically.
- document.dispatchEvent(new CustomEvent('it-play'));
- }
- return true;
- }).catch((err) => console.error('playerAutoPip: Failed to enter Picture-in-Picture mode', err));
- } else if (document.pictureInPictureElement && typeof document.exitPictureInPicture == 'function') {
- document.exitPictureInPicture();
- return false;
- }
+ const video = this.elements.video;
+
+ if (
+ !disable &&
+ video &&
+ document.pictureInPictureEnabled &&
+ typeof video.requestPictureInPicture == "function"
+ ) {
+ video
+ .requestPictureInPicture()
+ .then(() => {
+ if (video.paused) {
+ // manually send Play message to "Auto-pause while I'm not in the tab", paused PiP wont do it automatically.
+ document.dispatchEvent(new CustomEvent("it-play"));
+ }
+ return true;
+ })
+ .catch((err) =>
+ console.error(
+ "playerAutoPip: Failed to enter Picture-in-Picture mode",
+ err
+ )
+ );
+ } else if (
+ document.pictureInPictureElement &&
+ typeof document.exitPictureInPicture == "function"
+ ) {
+ document.exitPictureInPicture();
+ return false;
+ }
};
/*------------------------------------------------------------------------------
AUTO PIP WHEN SWITCHING TABS
------------------------------------------------------------------------------*/
ImprovedTube.playerAutoPip = function () {
- const video = this.elements.video;
-
- if (this.storage.player_autoPip && this.storage.player_autoPip_outside && this.focus) {
- this.enterPip(true);
- } else if (this.storage.player_autoPip && !this.focus && !video?.paused) {
- this.enterPip();
- }
+ const video = this.elements.video;
+
+ if (
+ this.storage.player_autoPip &&
+ this.storage.player_autoPip_outside &&
+ this.focus
+ ) {
+ this.enterPip(true);
+ } else if (this.storage.player_autoPip && !this.focus && !video?.paused) {
+ this.enterPip();
+ }
};
/*------------------------------------------------------------------------------
PLAYBACK SPEED
------------------------------------------------------------------------------*/
ImprovedTube.playbackSpeed = function (newSpeed) {
- const video = this.elements.video,
- player = this.elements.player,
- speed = video?.playbackRate ? Number(video.playbackRate.toFixed(2)) : (player?.getPlaybackRate ? Number(player.getPlaybackRate().toFixed(2)) : null);
-
- if (!speed) {
- console.error('PlaybackSpeed: Cant establish playbackRate/getPlaybackRate');
- return false;
- }
-
- // called with no option or demanded speed already set, only provide readback
- if (!newSpeed || speed == newSpeed) return speed;
-
- if (video?.playbackRate) {
- video.playbackRate = newSpeed;
- newSpeed = video.playbackRate;
- } else if (player?.setPlaybackRate && player.getPlaybackRate) {
- player.setPlaybackRate(newSpeed);
- newSpeed = player.getPlaybackRate();
- } else newSpeed = false;
-
- return newSpeed;
+ const video = this.elements.video,
+ player = this.elements.player,
+ speed = video?.playbackRate
+ ? Number(video.playbackRate.toFixed(2))
+ : player?.getPlaybackRate
+ ? Number(player.getPlaybackRate().toFixed(2))
+ : null;
+
+ if (!speed) {
+ console.error("PlaybackSpeed: Cant establish playbackRate/getPlaybackRate");
+ return false;
+ }
+
+ // called with no option or demanded speed already set, only provide readback
+ if (!newSpeed || speed == newSpeed) return speed;
+
+ if (video?.playbackRate) {
+ video.playbackRate = newSpeed;
+ newSpeed = video.playbackRate;
+ } else if (player?.setPlaybackRate && player.getPlaybackRate) {
+ player.setPlaybackRate(newSpeed);
+ newSpeed = player.getPlaybackRate();
+ } else newSpeed = false;
+
+ return newSpeed;
};
/*------------------------------------------------------------------------------
PERMANENT PLAYBACK SPEED
------------------------------------------------------------------------------*/
-ImprovedTube.playerPlaybackSpeed = function () { if (this.storage.player_forced_playback_speed === true) {
- var player = this.elements.player; if (!player) return;
- var video = this.elements.video || player.querySelector('video');
- option = this.storage.player_playback_speed;
- if (this.isset(option) === false) { option = 1; }
- else if ( option !== 1 ) {
- const speed = video?.playbackRate ? Number(video.playbackRate.toFixed(2)) : (player?.getPlaybackRate ? Number(player.getPlaybackRate().toFixed(2)) : null);
- if (speed !== option && speed !== 1 && speed !== Number((Math.floor(option / 0.05) * 0.05).toFixed(2)))
- { console.log("skipping permanent speed, since speed was manually set differently for this video to:" + video.playbackRate + ", was it?"); return; }
- }
- if (!(player.getVideoData() && player.getVideoData().isLive))
- { player.setPlaybackRate(Number(option)); if (!video) { video = { playbackRate: 1 }; }; video.playbackRate = Number(option); // #1729 q2 // hi! @raszpl
- if ( (this.storage.player_force_speed_on_music !== true || this.storage.player_dont_speed_education === true)
- && option !== 1) {
- ImprovedTube.speedException = function () {
- if (this.storage.player_dont_speed_education === true && DATA.genre === 'Education')
- {player.setPlaybackRate(Number(1)); video.playbackRate = Number(1); return;}
- if (this.storage.player_force_speed_on_music === true)
- { //player.setPlaybackRate(Number(option)); video.playbackRate = Number(option);
- return;}
- if (DATA.keywords && !keywords) { keywords = DATA.keywords.join(', ') || ''; }
- if (keywords === 'video, sharing, camera phone, video phone, free, upload') { keywords = ''; }
- var musicIdentifiers = /(official|music|lyrics?)[ -]video|(cover|studio|radio|album|alternate)[- ]version|soundtrack|unplugged|\bmedley\b|\blo-fi\b|\blofi\b|a(lla)? cappella|feat\.|(piano|guitar|jazz|ukulele|violin|reggae)[- ](version|cover)|karaok|backing[- ]track|instrumental|(sing|play)[- ]?along|卡拉OK|卡拉OK|الكاريوكي|караоке|カラオケ|노래방|bootleg|mashup|Radio edit|Guest (vocals|musician)|(title|opening|closing|bonus|hidden)[ -]track|live acoustic|interlude|featuring|recorded (at|live)/i;
- var musicIdentifiersTitleOnly = /lyrics|theme song|\bremix|\bAMV ?[^a-z0-9]|[^a-z0-9] ?AMV\b|\bfull song\b|\bsong:|\bsong[\!$]|^song\b|( - .*\bSong\b|\bSong\b.* - )|cover ?[^a-z0-9]|[^a-z0-9] ?cover|\bconcert\b/i;
- var musicIdentifiersTitle = new RegExp(musicIdentifiersTitleOnly.source + '|' + musicIdentifiers.source, "i");
- var musicRegexMatch = musicIdentifiersTitle.test(DATA.title);
- if (!musicRegexMatch) {
- var musicIdentifiersTagsOnly = /, (lyrics|remix|song|music|AMV|theme song|full song),|\(Musical Genre\)|, jazz|, reggae/i;
- var musicIdentifiersTags = new RegExp(musicIdentifiersTagsOnly.source + '|' + musicIdentifiers.source, "i");
- keywordsAmount = 1 + ((keywords || '').match(/,/) || []).length;
- if ( ((keywords || '').match(musicIdentifiersTags) || []).length / keywordsAmount > 0.08) {
- musicRegexMatch = true}}
- notMusicRegexMatch = /\bdo[ck]u|interv[iyj]|back[- ]?stage|インタビュー|entrevista|面试|面試|회견|wawancara|مقابلة|интервью|entretien|기록한 것|记录|記錄|ドキュメンタリ|وثائقي|документальный/i.test(DATA.title + " " + keywords);
- // (Tags/keywords shouldnt lie & very few songs titles might have these words)
- if (DATA.duration) {
- function parseDuration (duration) { const [_, h = 0, m = 0, s = 0] = duration.match(/PT(?:(\d+)?H)?(?:(\d+)?M)?(\d+)?S?/).map(part => parseInt(part) || 0);
- return h * 3600 + m * 60 + s; }
- DATA.lengthSeconds = parseDuration(DATA.duration); }
- function testSongDuration (s, ytMusic) {
- if (135 <= s && s <= 260) {return 'veryCommon';}
- if (105 <= s && s <= 420) {return 'common';}
- if (420 <= s && s <= 720) {return 'long';}
- if (45 <= s && s <= 105) {return 'short';}
- if (ytMusic && ytMusic > 1 && (85 <= s / ytMusic && (s / ytMusic <= 375 || ytMusic == 10))) {return 'multiple';}
- //does Youtube ever show more than 10 songs below the description?
- }
- var songDurationType = testSongDuration(DATA.lengthSeconds);
- console.log("genre: " + DATA.genre + "//title: " + DATA.title + "//keywords: " + keywords + "//music word match: " + musicRegexMatch + "// not music word match:" + notMusicRegexMatch + "//duration: " + DATA.lengthSeconds + "//song duration type: " + songDurationType);
- // check if the video is PROBABLY MUSIC:
- if ( ( DATA.genre === 'Music' && (!notMusicRegexMatch || songDurationType === 'veryCommon'))
- || ( musicRegexMatch && !notMusicRegexMatch && (typeof songDurationType !== 'undefined'
- || (/album|Álbum|专辑|專輯|एलबम|البوم|アルバム|альбом|앨범|mixtape|concert|playlist|\b(live|cd|vinyl|lp|ep|compilation|collection|symphony|suite|medley)\b/i.test(DATA.title + " " + keywords)
- && 1000 <= DATA.lengthSeconds )) ) // && 1150 <= DATA.lengthSeconds <= 5000
- || ( DATA.genre === 'Music' && musicRegexMatch && (typeof songDurationType !== 'undefined'
- || (/album|Álbum|专辑|專輯|एलबम|البوم|アルバム|альбом|앨범|mixtape|concert|playlist|\b(live|cd|vinyl|lp|ep|compilation|collection|symphony|suite|medley)\b/i.test(DATA.title + " " + keywords)
- && 1000 <= DATA.lengthSeconds )) ) // && DATA.lengthSeconds <= 5000
- || (amountOfSongs && testSongDuration(DATA.lengthSeconds, amountOfSongs ) !== 'undefined')
- // || location.href.indexOf('music.') !== -1 // (=currently we are only running on www.youtube.com anyways)
- ) { player.setPlaybackRate(1); video.playbackRate = 1; console.log ("...,thus must be music?"); }
- else { // Now this video might rarely be music
- // - however we can make extra-sure after waiting for the video descripion to load... (#1539)
- var tries = 0; var intervalMs = 210; if (location.href.indexOf('/watch?') !== -1) {var maxTries = 10;} else {var maxTries = 0;}
- // ...except when it is an embedded player?
- var waitForDescription = setInterval(() => {
- if (++tries >= maxTries) {
- subtitle = document.querySelector('#title + #subtitle:last-of-type')
- if ( subtitle && 1 <= Number((subtitle?.innerHTML?.match(/^\d+/) || [])[0]) // indicates buyable/registered music (amount of songs)
- && typeof testSongDuration(DATA.lengthSeconds, Number((subtitle?.innerHTML?.match(/^\d+/) || [])[0]) ) !== 'undefined' ) // resonable duration
- {player.setPlaybackRate(1); video.playbackRate = 1; console.log("...but YouTube shows music below the description!"); clearInterval(waitForDescription); }
- intervalMs *= 1.11; }}, intervalMs);
- window.addEventListener('load', () => { setTimeout(() => { clearInterval(waitForDescription); }, 1234); });
- }
- }
- //DATA (TO-DO: make the Data available to more/all features? #1452 #1763 (Then can replace ImprovedTube.elements.category === 'music', VideoID is also used elsewhere)
- DATA = {};
- defaultKeywords = "video,sharing,camera,phone,video phone,free,upload";
- keywords = false; amountOfSongs = false;
-
- ImprovedTube.fetchDOMData = function () {
- try { DATA = JSON.parse(document.querySelector('#microformat script')?.textContent) ?? false; DATA.title = DATA.name;}
- catch { DATA.genre = false; DATA.keywords = false; DATA.lengthSeconds = false;
- try {
- DATA.title = document.getElementsByTagName('meta')?.title?.content || false;
- DATA.genre = document.querySelector('meta[itemprop=genre]')?.content || false;
- DATA.duration = document.querySelector('meta[itemprop=duration]')?.content || false;
- } catch {}}
-
-let tries = 0; const maxTries = 11; let intervalMs = 200;
-const waitForVideoTitle = setInterval(() => { const title = ImprovedTube.videoTitle?.(); tries++;
-
-if (title && title !== 'YouTube') {
- clearInterval(waitForVideoTitle);
- DATA.videoID = ImprovedTube.videoId() || false; // console.log("SPEED: TITLE:" + ImprovedTube.videoTitle() + DATA.title);
- if ( DATA.title === ImprovedTube.videoTitle() || DATA.title.replace(/\s{2,}/g, ' ') === ImprovedTube.videoTitle() )
- { keywords = document.querySelector('meta[name="keywords"]')?.content || ''; ImprovedTube.speedException(); }
- else { keywords = ''; (async function () { try { const response = await fetch(`https://www.youtube.com/watch?v=${DATA.videoID}`);
- console.log("loading the html source:" + `https://www.youtube.com/watch?v=${DATA.videoID}`);
- const htmlContent = await response.text();
- const metaRegex = /]+(name|itemprop)=["'](keywords|genre|duration)["'][^>]+content=["']([^"']+)["'][^>]*>/gi;
- let match; while ((match = metaRegex.exec(htmlContent)) !== null) { // console.log(match);
- const [, property, value] = match;
- if (property === 'keywords') { keywords = value;} else {DATA[property] = value;}
- }
- amountOfSongs = (htmlContent.slice(-80000).match(/},"subtitle":{"simpleText":"(\d*)\s/) || [])[1] || false;
- if (keywords) { ImprovedTube.speedException(); }
- } catch (error) { console.error('Error: fetching from https://Youtube.com/watch?v=${DATA.videoID}', error); keywords = ''; }
- })();
- }
-}
-
-if (tries >= maxTries) { clearInterval(waitForVideoTitle); } intervalMs *= 1.11; }, intervalMs);
-window.addEventListener('load', () => { setTimeout(() => { clearInterval(waitForVideoTitle) }, 5000);});
- };
- ImprovedTube.fetchDOMData();
-/*
+ImprovedTube.playerPlaybackSpeed = function () {
+ if (this.storage.player_forced_playback_speed === true) {
+ var player = this.elements.player;
+ if (!player) return;
+ var video = this.elements.video || player.querySelector("video");
+ option = this.storage.player_playback_speed;
+ if (this.isset(option) === false) {
+ option = 1;
+ } else if (option !== 1) {
+ const speed = video?.playbackRate
+ ? Number(video.playbackRate.toFixed(2))
+ : player?.getPlaybackRate
+ ? Number(player.getPlaybackRate().toFixed(2))
+ : null;
+ if (
+ speed !== option &&
+ speed !== 1 &&
+ speed !== Number((Math.floor(option / 0.05) * 0.05).toFixed(2))
+ ) {
+ console.log(
+ "skipping permanent speed, since speed was manually set differently for this video to:" +
+ video.playbackRate +
+ ", was it?"
+ );
+ return;
+ }
+ }
+ if (!(player.getVideoData() && player.getVideoData().isLive)) {
+ player.setPlaybackRate(Number(option));
+ if (!video) {
+ video = { playbackRate: 1 };
+ }
+ video.playbackRate = Number(option); // #1729 q2 // hi! @raszpl
+ if (
+ (this.storage.player_force_speed_on_music !== true ||
+ this.storage.player_dont_speed_education === true) &&
+ option !== 1
+ ) {
+ ImprovedTube.speedException = function () {
+ if (
+ this.storage.player_dont_speed_education === true &&
+ DATA.genre === "Education"
+ ) {
+ player.setPlaybackRate(Number(1));
+ video.playbackRate = Number(1);
+ return;
+ }
+ if (this.storage.player_force_speed_on_music === true) {
+ //player.setPlaybackRate(Number(option)); video.playbackRate = Number(option);
+ return;
+ }
+ if (DATA.keywords && !keywords) {
+ keywords = DATA.keywords.join(", ") || "";
+ }
+ if (
+ keywords ===
+ "video, sharing, camera phone, video phone, free, upload"
+ ) {
+ keywords = "";
+ }
+ var musicIdentifiers =
+ /(official|music|lyrics?)[ -]video|(cover|studio|radio|album|alternate)[- ]version|soundtrack|unplugged|\bmedley\b|\blo-fi\b|\blofi\b|a(lla)? cappella|feat\.|(piano|guitar|jazz|ukulele|violin|reggae)[- ](version|cover)|karaok|backing[- ]track|instrumental|(sing|play)[- ]?along|卡拉OK|卡拉OK|الكاريوكي|караоке|カラオケ|노래방|bootleg|mashup|Radio edit|Guest (vocals|musician)|(title|opening|closing|bonus|hidden)[ -]track|live acoustic|interlude|featuring|recorded (at|live)/i;
+ var musicIdentifiersTitleOnly =
+ /lyrics|theme song|\bremix|\bAMV ?[^a-z0-9]|[^a-z0-9] ?AMV\b|\bfull song\b|\bsong:|\bsong[\!$]|^song\b|( - .*\bSong\b|\bSong\b.* - )|cover ?[^a-z0-9]|[^a-z0-9] ?cover|\bconcert\b/i;
+ var musicIdentifiersTitle = new RegExp(
+ musicIdentifiersTitleOnly.source + "|" + musicIdentifiers.source,
+ "i"
+ );
+ var musicRegexMatch = musicIdentifiersTitle.test(DATA.title);
+ if (!musicRegexMatch) {
+ var musicIdentifiersTagsOnly =
+ /, (lyrics|remix|song|music|AMV|theme song|full song),|\(Musical Genre\)|, jazz|, reggae/i;
+ var musicIdentifiersTags = new RegExp(
+ musicIdentifiersTagsOnly.source + "|" + musicIdentifiers.source,
+ "i"
+ );
+ keywordsAmount = 1 + ((keywords || "").match(/,/) || []).length;
+ if (
+ ((keywords || "").match(musicIdentifiersTags) || []).length /
+ keywordsAmount >
+ 0.08
+ ) {
+ musicRegexMatch = true;
+ }
+ }
+ notMusicRegexMatch =
+ /\bdo[ck]u|interv[iyj]|back[- ]?stage|インタビュー|entrevista|面试|面試|회견|wawancara|مقابلة|интервью|entretien|기록한 것|记录|記錄|ドキュメンタリ|وثائقي|документальный/i.test(
+ DATA.title + " " + keywords
+ );
+ // (Tags/keywords shouldnt lie & very few songs titles might have these words)
+ if (DATA.duration) {
+ function parseDuration(duration) {
+ const [_, h = 0, m = 0, s = 0] = duration
+ .match(/PT(?:(\d+)?H)?(?:(\d+)?M)?(\d+)?S?/)
+ .map((part) => parseInt(part) || 0);
+ return h * 3600 + m * 60 + s;
+ }
+ DATA.lengthSeconds = parseDuration(DATA.duration);
+ }
+ function testSongDuration(s, ytMusic) {
+ if (135 <= s && s <= 260) {
+ return "veryCommon";
+ }
+ if (105 <= s && s <= 420) {
+ return "common";
+ }
+ if (420 <= s && s <= 720) {
+ return "long";
+ }
+ if (45 <= s && s <= 105) {
+ return "short";
+ }
+ if (
+ ytMusic &&
+ ytMusic > 1 &&
+ 85 <= s / ytMusic &&
+ (s / ytMusic <= 375 || ytMusic == 10)
+ ) {
+ return "multiple";
+ }
+ //does Youtube ever show more than 10 songs below the description?
+ }
+ var songDurationType = testSongDuration(DATA.lengthSeconds);
+ console.log(
+ "genre: " +
+ DATA.genre +
+ "//title: " +
+ DATA.title +
+ "//keywords: " +
+ keywords +
+ "//music word match: " +
+ musicRegexMatch +
+ "// not music word match:" +
+ notMusicRegexMatch +
+ "//duration: " +
+ DATA.lengthSeconds +
+ "//song duration type: " +
+ songDurationType
+ );
+ // check if the video is PROBABLY MUSIC:
+ if (
+ (DATA.genre === "Music" &&
+ (!notMusicRegexMatch || songDurationType === "veryCommon")) ||
+ (musicRegexMatch &&
+ !notMusicRegexMatch &&
+ (typeof songDurationType !== "undefined" ||
+ (/album|Álbum|专辑|專輯|एलबम|البوم|アルバム|альбом|앨범|mixtape|concert|playlist|\b(live|cd|vinyl|lp|ep|compilation|collection|symphony|suite|medley)\b/i.test(
+ DATA.title + " " + keywords
+ ) &&
+ 1000 <= DATA.lengthSeconds))) || // && 1150 <= DATA.lengthSeconds <= 5000
+ (DATA.genre === "Music" &&
+ musicRegexMatch &&
+ (typeof songDurationType !== "undefined" ||
+ (/album|Álbum|专辑|專輯|एलबम|البوم|アルバム|альбом|앨범|mixtape|concert|playlist|\b(live|cd|vinyl|lp|ep|compilation|collection|symphony|suite|medley)\b/i.test(
+ DATA.title + " " + keywords
+ ) &&
+ 1000 <= DATA.lengthSeconds))) || // && DATA.lengthSeconds <= 5000
+ (amountOfSongs &&
+ testSongDuration(DATA.lengthSeconds, amountOfSongs) !==
+ "undefined")
+ // || location.href.indexOf('music.') !== -1 // (=currently we are only running on www.youtube.com anyways)
+ ) {
+ player.setPlaybackRate(1);
+ video.playbackRate = 1;
+ console.log("...,thus must be music?");
+ } else {
+ // Now this video might rarely be music
+ // - however we can make extra-sure after waiting for the video descripion to load... (#1539)
+ var tries = 0;
+ var intervalMs = 210;
+ if (location.href.indexOf("/watch?") !== -1) {
+ var maxTries = 10;
+ } else {
+ var maxTries = 0;
+ }
+ // ...except when it is an embedded player?
+ var waitForDescription = setInterval(() => {
+ if (++tries >= maxTries) {
+ subtitle = document.querySelector(
+ "#title + #subtitle:last-of-type"
+ );
+ if (
+ subtitle &&
+ 1 <= Number((subtitle?.innerHTML?.match(/^\d+/) || [])[0]) && // indicates buyable/registered music (amount of songs)
+ typeof testSongDuration(
+ DATA.lengthSeconds,
+ Number((subtitle?.innerHTML?.match(/^\d+/) || [])[0])
+ ) !== "undefined"
+ ) {
+ // resonable duration
+ player.setPlaybackRate(1);
+ video.playbackRate = 1;
+ console.log(
+ "...but YouTube shows music below the description!"
+ );
+ clearInterval(waitForDescription);
+ }
+ intervalMs *= 1.11;
+ }
+ }, intervalMs);
+ window.addEventListener("load", () => {
+ setTimeout(() => {
+ clearInterval(waitForDescription);
+ }, 1234);
+ });
+ }
+ };
+ //DATA (TO-DO: make the Data available to more/all features? #1452 #1763 (Then can replace ImprovedTube.elements.category === 'music', VideoID is also used elsewhere)
+ DATA = {};
+ defaultKeywords = "video,sharing,camera,phone,video phone,free,upload";
+ keywords = false;
+ amountOfSongs = false;
+
+ ImprovedTube.fetchDOMData = function () {
+ try {
+ DATA =
+ JSON.parse(
+ document.querySelector("#microformat script")?.textContent
+ ) ?? false;
+ DATA.title = DATA.name;
+ } catch {
+ DATA.genre = false;
+ DATA.keywords = false;
+ DATA.lengthSeconds = false;
+ try {
+ DATA.title =
+ document.getElementsByTagName("meta")?.title?.content || false;
+ DATA.genre =
+ document.querySelector("meta[itemprop=genre]")?.content ||
+ false;
+ DATA.duration =
+ document.querySelector("meta[itemprop=duration]")?.content ||
+ false;
+ } catch {}
+ }
+
+ let tries = 0;
+ const maxTries = 11;
+ let intervalMs = 200;
+ const waitForVideoTitle = setInterval(() => {
+ const title = ImprovedTube.videoTitle?.();
+ tries++;
+
+ if (title && title !== "YouTube") {
+ clearInterval(waitForVideoTitle);
+ DATA.videoID = ImprovedTube.videoId() || false; // console.log("SPEED: TITLE:" + ImprovedTube.videoTitle() + DATA.title);
+ if (
+ DATA.title === ImprovedTube.videoTitle() ||
+ DATA.title.replace(/\s{2,}/g, " ") === ImprovedTube.videoTitle()
+ ) {
+ keywords =
+ document.querySelector('meta[name="keywords"]')?.content ||
+ "";
+ ImprovedTube.speedException();
+ } else {
+ keywords = "";
+ (async function () {
+ try {
+ const response = await fetch(
+ `https://www.youtube.com/watch?v=${DATA.videoID}`
+ );
+ console.log(
+ "loading the html source:" +
+ `https://www.youtube.com/watch?v=${DATA.videoID}`
+ );
+ const htmlContent = await response.text();
+ const metaRegex =
+ /]+(name|itemprop)=["'](keywords|genre|duration)["'][^>]+content=["']([^"']+)["'][^>]*>/gi;
+ let match;
+ while ((match = metaRegex.exec(htmlContent)) !== null) {
+ // console.log(match);
+ const [, property, value] = match;
+ if (property === "keywords") {
+ keywords = value;
+ } else {
+ DATA[property] = value;
+ }
+ }
+ amountOfSongs =
+ (htmlContent
+ .slice(-80000)
+ .match(/},"subtitle":{"simpleText":"(\d*)\s/) ||
+ [])[1] || false;
+ if (keywords) {
+ ImprovedTube.speedException();
+ }
+ } catch (error) {
+ console.error(
+ "Error: fetching from https://Youtube.com/watch?v=${DATA.videoID}",
+ error
+ );
+ keywords = "";
+ }
+ })();
+ }
+ }
+
+ if (tries >= maxTries) {
+ clearInterval(waitForVideoTitle);
+ }
+ intervalMs *= 1.11;
+ }, intervalMs);
+ window.addEventListener("load", () => {
+ setTimeout(() => {
+ clearInterval(waitForVideoTitle);
+ }, 5000);
+ });
+ };
+ ImprovedTube.fetchDOMData();
+ /*
if ( (history && history.length === 1) || !history?.state?.endpoint?.watchEndpoint) { ImprovedTube.fetchDOMData(); }
else {
//Invidious instances. Should be updated automatically!...
@@ -264,48 +503,70 @@ window.addEventListener('load', () => { setTimeout(() => { clearInterval(waitFo
else { ImprovedTube.fetchDOMData();} }
})();
}
-*/
- } // else { }
- }
-}
-}
+*/
+ } // else { }
+ }
+ }
+};
/*------------------------------------------------------------------------------
SUBTITLES
------------------------------------------------------------------------------*/
ImprovedTube.playerSubtitles = function () {
- const player = this.elements.player;
-
- if (player && player.isSubtitlesOn && player.toggleSubtitles && player.toggleSubtitlesOn) {
- switch (this.storage.player_subtitles) {
- case true:
- case 'enabled':
- player.toggleSubtitlesOn();
- break
-
- case 'disabled':
- if (player.isSubtitlesOn()) { player.toggleSubtitles(); }
- break
- }
- }
+ const player = this.elements.player;
+
+ if (
+ player &&
+ player.isSubtitlesOn &&
+ player.toggleSubtitles &&
+ player.toggleSubtitlesOn
+ ) {
+ switch (this.storage.player_subtitles) {
+ case true:
+ case "enabled":
+ player.toggleSubtitlesOn();
+ break;
+
+ case "disabled":
+ if (player.isSubtitlesOn()) {
+ player.toggleSubtitles();
+ }
+ break;
+ }
+ }
};
/*------------------------------------------------------------------------------
SUBTITLES LANGUAGE
------------------------------------------------------------------------------*/
ImprovedTube.subtitlesLanguage = function () {
- const option = this.storage.subtitles_language,
- player = this.elements.player;
- let subtitlesState;
-
- if (option && player && player.getOption && player.setOption && player.isSubtitlesOn && player.toggleSubtitles) {
- const matchedTrack = player.getOption('captions', 'tracklist', {includeAsr: true})?.find(track => track.languageCode.includes(option) && (!track.vss_id.includes("a.") || this.storage.auto_generate));
-
- if (matchedTrack) {
- subtitlesState = player.isSubtitlesOn();
- player.setOption('captions', 'track', matchedTrack);
- // setOption forces Subtitles ON, restore state from before calling it.
- if (!subtitlesState) { player.toggleSubtitles(); }
- }
- }
+ const option = this.storage.subtitles_language,
+ player = this.elements.player;
+ let subtitlesState;
+
+ if (
+ option &&
+ player &&
+ player.getOption &&
+ player.setOption &&
+ player.isSubtitlesOn &&
+ player.toggleSubtitles
+ ) {
+ const matchedTrack = player
+ .getOption("captions", "tracklist", { includeAsr: true })
+ ?.find(
+ (track) =>
+ track.languageCode.includes(option) &&
+ (!track.vss_id.includes("a.") || this.storage.auto_generate)
+ );
+
+ if (matchedTrack) {
+ subtitlesState = player.isSubtitlesOn();
+ player.setOption("captions", "track", matchedTrack);
+ // setOption forces Subtitles ON, restore state from before calling it.
+ if (!subtitlesState) {
+ player.toggleSubtitles();
+ }
+ }
+ }
};
/*------------------------------------------------------------------------------
SUBTITLES FONT FAMILY
@@ -330,800 +591,1043 @@ default = {
},
------------------------------------------------------------------------------*/
ImprovedTube.subtitlesUserSettings = function () {
- const ourSettings = {
- fontFamily: this.storage.subtitles_font_family,
- color: this.storage.subtitles_font_color,
- fontSizeIncrement: this.storage.subtitles_font_size,
- background: this.storage.subtitles_background_color,
- backgroundOpacity: this.storage.subtitles_background_opacity,
- windowColor: this.storage.subtitles_window_color,
- windowOpacity: this.storage.subtitles_window_opacity,
- charEdgeStyle: this.storage.subtitles_character_edge_style,
- textOpacity: this.storage.subtitles_font_opacity
- },
- userSettings = Object.keys(ourSettings).filter(e => ourSettings[e]),
- player = this.elements.player;
-
- if (userSettings.length && player && player.getSubtitlesUserSettings && player.updateSubtitlesUserSettings) {
- let ytSettings = player.getSubtitlesUserSettings(),
- setting;
-
- if (!ytSettings) return; //null SubtitlesUserSettings seem to mean subtitles not available
-
- for (const value of userSettings) {
- setting = null;
- switch (value) {
- case 'fontFamily':
- case 'fontSizeIncrement':
- case 'charEdgeStyle':
- setting = Number(ourSettings[value]);
- break;
-
- case 'color':
- case 'background':
- case 'windowColor':
- setting = ourSettings[value];
- break;
-
- case 'backgroundOpacity':
- case 'windowOpacity':
- case 'textOpacity':
- setting = Number(ourSettings[value]) / 100;
- break;
- }
-
- if (Object.keys(ytSettings).includes(value)) {
- ytSettings[value] = setting;
- } else {
- console.error('subtitlesUserSettings failed at: ', value, setting);
- }
- }
- player.updateSubtitlesUserSettings(ytSettings);
- }
+ const ourSettings = {
+ fontFamily: this.storage.subtitles_font_family,
+ color: this.storage.subtitles_font_color,
+ fontSizeIncrement: this.storage.subtitles_font_size,
+ background: this.storage.subtitles_background_color,
+ backgroundOpacity: this.storage.subtitles_background_opacity,
+ windowColor: this.storage.subtitles_window_color,
+ windowOpacity: this.storage.subtitles_window_opacity,
+ charEdgeStyle: this.storage.subtitles_character_edge_style,
+ textOpacity: this.storage.subtitles_font_opacity,
+ },
+ userSettings = Object.keys(ourSettings).filter((e) => ourSettings[e]),
+ player = this.elements.player;
+
+ if (
+ userSettings.length &&
+ player &&
+ player.getSubtitlesUserSettings &&
+ player.updateSubtitlesUserSettings
+ ) {
+ let ytSettings = player.getSubtitlesUserSettings(),
+ setting;
+
+ if (!ytSettings) return; //null SubtitlesUserSettings seem to mean subtitles not available
+
+ for (const value of userSettings) {
+ setting = null;
+ switch (value) {
+ case "fontFamily":
+ case "fontSizeIncrement":
+ case "charEdgeStyle":
+ setting = Number(ourSettings[value]);
+ break;
+
+ case "color":
+ case "background":
+ case "windowColor":
+ setting = ourSettings[value];
+ break;
+
+ case "backgroundOpacity":
+ case "windowOpacity":
+ case "textOpacity":
+ setting = Number(ourSettings[value]) / 100;
+ break;
+ }
+
+ if (Object.keys(ytSettings).includes(value)) {
+ ytSettings[value] = setting;
+ } else {
+ console.error("subtitlesUserSettings failed at: ", value, setting);
+ }
+ }
+ player.updateSubtitlesUserSettings(ytSettings);
+ }
};
/*------------------------------------------------------------------------------
SUBTITLES DISABLE SUBTILES FOR LYRICS
------------------------------------------------------------------------------*/
ImprovedTube.subtitlesDisableLyrics = function () {
- if (this.storage.subtitles_disable_lyrics) {
- const player = this.elements.player;
-
- if (player && player.isSubtitlesOn && player.isSubtitlesOn() && player.toggleSubtitles) {
- // Music detection only uses 3 identifiers for Lyrics: lyrics, sing-along, karaoke.
- // Easier to simply use those here. Can replace with music detection later.
- const terms = ["sing along", "sing-along", "karaoke", "lyric", "卡拉OK", "卡拉OK", "الكاريوكي", "караоке", "カラオケ", "노래방"];
- if (terms.some(term => this.videoTitle().toLowerCase().includes(term))) {
- player.toggleSubtitles();
- }
- }
- }
+ if (this.storage.subtitles_disable_lyrics) {
+ const player = this.elements.player;
+
+ if (
+ player &&
+ player.isSubtitlesOn &&
+ player.isSubtitlesOn() &&
+ player.toggleSubtitles
+ ) {
+ // Music detection only uses 3 identifiers for Lyrics: lyrics, sing-along, karaoke.
+ // Easier to simply use those here. Can replace with music detection later.
+ const terms = [
+ "sing along",
+ "sing-along",
+ "karaoke",
+ "lyric",
+ "卡拉OK",
+ "卡拉OK",
+ "الكاريوكي",
+ "караоке",
+ "カラオケ",
+ "노래방",
+ ];
+ if (
+ terms.some((term) => this.videoTitle().toLowerCase().includes(term))
+ ) {
+ player.toggleSubtitles();
+ }
+ }
+ }
};
/*------------------------------------------------------------------------------
UP NEXT AUTOPLAY
------------------------------------------------------------------------------*/
ImprovedTube.upNextAutoplay = function () {
- var option = this.storage.up_next_autoplay;
+ var option = this.storage.up_next_autoplay;
- if (this.isset(option)) {
- var toggle = document.querySelector('.ytp-autonav-toggle-button');
+ if (this.isset(option)) {
+ var toggle = document.querySelector(".ytp-autonav-toggle-button");
- if (toggle) {
- if (option !== (toggle.getAttribute('aria-checked') === 'true')) {
- toggle.click();
- }
- }
- }
+ if (toggle) {
+ if (option !== (toggle.getAttribute("aria-checked") === "true")) {
+ toggle.click();
+ }
+ }
+ }
};
/*------------------------------------------------------------------------------
ADS
------------------------------------------------------------------------------*/
-ImprovedTube.playerAds = function (parent) {
- let button = parent.querySelector('.ytp-ad-skip-button-modern.ytp-button,[class*="ytp-ad-skip-button"].ytp-button') || parent;
- // TODO: Replace this with centralized video element pointer
- let video = document.querySelector('.video-stream.html5-main-video') || false;
- function skipAd () {
- if (video) video.currentTime = video.duration;
- if (button) button.click();
- }
- if (this.storage.ads === 'block_all') {
- skipAd();
- } else if (this.storage.ads === 'subscribed_channels') {
- if (!parent.querySelector('#meta paper-button[subscribed]')) {
- skipAd();
- }
- } else if (this.storage.ads === 'block_music') {
- if (ImprovedTube.elements.category === 'music') {
- skipAd();
- }
- } else if (this.storage.ads === 'small_creators') {
- let userDefiniedLimit = this.storage.smallCreatorsCount * parseInt(this.storage.smallCreatorsUnit);
- let subscribersNumber = ImprovedTube.subscriberCount;
- if (subscribersNumber > userDefiniedLimit) {
- skipAd();
- }
- }
+ImprovedTube.muteAds = function () {
+ if (
+ !ImprovedTube.storage.ads ||
+ ImprovedTube.storage.ads !== "mute_ads" ||
+ ImprovedTube._mutedAdsObserverInitialized
+ )
+ return;
+
+ let player = document.querySelector(".html5-video-player");
+ let video = document.querySelector(".video-stream.html5-main-video");
+
+ if (!player || !video) return;
+
+ let observer = new MutationObserver(() => {
+ let isAd = player.classList.contains("ad-showing") && video.duration < 40;
+
+ if (isAd) {
+ if (ImprovedTube.wasMutedBeforeAd === undefined) {
+ ImprovedTube.wasMutedBeforeAd = video.muted;
+ video.muted = true;
+ }
+ } else {
+ if (ImprovedTube.wasMutedBeforeAd !== undefined) {
+ video.muted = ImprovedTube.wasMutedBeforeAd;
+ ImprovedTube.wasMutedBeforeAd = undefined;
+ }
+ }
+ });
+
+ observer.observe(player, { attributes: true, attributeFilter: ["class"] });
+
+ ImprovedTube._mutedAdsObserverInitialized = true;
+};
+
+ImprovedTube.playerAds = function (parent) {
+ let button =
+ parent.querySelector(
+ '.ytp-ad-skip-button-modern.ytp-button,[class*="ytp-ad-skip-button"].ytp-button'
+ ) || parent;
+
+ // TODO: Replace this with centralized video element pointer
+ let video = document.querySelector(".video-stream.html5-main-video") || false;
+ function skipAd() {
+ if (video) video.currentTime = video.duration;
+ if (button) button.click();
+ }
+
+ if (this.storage.ads === "block_all") {
+ skipAd();
+ } else if (this.storage.ads === "subscribed_channels") {
+ if (!parent.querySelector("#meta paper-button[subscribed]")) {
+ skipAd();
+ }
+ } else if (this.storage.ads === "block_music") {
+ if (ImprovedTube.elements.category === "music") {
+ skipAd();
+ }
+ } else if (this.storage.ads === "small_creators") {
+ let userDefiniedLimit =
+ this.storage.smallCreatorsCount *
+ parseInt(this.storage.smallCreatorsUnit);
+ let subscribersNumber = ImprovedTube.subscriberCount;
+ if (subscribersNumber > userDefiniedLimit) {
+ skipAd();
+ }
+ } else {
+ if (this.storage.ads === "mute_ads") {
+ ImprovedTube.muteAds();
+ }
+ }
};
+
/*------------------------------------------------------------------------------
AUTO FULLSCREEN
------------------------------------------------------------------------------*/
ImprovedTube.playerAutofullscreen = function () {
- if (
- this.storage.player_autofullscreen === true &&
- document.documentElement.dataset.pageType === 'video' &&
- !document.fullscreenElement
- ) {
- this.elements.player.toggleFullscreen();
- }
+ if (
+ this.storage.player_autofullscreen === true &&
+ document.documentElement.dataset.pageType === "video" &&
+ !document.fullscreenElement
+ ) {
+ this.elements.player.toggleFullscreen();
+ }
};
/*------------------------------------------------------------------------------
QUALITY
------------------------------------------------------------------------------*/
ImprovedTube.playerQuality = function (quality = this.storage.player_quality) {
- let player = this.elements.player;
- if (quality && quality !== 'disabled'
- && player && player.getAvailableQualityLevels
- && (!player.dataset.defaultQuality || player.dataset.defaultQuality != quality)) {
- let available_quality_levels = player.getAvailableQualityLevels();
- function closest (num, arr) {
- let curr = arr[0];
- let diff = Math.abs(num - curr);
- for (let val = 1; val < arr.length; val++) {
- let newdiff = Math.abs(num - arr[val]);
- if (newdiff < diff) {
- diff = newdiff;
- curr = arr[val];
- }
- }
- return curr;
- };
-
- if (!available_quality_levels.includes(quality)) {
- let label = ['tiny', 'small', 'medium', 'large', 'hd720', 'hd1080', 'hd1440', 'hd2160', 'hd2880', 'highres'];
- let resolution = ['144', '240', '360', '480', '720', '1080', '1440', '2160', '2880', '4320'];
- let availableresolutions = available_quality_levels.map(q => resolution[label.indexOf(q)]);
- quality = label[resolution.indexOf(closest(resolution[label.indexOf(quality)], availableresolutions))];
- }
- player.setPlaybackQualityRange(quality);
- player.setPlaybackQuality(quality);
- player.dataset.defaultQuality = quality;
- }
+ let player = this.elements.player;
+ if (
+ quality &&
+ quality !== "disabled" &&
+ player &&
+ player.getAvailableQualityLevels &&
+ (!player.dataset.defaultQuality || player.dataset.defaultQuality != quality)
+ ) {
+ let available_quality_levels = player.getAvailableQualityLevels();
+ function closest(num, arr) {
+ let curr = arr[0];
+ let diff = Math.abs(num - curr);
+ for (let val = 1; val < arr.length; val++) {
+ let newdiff = Math.abs(num - arr[val]);
+ if (newdiff < diff) {
+ diff = newdiff;
+ curr = arr[val];
+ }
+ }
+ return curr;
+ }
+
+ if (!available_quality_levels.includes(quality)) {
+ let label = [
+ "tiny",
+ "small",
+ "medium",
+ "large",
+ "hd720",
+ "hd1080",
+ "hd1440",
+ "hd2160",
+ "hd2880",
+ "highres",
+ ];
+ let resolution = [
+ "144",
+ "240",
+ "360",
+ "480",
+ "720",
+ "1080",
+ "1440",
+ "2160",
+ "2880",
+ "4320",
+ ];
+ let availableresolutions = available_quality_levels.map(
+ (q) => resolution[label.indexOf(q)]
+ );
+ quality =
+ label[
+ resolution.indexOf(
+ closest(resolution[label.indexOf(quality)], availableresolutions)
+ )
+ ];
+ }
+ player.setPlaybackQualityRange(quality);
+ player.setPlaybackQuality(quality);
+ player.dataset.defaultQuality = quality;
+ }
};
/*------------------------------------------------------------------------------
QUALITY WITHOUT FOCUS
------------------------------------------------------------------------------*/
ImprovedTube.playerQualityWithoutFocus = function () {
- let player = this.elements.player,
- qualityWithoutFocus = this.storage.player_quality_without_focus;
- if (qualityWithoutFocus && qualityWithoutFocus !== 'auto' && player && player.getPlaybackQuality) {
- if (this.focus) {
- if (ImprovedTube.qualityBeforeBlur) {
- ImprovedTube.playerQuality(ImprovedTube.qualityBeforeBlur);
- ImprovedTube.qualityBeforeBlur = undefined;
- }
- } else {
- if (!ImprovedTube.elements.video.paused) {
- if (!ImprovedTube.qualityBeforeBlur) {
- ImprovedTube.qualityBeforeBlur = player.getPlaybackQuality();
- }
- ImprovedTube.playerQuality(qualityWithoutFocus);
- }
- }
- }
+ let player = this.elements.player,
+ qualityWithoutFocus = this.storage.player_quality_without_focus;
+ if (
+ qualityWithoutFocus &&
+ qualityWithoutFocus !== "auto" &&
+ player &&
+ player.getPlaybackQuality
+ ) {
+ if (this.focus) {
+ if (ImprovedTube.qualityBeforeBlur) {
+ ImprovedTube.playerQuality(ImprovedTube.qualityBeforeBlur);
+ ImprovedTube.qualityBeforeBlur = undefined;
+ }
+ } else {
+ if (!ImprovedTube.elements.video.paused) {
+ if (!ImprovedTube.qualityBeforeBlur) {
+ ImprovedTube.qualityBeforeBlur = player.getPlaybackQuality();
+ }
+ ImprovedTube.playerQuality(qualityWithoutFocus);
+ }
+ }
+ }
};
/*------------------------------------------------------------------------------
BATTERY FEATURES; PLAYER QUALITY BASED ON POWER STATUS
------------------------------------------------------------------------------*/
ImprovedTube.batteryFeatures = async function () {
- if (ImprovedTube.storage.qualityWhenRunningOnBattery
- || ImprovedTube.storage.pauseWhileIUnplugTheCharger
- || ImprovedTube.storage.whenBatteryIslowDecreaseQuality) {
- const updateQuality = async (battery, charging) => {
- if (battery) {
- if (!battery.charging) {
- if (ImprovedTube.storage.pauseWhileIUnplugTheCharger && charging) {
- ImprovedTube.elements.player.pauseVideo();
- ImprovedTube.paused = true;
- }
- if (ImprovedTube.storage.qualityWhenRunningOnBattery) {
- ImprovedTube.playerQuality(ImprovedTube.storage.qualityWhenRunningOnBattery);
- }
- if (ImprovedTube.storage.whenBatteryIslowDecreaseQuality) {
- let quality;
- if (battery.level > 0.11 || battery.dischargingTime > 900) {
- quality = "large";
- } else if (battery.level > 0.08 || battery.dischargingTime > 600) {
- quality = "medium";
- } else if (battery.level > 0.04 || battery.dischargingTime > 360) {
- quality = "small";
- } else {
- quality = "tiny";
- }
- ImprovedTube.playerQuality(quality);
- }
- } else if (charging && ImprovedTube.paused && ImprovedTube.storage.pauseWhileIUnplugTheCharger) {
- ImprovedTube.elements.player.playVideo();
- delete ImprovedTube.paused;
- }
- }
- };
- const battery = await navigator.getBattery();
- battery.addEventListener("levelchange", () => updateQuality(battery));
- battery.addEventListener("chargingchange", () => updateQuality(battery, true));
- await updateQuality(battery);
- }
+ if (
+ ImprovedTube.storage.qualityWhenRunningOnBattery ||
+ ImprovedTube.storage.pauseWhileIUnplugTheCharger ||
+ ImprovedTube.storage.whenBatteryIslowDecreaseQuality
+ ) {
+ const updateQuality = async (battery, charging) => {
+ if (battery) {
+ if (!battery.charging) {
+ if (ImprovedTube.storage.pauseWhileIUnplugTheCharger && charging) {
+ ImprovedTube.elements.player.pauseVideo();
+ ImprovedTube.paused = true;
+ }
+ if (ImprovedTube.storage.qualityWhenRunningOnBattery) {
+ ImprovedTube.playerQuality(
+ ImprovedTube.storage.qualityWhenRunningOnBattery
+ );
+ }
+ if (ImprovedTube.storage.whenBatteryIslowDecreaseQuality) {
+ let quality;
+ if (battery.level > 0.11 || battery.dischargingTime > 900) {
+ quality = "large";
+ } else if (battery.level > 0.08 || battery.dischargingTime > 600) {
+ quality = "medium";
+ } else if (battery.level > 0.04 || battery.dischargingTime > 360) {
+ quality = "small";
+ } else {
+ quality = "tiny";
+ }
+ ImprovedTube.playerQuality(quality);
+ }
+ } else if (
+ charging &&
+ ImprovedTube.paused &&
+ ImprovedTube.storage.pauseWhileIUnplugTheCharger
+ ) {
+ ImprovedTube.elements.player.playVideo();
+ delete ImprovedTube.paused;
+ }
+ }
+ };
+ const battery = await navigator.getBattery();
+ battery.addEventListener("levelchange", () => updateQuality(battery));
+ battery.addEventListener("chargingchange", () =>
+ updateQuality(battery, true)
+ );
+ await updateQuality(battery);
+ }
};
/*------------------------------------------------------------------------------
FORCED VOLUME
------------------------------------------------------------------------------*/
ImprovedTube.playerVolume = function () {
- if (this.storage.player_forced_volume === true) {
- var volume = this.storage.player_volume;
-
- if (!this.isset(volume)) {
- volume = 100;
- } else {
- volume = Number(volume);
- }
-
- if (!this.audioContextGain && volume <= 100) {
- if (this.audioContext) {
- this.audioContext.close();
- }
-
- this.elements.player.setVolume(volume);
- } else {
- if (!this.audioContext) {
- this.audioContext = new AudioContext();
-
- this.audioContextSource = this.audioContext.createMediaElementSource(document.querySelector('video'));
- this.audioContextGain = this.audioContext.createGain();
-
- this.audioContextGain.gain.value = 1;
- this.audioContextSource.connect(this.audioContextGain);
- this.audioContextGain.connect(this.audioContext.destination)
- }
- if (this.elements.player.getVolume() !== 100) { this.elements.player.setVolume(100);}
- this.audioContextGain.gain.value = volume / 100;
- }
- }
+ if (this.storage.player_forced_volume === true) {
+ var volume = this.storage.player_volume;
+
+ if (!this.isset(volume)) {
+ volume = 100;
+ } else {
+ volume = Number(volume);
+ }
+
+ if (!this.audioContextGain && volume <= 100) {
+ if (this.audioContext) {
+ this.audioContext.close();
+ }
+
+ this.elements.player.setVolume(volume);
+ } else {
+ if (!this.audioContext) {
+ this.audioContext = new AudioContext();
+
+ this.audioContextSource = this.audioContext.createMediaElementSource(
+ document.querySelector("video")
+ );
+ this.audioContextGain = this.audioContext.createGain();
+
+ this.audioContextGain.gain.value = 1;
+ this.audioContextSource.connect(this.audioContextGain);
+ this.audioContextGain.connect(this.audioContext.destination);
+ }
+ if (this.elements.player.getVolume() !== 100) {
+ this.elements.player.setVolume(100);
+ }
+ this.audioContextGain.gain.value = volume / 100;
+ }
+ }
};
/*------------------------------------------------------------------------------
LOUDNESS NORMALIZATION
------------------------------------------------------------------------------*/
ImprovedTube.onvolumechange = function () {
- if (document.querySelector('.ytp-volume-panel') && ImprovedTube.storage.player_loudness_normalization === false) {
- var volume = Number(document.querySelector('.ytp-volume-panel').getAttribute('aria-valuenow'));
-
- this.volume = volume / 100;
- }
+ if (
+ document.querySelector(".ytp-volume-panel") &&
+ ImprovedTube.storage.player_loudness_normalization === false
+ ) {
+ var volume = Number(
+ document.querySelector(".ytp-volume-panel").getAttribute("aria-valuenow")
+ );
+
+ this.volume = volume / 100;
+ }
};
ImprovedTube.playerLoudnessNormalization = function () {
- var video = this.elements.video;
-
- if (video) {
- video.removeEventListener('volumechange', this.onvolumechange);
- video.addEventListener('volumechange', this.onvolumechange);
- }
-
- if (this.storage.player_loudness_normalization === false) {
- try {
- var local_storage = localStorage['yt-player-volume'];
-
- if (this.isset(Number(this.storage.player_volume)) && this.storage.player_forced_volume === true) {
- return;
- } else if (local_storage) {
- local_storage = JSON.parse(JSON.parse(local_storage).data);
-
- local_storage = Number(local_storage.volume);
-
- video.volume = local_storage / 100;
- } else {
- video.volume = 100;
- }
- } catch (err) {}
- }
+ var video = this.elements.video;
+
+ if (video) {
+ video.removeEventListener("volumechange", this.onvolumechange);
+ video.addEventListener("volumechange", this.onvolumechange);
+ }
+
+ if (this.storage.player_loudness_normalization === false) {
+ try {
+ var local_storage = localStorage["yt-player-volume"];
+
+ if (
+ this.isset(Number(this.storage.player_volume)) &&
+ this.storage.player_forced_volume === true
+ ) {
+ return;
+ } else if (local_storage) {
+ local_storage = JSON.parse(JSON.parse(local_storage).data);
+
+ local_storage = Number(local_storage.volume);
+
+ video.volume = local_storage / 100;
+ } else {
+ video.volume = 100;
+ }
+ } catch (err) {}
+ }
};
/*------------------------------------------------------------------------------
SCREENSHOT
------------------------------------------------------------------------------*/
ImprovedTube.screenshot = function () {
- const video = ImprovedTube.elements.video,
- cvs = document.createElement('canvas'),
- ctx = cvs.getContext('2d');
- let subText = '';
-
- cvs.width = video.videoWidth;
- cvs.height = video.videoHeight;
-
- ctx.drawImage(video, 0, 0, cvs.width, cvs.height);
-
- if (ImprovedTube.storage.embed_subtitle != false) {
- let captionElements = document.querySelectorAll('.captions-text .ytp-caption-segment');
- captionElements.forEach(function (caption) {subText += caption.textContent.trim() + ' ';});
-
- ImprovedTube.renderSubtitle(ctx, captionElements);
- }
-
- cvs.toBlob(function (blob) {
- if (ImprovedTube.storage.player_screenshot_save_as == 'clipboard') {
- window.focus();
- navigator.clipboard.write([
- new ClipboardItem({
- 'image/png': blob
- })
- ])
- .then(function () { console.log("ImprovedTube: Screeeeeeenshot tada!"); })
- .catch(function (error) {
- console.log('ImprovedTube screenshot: ', error);
- alert('ImprovedTube Screenshot to Clipboard error. Details in Debug Console.');
- });
- } else {
- let a = document.createElement('a');
- a.href = URL.createObjectURL(blob);
- a.download = (ImprovedTube.videoId() || location.href.match) + ' ' + new Date(ImprovedTube.elements.player.getCurrentTime() * 1000).toISOString().substr(11, 8).replace(/:/g, '-') + ' ' + ImprovedTube.videoTitle() + (subText ? ' - ' + subText.trim() : '') + '.png';
- a.click();
- console.log("ImprovedTube: Screeeeeeenshot tada!");
- }
- });
+ const video = ImprovedTube.elements.video,
+ cvs = document.createElement("canvas"),
+ ctx = cvs.getContext("2d");
+ let subText = "";
+
+ cvs.width = video.videoWidth;
+ cvs.height = video.videoHeight;
+
+ ctx.drawImage(video, 0, 0, cvs.width, cvs.height);
+
+ if (ImprovedTube.storage.embed_subtitle != false) {
+ let captionElements = document.querySelectorAll(
+ ".captions-text .ytp-caption-segment"
+ );
+ captionElements.forEach(function (caption) {
+ subText += caption.textContent.trim() + " ";
+ });
+
+ ImprovedTube.renderSubtitle(ctx, captionElements);
+ }
+
+ cvs.toBlob(function (blob) {
+ if (ImprovedTube.storage.player_screenshot_save_as == "clipboard") {
+ window.focus();
+ navigator.clipboard
+ .write([
+ new ClipboardItem({
+ "image/png": blob,
+ }),
+ ])
+ .then(function () {
+ console.log("ImprovedTube: Screeeeeeenshot tada!");
+ })
+ .catch(function (error) {
+ console.log("ImprovedTube screenshot: ", error);
+ alert(
+ "ImprovedTube Screenshot to Clipboard error. Details in Debug Console."
+ );
+ });
+ } else {
+ let a = document.createElement("a");
+ a.href = URL.createObjectURL(blob);
+ a.download =
+ (ImprovedTube.videoId() || location.href.match) +
+ " " +
+ new Date(ImprovedTube.elements.player.getCurrentTime() * 1000)
+ .toISOString()
+ .substr(11, 8)
+ .replace(/:/g, "-") +
+ " " +
+ ImprovedTube.videoTitle() +
+ (subText ? " - " + subText.trim() : "") +
+ ".png";
+ a.click();
+ console.log("ImprovedTube: Screeeeeeenshot tada!");
+ }
+ });
};
ImprovedTube.renderSubtitle = function (ctx, captionElements) {
- if (ctx && captionElements) {
- captionElements.forEach(function (captionElement, index) {
- var captionText = captionElement.textContent.trim();
- var captionStyles = window.getComputedStyle(captionElement);
-
- ctx.fillStyle = captionStyles.color;
- ctx.font = captionStyles.font;
- ctx.textAlign = 'center';
- ctx.textBaseline = 'bottom';
- var txtWidth = ctx.measureText(captionText).width;
- var txtHeight = parseFloat(captionStyles.fontSize);
-
- var xOfset = (ctx.canvas.width - txtWidth) / 2;
-
- var padding = 5; // Adjust the padding as needed
- var yofset = ctx.canvas.height - (captionElements.length - index) * (txtHeight + 2 * padding);
-
- ctx.fillStyle = captionStyles.backgroundColor;
- ctx.fillRect(xOfset - padding, yofset - txtHeight - padding, txtWidth + 2 * padding, txtHeight + 2 * padding);
- ctx.fillStyle = captionStyles.color;
- ctx.fillText(captionText, xOfset + txtWidth / 2, yofset);
- });
- }
+ if (ctx && captionElements) {
+ captionElements.forEach(function (captionElement, index) {
+ var captionText = captionElement.textContent.trim();
+ var captionStyles = window.getComputedStyle(captionElement);
+
+ ctx.fillStyle = captionStyles.color;
+ ctx.font = captionStyles.font;
+ ctx.textAlign = "center";
+ ctx.textBaseline = "bottom";
+ var txtWidth = ctx.measureText(captionText).width;
+ var txtHeight = parseFloat(captionStyles.fontSize);
+
+ var xOfset = (ctx.canvas.width - txtWidth) / 2;
+
+ var padding = 5; // Adjust the padding as needed
+ var yofset =
+ ctx.canvas.height -
+ (captionElements.length - index) * (txtHeight + 2 * padding);
+
+ ctx.fillStyle = captionStyles.backgroundColor;
+ ctx.fillRect(
+ xOfset - padding,
+ yofset - txtHeight - padding,
+ txtWidth + 2 * padding,
+ txtHeight + 2 * padding
+ );
+ ctx.fillStyle = captionStyles.color;
+ ctx.fillText(captionText, xOfset + txtWidth / 2, yofset);
+ });
+ }
};
ImprovedTube.playerScreenshotButton = function () {
- if (this.storage.player_screenshot_button === true) {
- var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
- path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
-
- svg.setAttributeNS(null, 'viewBox', '0 0 24 24');
- path.setAttributeNS(null, 'd', 'M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z');
-
- svg.appendChild(path);
-
- this.createPlayerButton({
- id: 'it-screenshot-button',
- child: svg,
- opacity: 0.64,
- onclick: this.screenshot,
- title: 'Screenshot'
- });
- }
+ if (this.storage.player_screenshot_button === true) {
+ var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"),
+ path = document.createElementNS("http://www.w3.org/2000/svg", "path");
+
+ svg.setAttributeNS(null, "viewBox", "0 0 24 24");
+ path.setAttributeNS(
+ null,
+ "d",
+ "M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"
+ );
+
+ svg.appendChild(path);
+
+ this.createPlayerButton({
+ id: "it-screenshot-button",
+ child: svg,
+ opacity: 0.64,
+ onclick: this.screenshot,
+ title: "Screenshot",
+ });
+ }
};
/*------------------------------------------------------------------------------
REPEAT
-------------------------------------------------------------------------------*/
ImprovedTube.playerRepeat = function () {
- setTimeout(function () {
- if (!/ad-showing/.test(ImprovedTube.elements.player.className)) {
- ImprovedTube.elements.video.setAttribute('loop', '');
- }
- //ImprovedTube.elements.buttons['it-repeat-styles'].style.opacity = '1'; //old class from version 3.x? that both repeat buttons could have
- }, 200);
-}
+ setTimeout(function () {
+ if (!/ad-showing/.test(ImprovedTube.elements.player.className)) {
+ ImprovedTube.elements.video.setAttribute("loop", "");
+ }
+ //ImprovedTube.elements.buttons['it-repeat-styles'].style.opacity = '1'; //old class from version 3.x? that both repeat buttons could have
+ }, 200);
+};
/*------------------------------------------------------------------------------
REPEAT BUTTON
------------------------------------------------------------------------------*/
ImprovedTube.playerRepeatButton = function () {
- if (this.storage.player_repeat_button === true) {
- var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
- path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
- svg.setAttributeNS(null, 'viewBox', '0 0 24 24');
- path.setAttributeNS(null, 'd', 'M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4zm-4-2V9h-1l-2 1v1h1.5v4H13z');
- svg.appendChild(path);
- var transparentOrOn = 0.5; if (this.storage.player_always_repeat === true ) { transparentOrOn = 1; }
- this.createPlayerButton({
- id: 'it-repeat-button',
- child: svg,
- opacity: transparentOrOn,
- onclick: function () {
- var video = ImprovedTube.elements.video;
- function matchLoopState (opacity) {
- var thisButton = document.querySelector('#it-repeat-button');
- thisButton.style.opacity = opacity;
- if (ImprovedTube.storage.below_player_loop !== false) {
- var otherButton = document.querySelector('#it-below-player-loop');
- otherButton.children[0].style.opacity = opacity;
- }
- } if (video.hasAttribute('loop')) {
- video.removeAttribute('loop');
- matchLoopState('.5')
- } else if (!/ad-showing/.test(ImprovedTube.elements.player.className)) {
- video.setAttribute('loop', '');
- matchLoopState('1')
- }
- },
- title: 'Repeat',
- });
- }
+ if (this.storage.player_repeat_button === true) {
+ var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"),
+ path = document.createElementNS("http://www.w3.org/2000/svg", "path");
+ svg.setAttributeNS(null, "viewBox", "0 0 24 24");
+ path.setAttributeNS(
+ null,
+ "d",
+ "M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4zm-4-2V9h-1l-2 1v1h1.5v4H13z"
+ );
+ svg.appendChild(path);
+ var transparentOrOn = 0.5;
+ if (this.storage.player_always_repeat === true) {
+ transparentOrOn = 1;
+ }
+ this.createPlayerButton({
+ id: "it-repeat-button",
+ child: svg,
+ opacity: transparentOrOn,
+ onclick: function () {
+ var video = ImprovedTube.elements.video;
+ function matchLoopState(opacity) {
+ var thisButton = document.querySelector("#it-repeat-button");
+ thisButton.style.opacity = opacity;
+ if (ImprovedTube.storage.below_player_loop !== false) {
+ var otherButton = document.querySelector("#it-below-player-loop");
+ otherButton.children[0].style.opacity = opacity;
+ }
+ }
+ if (video.hasAttribute("loop")) {
+ video.removeAttribute("loop");
+ matchLoopState(".5");
+ } else if (!/ad-showing/.test(ImprovedTube.elements.player.className)) {
+ video.setAttribute("loop", "");
+ matchLoopState("1");
+ }
+ },
+ title: "Repeat",
+ });
+ }
};
/*------------------------------------------------------------------------------
ROTATE
------------------------------------------------------------------------------*/
ImprovedTube.playerRotateButton = function () {
- if (this.storage.player_rotate_button === true) {
- var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
- path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
-
- svg.setAttributeNS(null, 'viewBox', '0 0 24 24');
- path.setAttributeNS(null, 'd', 'M15.55 5.55L11 1v3.07a8 8 0 0 0 0 15.86v-2.02a6 6 0 0 1 0-11.82V10l4.55-4.45zM19.93 11a7.9 7.9 0 0 0-1.62-3.89l-1.42 1.42c.54.75.88 1.6 1.02 2.47h2.02zM13 17.9v2.02a7.92 7.92 0 0 0 3.9-1.61l-1.44-1.44c-.75.54-1.59.89-2.46 1.03zm3.89-2.42l1.42 1.41A7.9 7.9 0 0 0 19.93 13h-2.02a5.9 5.9 0 0 1-1.02 2.48z');
-
- svg.appendChild(path);
-
- this.createPlayerButton({
- id: 'it-rotate-button',
- child: svg,
- opacity: 0.85,
- onclick: function (e) {
- var player = ImprovedTube.elements.player,
- video = ImprovedTube.elements.video,
- rotate = Number(document.body.dataset.itRotate) || 0,
- transform = '';
- if(!e.ctrlKey){
- rotate += 90;
- } else {
- rotate -= 90;
- }
-
- if (rotate === 360) {
- rotate = 0;
- } else if (rotate < 0){
- rotate = 270;
- }
-
- document.body.dataset.itRotate = rotate;
-
- transform += 'rotate(' + rotate + 'deg)';
-
- if (rotate == 90 || rotate == 270) {
- var is_vertical_video = video.videoHeight > video.videoWidth;
-
- transform += ' scale(' + (is_vertical_video ? player.clientWidth : player.clientHeight) / (is_vertical_video ? player.clientHeight : player.clientWidth) + ')';
- }
-
- if (!ImprovedTube.elements.buttons['it-rotate-styles']) {
- var style = document.createElement('style');
-
- ImprovedTube.elements.buttons['it-rotate-styles'] = style;
-
- document.body.appendChild(style);
- }
-
- ImprovedTube.elements.buttons['it-rotate-styles'].textContent = 'video{transform:' + transform + '}';
- },
- title: 'Rotate'
- });
- }
+ if (this.storage.player_rotate_button === true) {
+ var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"),
+ path = document.createElementNS("http://www.w3.org/2000/svg", "path");
+
+ svg.setAttributeNS(null, "viewBox", "0 0 24 24");
+ path.setAttributeNS(
+ null,
+ "d",
+ "M15.55 5.55L11 1v3.07a8 8 0 0 0 0 15.86v-2.02a6 6 0 0 1 0-11.82V10l4.55-4.45zM19.93 11a7.9 7.9 0 0 0-1.62-3.89l-1.42 1.42c.54.75.88 1.6 1.02 2.47h2.02zM13 17.9v2.02a7.92 7.92 0 0 0 3.9-1.61l-1.44-1.44c-.75.54-1.59.89-2.46 1.03zm3.89-2.42l1.42 1.41A7.9 7.9 0 0 0 19.93 13h-2.02a5.9 5.9 0 0 1-1.02 2.48z"
+ );
+
+ svg.appendChild(path);
+
+ this.createPlayerButton({
+ id: "it-rotate-button",
+ child: svg,
+ opacity: 0.85,
+ onclick: function (e) {
+ var player = ImprovedTube.elements.player,
+ video = ImprovedTube.elements.video,
+ rotate = Number(document.body.dataset.itRotate) || 0,
+ transform = "";
+ if (!e.ctrlKey) {
+ rotate += 90;
+ } else {
+ rotate -= 90;
+ }
+
+ if (rotate === 360) {
+ rotate = 0;
+ } else if (rotate < 0) {
+ rotate = 270;
+ }
+
+ document.body.dataset.itRotate = rotate;
+
+ transform += "rotate(" + rotate + "deg)";
+
+ if (rotate == 90 || rotate == 270) {
+ var is_vertical_video = video.videoHeight > video.videoWidth;
+
+ transform +=
+ " scale(" +
+ (is_vertical_video ? player.clientWidth : player.clientHeight) /
+ (is_vertical_video ? player.clientHeight : player.clientWidth) +
+ ")";
+ }
+
+ if (!ImprovedTube.elements.buttons["it-rotate-styles"]) {
+ var style = document.createElement("style");
+
+ ImprovedTube.elements.buttons["it-rotate-styles"] = style;
+
+ document.body.appendChild(style);
+ }
+
+ ImprovedTube.elements.buttons["it-rotate-styles"].textContent =
+ "video{transform:" + transform + "}";
+ },
+ title: "Rotate",
+ });
+ }
};
/*------------------------------------------------------------------------------
FIT-TO-WIN BUTTON
------------------------------------------------------------------------------*/
ImprovedTube.playerFitToWinButton = function () {
- if (this.storage.player_fit_to_win_button === true && (/watch\?/.test(location.href))) {
- let tempContainer = document.createElement("div");
- let svg;
- if (typeof trustedTypes !== 'undefined' && typeof trustedTypes.createPolicy === 'function') {
- // Create a Trusted Type policy
- const policy = trustedTypes.createPolicy('default', {
- createHTML: (string) => string,
- });
-
- // Use the policy to set innerHTML
- tempContainer.innerHTML = policy.createHTML(`
+ if (
+ this.storage.player_fit_to_win_button === true &&
+ /watch\?/.test(location.href)
+ ) {
+ let tempContainer = document.createElement("div");
+ let svg;
+ if (
+ typeof trustedTypes !== "undefined" &&
+ typeof trustedTypes.createPolicy === "function"
+ ) {
+ // Create a Trusted Type policy
+ const policy = trustedTypes.createPolicy("default", {
+ createHTML: (string) => string,
+ });
+
+ // Use the policy to set innerHTML
+ tempContainer.innerHTML = policy.createHTML(`
`);
- // Ensure the SVG element is correctly parsed
- svg = tempContainer.querySelector('svg');
- } else {tempContainer.innerHTML = `