From ab26e6de15279071a3f95bad00aa1cc54c7b471b Mon Sep 17 00:00:00 2001
From: kalischuchhardt <148989348+kalischuchhardt@users.noreply.github.com>
Date: Sun, 5 Oct 2025 15:20:34 -0400
Subject: [PATCH 1/3] Add disable hold-to-play 2x feature and related
UI/settings
---
_locales/en/messages.json | 3 +
js&css/extension/functions.js | 144 +++++++++++++-
.../www.youtube.com/appearance.js | 2 +-
.../web-accessible/www.youtube.com/player.js | 2 +-
manifest.json | 181 ++++++++++--------
menu/index.html | 1 +
menu/skeleton-parts/appearance.js | 4 +-
menu/skeleton-parts/player.js | 8 +
8 files changed, 254 insertions(+), 91 deletions(-)
diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index 50a7e823e..584276f46 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -1513,5 +1513,8 @@
},
"excludeShortsInPlayAll": {
"message": "Exclude Shorts when using \"Play all\""
+ },
+ "disableHoldToPlay2x":{
+ "message": "Disable hold to play 2x"
}
}
diff --git a/js&css/extension/functions.js b/js&css/extension/functions.js
index 4b6c9f742..7efb60030 100644
--- a/js&css/extension/functions.js
+++ b/js&css/extension/functions.js
@@ -1,3 +1,4 @@
+window.ImprovedTube = window.ImprovedTube || {};
/*--------------------------------------------------------------
>>> FUNCTIONS:
/*--------------------------------------------------------------
@@ -6,4 +7,145 @@
extension.functions.getUrlParameter = function (url, parameter) {
var match = url.match(new RegExp('(\\?|\\&)' + parameter + '=[^&]+'));
if (match) {return match[0].substr(3);}
-};
\ No newline at end of file
+};
+
+/*------------------------------------------------------------------------------
+DISABLE/ENABLE HOLD TO PLAY ON 2X SPEED (GLOBAL)
+------------------------------------------------------------------------------*/
+ImprovedTube._holdToPlayListener = null;
+
+// DISABLE
+ImprovedTube.disableHoldToPlay = function () {
+ console.log('[ImprovedTube] disableHoldToPlay called');
+
+
+ // REMOVE PREVIOUS LISTENERS
+ if (this._holdToPlayListener) {
+ document.removeEventListener('keydown', this._holdToPlayListener, true);
+ document.removeEventListener('keyup', this._holdToPlayListener, true);
+ document.removeEventListener('mousedown', this._holdToPlayListener, true);
+ document.removeEventListener('mouseup', this._holdToPlayListener, true);
+ this._holdToPlayListener = null;
+ console.log('[ImprovedTube] Removed previous holdToPlay listeners');
+ }
+
+
+ this._holdToPlayListener = (e) => {
+ // BLOCK SPACEBAR HOLD (block ALL keydown/keyup for Space)
+ if ((e.type === 'keydown' && e.code === 'Space') ||
+ (e.type === 'keyup' && e.code === 'Space')) {
+ console.log('[ImprovedTube] Blocked spacebar event:', e.type, e);
+ e.stopImmediatePropagation();
+ e.preventDefault();
+ }
+ // BLOCK MOUSE HOLD
+ if ((e.type === 'mousedown' || e.type === 'mouseup') && e.target.tagName === 'VIDEO') {
+ console.log('[ImprovedTube] Blocked mouse event:', e.type, e);
+ e.stopImmediatePropagation();
+ e.preventDefault();
+ }
+ };
+
+
+ document.addEventListener('keydown', this._holdToPlayListener, true);
+ document.addEventListener('keyup', this._holdToPlayListener, true);
+ document.addEventListener('mousedown', this._holdToPlayListener, true);
+ document.addEventListener('mouseup', this._holdToPlayListener, true);
+ console.log('[ImprovedTube] Attached holdToPlay listeners');
+
+ // REATTACH LISTENERS IF VIDEO ELEMENT CHANGES (YOUTUBE SPA NAVIGATION)
+ if (!this._holdToPlayVideoObserver) {
+ this._holdToPlayVideoObserver = new MutationObserver(() => {
+ // CHECK CHROME STORAGE FOR THE NEWEST VALUE
+ chrome.storage.local.get('disable_hold_to_play_2x', (result) => {
+ console.log('[ImprovedTube] MutationObserver: disable_hold_to_play_2x =', result.disable_hold_to_play_2x);
+ if (result.disable_hold_to_play_2x) {
+ ImprovedTube.disableHoldToPlay();
+ } else {
+ ImprovedTube.enableHoldToPlay();
+ }
+ });
+ });
+ const player = document.getElementById('movie_player') || document.querySelector('.html5-video-player');
+ if (player) {
+ this._holdToPlayVideoObserver.observe(player, { childList: true, subtree: true });
+ console.log('[ImprovedTube] MutationObserver attached to player');
+ }
+ }
+};
+// ENABLE
+ImprovedTube.enableHoldToPlay = function () {
+ console.log('[ImprovedTube] enableHoldToPlay called');
+ if (this._holdToPlayListener) {
+ document.removeEventListener('keydown', this._holdToPlayListener, true);
+ document.removeEventListener('keyup', this._holdToPlayListener, true);
+ document.removeEventListener('mousedown', this._holdToPlayListener, true);
+ document.removeEventListener('mouseup', this._holdToPlayListener, true);
+ this._holdToPlayListener = null;
+ console.log('[ImprovedTube] Removed holdToPlay listeners (enable)');
+ }
+ if (this._holdToPlayVideoObserver) {
+ this._holdToPlayVideoObserver.disconnect();
+ this._holdToPlayVideoObserver = null;
+ console.log('[ImprovedTube] MutationObserver disconnected (enable)');
+ }
+};
+
+// LISTEN FOR STORAGE CHANGES TO UPDATE THE BEHAVIOR INSTANTLY
+if (typeof chrome !== 'undefined' && chrome.storage && chrome.storage.onChanged) {
+ chrome.storage.onChanged.addListener(function(changes, area) {
+ if (area === 'local' && changes.disable_hold_to_play_2x) {
+ console.log('[ImprovedTube] chrome.storage.onChanged: disable_hold_to_play_2x =', changes.disable_hold_to_play_2x.newValue);
+ if (changes.disable_hold_to_play_2x.newValue) {
+ ImprovedTube.disableHoldToPlay();
+ } else {
+ ImprovedTube.enableHoldToPlay();
+ }
+ }
+ });
+}
+
+// CHECKS CHROME STORAGE ON CONTENT SCRIPT LOAD AND INITIALIZES
+if (typeof chrome !== 'undefined' && chrome.storage && chrome.storage.local) {
+ chrome.storage.local.get('disable_hold_to_play_2x', (result) => {
+ console.log('[ImprovedTube] Content script loaded. disable_hold_to_play_2x =', result.disable_hold_to_play_2x);
+ if (result.disable_hold_to_play_2x) {
+ // SCRIPT TAG INJECTION (TO CATCH EVENTS BEFORE YT DOES)
+ const code = `
+ (function() {
+ function blockHoldToPlay(e) {
+ if ((e.type === 'keydown' && e.code === 'Space') ||
+ (e.type === 'keyup' && e.code === 'Space')) {
+ console.log('[ImprovedTube injected] Blocked spacebar event:', e.type, e);
+ e.stopImmediatePropagation();
+ e.preventDefault();
+ }
+ if ((e.type === 'mousedown' || e.type === 'mouseup') && e.target.tagName === 'VIDEO') {
+ console.log('[ImprovedTube injected] Blocked mouse event:', e.type, e);
+ e.stopImmediatePropagation();
+ e.preventDefault();
+ }
+ }
+ window.addEventListener('keydown', blockHoldToPlay, true);
+ window.addEventListener('keyup', blockHoldToPlay, true);
+ window.addEventListener('mousedown', blockHoldToPlay, true);
+ window.addEventListener('mouseup', blockHoldToPlay, true);
+ console.log('[ImprovedTube injected] Hold-to-play block active');
+ })();
+ `;
+ const script = document.createElement('script');
+ script.textContent = code;
+ (document.head || document.documentElement).appendChild(script);
+ script.remove();
+ }
+ // RUN THE NORMAL CONTENT SCRIPT LOGIC
+ if (result.disable_hold_to_play_2x) {
+ ImprovedTube.disableHoldToPlay();
+ } else {
+ ImprovedTube.enableHoldToPlay();
+ }
+ });
+}
+/*------------------------------------------------------------------------------
+END OF DISABLE/ENABLE HOLD TO PLAY ON 2X SPEED (GLOBAL)
+------------------------------------------------------------------------------*/
\ No newline at end of file
diff --git a/js&css/web-accessible/www.youtube.com/appearance.js b/js&css/web-accessible/www.youtube.com/appearance.js
index ad491926f..248adca40 100644
--- a/js&css/web-accessible/www.youtube.com/appearance.js
+++ b/js&css/web-accessible/www.youtube.com/appearance.js
@@ -869,7 +869,7 @@ ImprovedTube.playerRevertTheaterButtonSize();
document.addEventListener('yt-page-data-updated', run);
document.addEventListener('yt-navigate-finish', run);
window.addEventListener('load', run);
- etTimeout(run, 2000); // fallback for late loads
+ setTimeout(run, 2000); // fallback for late loads
})();
/*------------------------------------------------------------------------------
diff --git a/js&css/web-accessible/www.youtube.com/player.js b/js&css/web-accessible/www.youtube.com/player.js
index b00ad715e..806270273 100644
--- a/js&css/web-accessible/www.youtube.com/player.js
+++ b/js&css/web-accessible/www.youtube.com/player.js
@@ -268,7 +268,7 @@ window.addEventListener('load', () => { setTimeout(() => { clearInterval(waitFo
} // else { }
}
}
-}
+}
/*------------------------------------------------------------------------------
SUBTITLES
------------------------------------------------------------------------------*/
diff --git a/manifest.json b/manifest.json
index 589992ce9..9f490d4b7 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,86 +1,97 @@
{
- "manifest_version": 3,
- "short_name": "ImprovedTube",
- "name": "'Improve YouTube!' 🎧 (for YouTube & Videos)",
- "description": "__MSG_description_ext__",
- "version": "4",
- "default_locale": "en",
- "icons": {
- "128": "menu/icons/128.png",
- "16": "menu/icons/16.png",
- "32": "menu/icons/32.png",
- "48": "menu/icons/48.png"
- },
- "browser_specific_settings": {
- "gecko": {
- "id": "{3c6bf0cc-3ae2-42fb-9993-0d33104fdcaf}"
- }
- },
- "background": {
- "service_worker": "background.js"
- },
- "action": {
- "default_popup": "menu/index.html",
- "default_area": "navbar"
- },
- "options_page": "menu/index.html",
- "options_ui": {
- "page": "menu/index.html"
- },
- "content_scripts": [
- {
- "all_frames": true,
- "css": [
- "js&css/extension/www.youtube.com/styles.css",
- "js&css/extension/www.youtube.com/night-mode/night-mode.css",
- "js&css/extension/www.youtube.com/general/general.css",
- "js&css/extension/www.youtube.com/appearance/header/header.css",
- "js&css/extension/www.youtube.com/appearance/player/player.css",
- "js&css/extension/www.youtube.com/appearance/details/details.css",
- "js&css/extension/www.youtube.com/appearance/sidebar/sidebar.css",
- "js&css/extension/www.youtube.com/appearance/comments/comments.css"
- ],
- "exclude_matches": [
- "https://www.youtube.com/audiolibrary/*",
- "https://www.youtube.com/tv*"
- ],
- "js": [
- "js&css/extension/core.js",
- "js&css/extension/functions.js",
- "js&css/extension/www.youtube.com/night-mode/night-mode.js",
- "js&css/extension/www.youtube.com/general/general.js",
- "js&css/extension/www.youtube.com/appearance/sidebar/sidebar.js",
- "js&css/extension/www.youtube.com/appearance/comments/comments.js",
- "js&css/extension/init.js"
- ],
- "matches": ["https://www.youtube.com/*"],
- "run_at": "document_start"
- }
- ],
- "host_permissions": ["https://www.youtube.com/*"],
- "optional_permissions": ["downloads"],
- "permissions": ["contextMenus", "storage"],
- "web_accessible_resources": [
- {
- "resources": [
- "menu/index.html",
- "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/player.js",
- "js&css/web-accessible/www.youtube.com/themes.js",
- "js&css/web-accessible/www.youtube.com/playlist.js",
- "js&css/web-accessible/www.youtube.com/playlist-complete-playlist.js",
- "js&css/web-accessible/www.youtube.com/playlist-cleaner.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/www.youtube.com/last-watched-overlay.js",
- "js&css/web-accessible/init.js",
- "menu/icons/48.png"
- ],
- "matches": ["https://www.youtube.com/*"]
- }
- ]
-}
+ "action": {
+ "default_area": "navbar",
+ "default_popup": "menu/index.html"
+ },
+ "background": {
+ "service_worker": "background.js"
+ },
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "{3c6bf0cc-3ae2-42fb-9993-0d33104fdcaf}"
+ }
+ },
+ "content_scripts": [
+ {
+ "all_frames": true,
+ "css": [
+ "js&css/extension/www.youtube.com/styles.css",
+ "js&css/extension/www.youtube.com/night-mode/night-mode.css",
+ "js&css/extension/www.youtube.com/general/general.css",
+ "js&css/extension/www.youtube.com/appearance/header/header.css",
+ "js&css/extension/www.youtube.com/appearance/player/player.css",
+ "js&css/extension/www.youtube.com/appearance/details/details.css",
+ "js&css/extension/www.youtube.com/appearance/sidebar/sidebar.css",
+ "js&css/extension/www.youtube.com/appearance/comments/comments.css"
+ ],
+ "exclude_matches": [
+ "https://www.youtube.com/audiolibrary/*",
+ "https://www.youtube.com/tv*"
+ ],
+ "js": [
+ "js&css/extension/core.js",
+ "js&css/extension/functions.js",
+ "js&css/extension/www.youtube.com/night-mode/night-mode.js",
+ "js&css/extension/www.youtube.com/general/general.js",
+ "js&css/extension/www.youtube.com/appearance/sidebar/sidebar.js",
+ "js&css/extension/www.youtube.com/appearance/comments/comments.js",
+ "js&css/extension/init.js"
+ ],
+ "matches": [
+ "https://www.youtube.com/*"
+ ],
+ "run_at": "document_start"
+ }
+ ],
+ "default_locale": "en",
+ "description": "__MSG_description_ext__",
+ "host_permissions": [
+ "https://www.youtube.com/*"
+ ],
+ "icons": {
+ "128": "menu/icons/128.png",
+ "16": "menu/icons/16.png",
+ "32": "menu/icons/32.png",
+ "48": "menu/icons/48.png"
+ },
+ "manifest_version": 3,
+ "name": "'Improve YouTube!' \u00f0\u0178\u017d\u00a7 (for YouTube & Videos)",
+ "optional_permissions": [
+ "downloads"
+ ],
+ "options_page": "menu/index.html",
+ "options_ui": {
+ "page": "menu/index.html"
+ },
+ "permissions": [
+ "contextMenus",
+ "storage"
+ ],
+ "short_name": "ImprovedTube",
+ "version": "4",
+ "web_accessible_resources": [
+ {
+ "matches": [
+ "https://www.youtube.com/*"
+ ],
+ "resources": [
+ "menu/index.html",
+ "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/player.js",
+ "js&css/web-accessible/www.youtube.com/themes.js",
+ "js&css/web-accessible/www.youtube.com/playlist.js",
+ "js&css/web-accessible/www.youtube.com/playlist-complete-playlist.js",
+ "js&css/web-accessible/www.youtube.com/playlist-cleaner.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/www.youtube.com/last-watched-overlay.js",
+ "js&css/web-accessible/init.js",
+ "menu/icons/48.png"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/menu/index.html b/menu/index.html
index 6a3ef371f..8a2f317d8 100644
--- a/menu/index.html
+++ b/menu/index.html
@@ -4,6 +4,7 @@
+
diff --git a/menu/skeleton-parts/appearance.js b/menu/skeleton-parts/appearance.js
index e08ddf30e..12b84bd8e 100644
--- a/menu/skeleton-parts/appearance.js
+++ b/menu/skeleton-parts/appearance.js
@@ -428,11 +428,9 @@ extension.skeleton.main.layers.section.appearance.on.click.player = {
component: "switch",
text: "hideTopLoadingBar",
tags: "remove,hide"
- },
+ }
}
}
-
-
};
/*--------------------------------------------------------------
diff --git a/menu/skeleton-parts/player.js b/menu/skeleton-parts/player.js
index f6e928231..56410d824 100644
--- a/menu/skeleton-parts/player.js
+++ b/menu/skeleton-parts/player.js
@@ -73,6 +73,14 @@ extension.skeleton.main.layers.section.player.on.click = {
}
}
},
+ /* DISABLE/ENABLE HOLD TO PLAY 2X UI */
+ disable_hold_to_play_2x: {
+ component: 'switch',
+ text: 'disableHoldToPlay2x', // YOU CAN CHANGE IF YOU SEE FIT
+ storage: 'disable_hold_to_play_2x',
+ value: false, // STAYS FALSE UNLESS TOGGLED
+ },
+ /* END OF DISABLE/ENABLE HOLD TO PLAY 2X UI */
pause_while_typing_on_youtube: {
component: 'switch',
text: 'pauseWhileIAmTypingOnYouTube',
From d3316fd64f5df1ada77d702d1a6d87ffa1fdddf0 Mon Sep 17 00:00:00 2001
From: ImprovedTube
Date: Wed, 8 Oct 2025 17:30:03 +0200
Subject: [PATCH 2/3] Update player.js
---
menu/skeleton-parts/player.js | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/menu/skeleton-parts/player.js b/menu/skeleton-parts/player.js
index 56410d824..1b492d54d 100644
--- a/menu/skeleton-parts/player.js
+++ b/menu/skeleton-parts/player.js
@@ -73,14 +73,6 @@ extension.skeleton.main.layers.section.player.on.click = {
}
}
},
- /* DISABLE/ENABLE HOLD TO PLAY 2X UI */
- disable_hold_to_play_2x: {
- component: 'switch',
- text: 'disableHoldToPlay2x', // YOU CAN CHANGE IF YOU SEE FIT
- storage: 'disable_hold_to_play_2x',
- value: false, // STAYS FALSE UNLESS TOGGLED
- },
- /* END OF DISABLE/ENABLE HOLD TO PLAY 2X UI */
pause_while_typing_on_youtube: {
component: 'switch',
text: 'pauseWhileIAmTypingOnYouTube',
@@ -846,6 +838,11 @@ extension.skeleton.main.layers.section.player.on.click = {
component: 'switch',
text: 'customMiniPlayer'
},
+ disable_hold_to_play_2x: {
+ component: 'switch',
+ text: 'disableHoldToPlay2x',
+ value: false,
+ },
forced_play_video_from_the_beginning: {
component: 'switch',
text: 'forcedPlayVideoFromTheBeginning'
From 6201c58f28a6636be4f53c446af6f5811895c36e Mon Sep 17 00:00:00 2001
From: ImprovedTube
Date: Wed, 8 Oct 2025 18:29:46 +0200
Subject: [PATCH 3/3] Update index.html
---
menu/index.html | 1 -
1 file changed, 1 deletion(-)
diff --git a/menu/index.html b/menu/index.html
index 8a2f317d8..6a3ef371f 100644
--- a/menu/index.html
+++ b/menu/index.html
@@ -4,7 +4,6 @@
-