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); })();