NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @namespace https://openuserjs.org/users/thecyberd3m0n
// @name Youtube TV in browser / Youtube Leaning
// @description Enjoy fully-fledged Youtube TV in browser. Script mocks User Agent (to Xbox X)
// and sets some config flags to enable chat or animations. Ads were not disabled
// ads some CSS to not display ugly desktop scrollbars. App can be controlled
// from iOS/Android client, just like in consoles or smart TV's.
// It's fully pairable with fully working Google Cast features.
// @copyright 2024, thecyberd3m0n (https://openuserjs.org/users/thecyberd3m0n)
// @license MIT
// @version 0.0.1
// @include https://www.youtube.com/tv*
// @grant none
// ==/UserScript==
// ==OpenUserJS==
// @author thecyberd3m0n
// ==/OpenUserJS==
/**
*
* Please begin typing or paste your User script now.
*
* NOTE: It is still strongly recommended to use the Author Tools panel to
* add your `@updateURL` even if we are not in lockdown.
*
*/
(function () {
'use strict';
// Override the User-Agent property to not be redirected to youtube.com
Object.defineProperty(navigator, 'userAgent', {
get: function () {
return 'Mozilla/5.0 (Windows NT 10.0; Xbox; Xbox Series X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.0.0';
},
configurable: true
});
// Override the properties directly on the window object
Object.defineProperty(window, 'tectonicConfig', {
configurable: true,
enumerable: true,
writable: true,
value: window.tectonicConfig || {}
});
Object.defineProperty(window.tectonicConfig, 'featureSwitches', {
configurable: true,
enumerable: true,
writable: true,
value: window.tectonicConfig.featureSwitches || {}
});
// Override 'enableAnimations' to always return true and prevent setting to false
Object.defineProperty(window.tectonicConfig.featureSwitches, 'enableAnimations', {
get: function () {
return true; // Always return true
},
set: function () {
// Do nothing, prevent setting it to false or any other value
},
configurable: false // Prevent reconfiguring this property
});
// Override 'enableAmbientInterludes' to always return true and prevent setting to false
Object.defineProperty(window.tectonicConfig.featureSwitches, 'enableAmbientInterludes', {
get: function () {
return true; // Always return true
},
set: function () {
// Do nothing, prevent setting it to false or any other value
},
configurable: false // Prevent reconfiguring this property
});
// Override 'enableStartupSound' to always return true and prevent setting to false
Object.defineProperty(window.tectonicConfig.featureSwitches, 'enableStartupSound', {
get: function () {
return true; // Always return true
},
set: function () {
// Do nothing, prevent setting it to false or any other value
},
configurable: false // Prevent reconfiguring this property
});
// Override 'enableAndroidAttestation' to always return true and prevent setting to false
Object.defineProperty(window.tectonicConfig.featureSwitches, 'enableAndroidAttestation', {
get: function () {
return true; // Always return true
},
set: function () {
// Do nothing, prevent setting it to false or any other value
},
configurable: false // Prevent reconfiguring this property
});
// Override 'enableListAnimations' to always return true and prevent setting to false
Object.defineProperty(window.tectonicConfig.featureSwitches, 'enableListAnimations', {
get: function () {
return true; // Always return true
},
set: function () {
// Do nothing, prevent setting it to false or any other value
},
configurable: false // Prevent reconfiguring this property
});
// Override 'enableTouchSupport' to always return true and prevent setting to false
Object.defineProperty(window.tectonicConfig.featureSwitches, 'enableTouchSupport', {
get: function () {
return true; // Always return true
},
set: function () {
// Do nothing, prevent setting it to false or any other value
},
configurable: false // Prevent reconfiguring this property
});
Object.defineProperty(window.tectonicConfig.featureSwitches, 'isLimitedMemory', {
get: function () {
return false; // Always return true
},
set: function () {
// Do nothing, prevent setting it to false or any other value
},
configurable: false // Prevent reconfiguring this property
});
Object.defineProperty(window.tectonicConfig.featureSwitches, 'isServiceWorkerCapable', {
get: function () {
return true; // Always return true
},
set: function () {
// Do nothing, prevent setting it to false or any other value
},
configurable: false // Prevent reconfiguring this property
});
Object.defineProperty(window.tectonicConfig.featureSwitches, 'enableLightweightTimely', {
get: function () {
return false; // Always return true
},
set: function () {
// Do nothing, prevent setting it to false or any other value
},
configurable: false // Prevent reconfiguring this property
});
Object.defineProperty(window.tectonicConfig.featureSwitches, 'enableLiveChat', {
get: function () {
return true; // Always return true
},
set: function () {
// Do nothing, prevent setting it to false or any other value
},
configurable: false // Prevent reconfiguring this property
});
Object.defineProperty(window.tectonicConfig.featureSwitches, 'enablePageServiceCache', {
get: function () {
return true; // Always return true
},
set: function () {
// Do nothing, prevent setting it to false or any other value
},
configurable: false // Prevent reconfiguring this property
});
Object.defineProperty(window.tectonicConfig.featureSwitches, 'enableRoundedProgressBar', {
get: function () {
return true; // Always return true
},
set: function () {
// Do nothing, prevent setting it to false or any other value
},
configurable: false // Prevent reconfiguring this property
});
Object.defineProperty(window.tectonicConfig.featureSwitches, 'forceVoiceIncapable', {
get: function () {
return false; // Always return true
},
set: function () {
// Do nothing, prevent setting it to false or any other value
},
configurable: false // Prevent reconfiguring this property
});
Object.defineProperty(window.tectonicConfig.featureSwitches, 'forceVoiceEnabled', {
get: function () {
return true; // Always return true
},
set: function () {
// Do nothing, prevent setting it to false or any other value
},
configurable: false // Prevent reconfiguring this property
});
// Apply CSS to modify scrollbars to look darker, semi-transparent, and hide tracks
const style = document.createElement('style');
style.innerHTML = `
/* Mobile-like scrollbars with dark and semi-transparent appearance */
::-webkit-scrollbar {
width: 0px; /* Width of the scrollbar */
height: 0px; /* Height of horizontal scrollbar */
}
::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.6); /* Dark and semi-transparent thumb */
border-radius: 10px;
border: 0px solid rgba(255, 255, 255, 0.3); /* Adds a little space around the thumb */
}
::-webkit-scrollbar-thumb:hover {
background-color: rgba(0, 0, 0, 0.8); /* Darker color when hovered */
}
::-webkit-scrollbar-track {
background: transparent; /* Make the track invisible */
}
`;
document.head.appendChild(style);
})();