// ==UserScript== // @name Youtube Music Mod // @namespace https://greasyfork.org // @version 0.8 // @description Removes the annoying video player on youtube music, adds a screensaver feature, modifies the colors and adds fade colors too // @author Red & one other person // @match https://music.youtube.com/watch* // @match https://music.youtube.com/* // @icon https://music.youtube.com/favicon.ico // @grant GM_setValue // @grant GM_getValue // @downloadURL https://update.greasyfork.icu/scripts/463278/Youtube%20Music%20Mod.user.js // @updateURL https://update.greasyfork.icu/scripts/463278/Youtube%20Music%20Mod.meta.js // ==/UserScript== let watchModActive = false; let watchModSleepTime = GM_getValue("watchModSleepTime", 6000); let watchModSleepStart = 0; let watchModClicks = GM_getValue("watchModClicks", 3); let fadeModSleepTime = GM_getValue("fadehModSleepTime", 1000);; let fadeModSleepStart = 0; let backgroundColor = GM_getValue("backgroundColor", '#300606') let fadeColor = GM_getValue("fadeColor", '#000000') let textColor = GM_getValue("textColor", '#ffffff') let fadeTransition = GM_getValue("fadeTransition", 'background-color .3s ease') let fadeShadowTransition = GM_getValue("fadeShadowTransition", 'box-shadow .3s ease') let configOpen = false; let doneNonWatchStyles = false; let doneWatchStyles = false; let previewRotation = false; function doNonWatchStyles(initial=false, bg) { bg = bg ? bg : backgroundColor if (doneNonWatchStyles) return; const element_list_background = document.querySelector("ytmusic-section-list-renderer"); element_list_background.style.backgroundColor = bg; if (initial) addFade(element_list_background); doneNonWatchStyles = true; } function doWatchStyles(initial=false, bg) { bg = bg ? bg : backgroundColor if (doneWatchStyles) return; let element_favorites = document.getElementById("items"); if (element_favorites != null){ element_favorites.remove(); } doneWatchStyles = true; } function reset_watchModSleepStart(additionalTime = 0) { if (typeof additionalTime !== 'number' || isNaN(additionalTime)) additionalTime = 0; watchModSleepStart = Date.now() + additionalTime; fadeModSleepStart = Date.now() + additionalTime; } function updateWatchElement() { let watchElement = document.querySelector(".watch-element"); let contentInfo = document.querySelector(".content-info-wrapper.ytmusic-player-bar"); if (!watchElement) return; let clickCount = parseInt(watchElement.getAttribute('data-click-count'), 10); clickCount = isNaN(clickCount) ? 0 : clickCount; if (clickCount >= watchModClicks) return; if (!contentInfo) { setTimeout(updateWatchElement, 100); return; } watchElement.children[0].innerHTML = contentInfo.children[0].innerHTML; setTimeout(updateWatchElement, 5000); } function checkWatchElement() { let watchElement = document.querySelector(".watch-element"); if (!watchElement) return; let currentTime = Date.now(); let timeElapsed = currentTime - watchModSleepStart; if (timeElapsed >= watchModSleepTime) { watchElement.style.zIndex = 5; watchElement.style.opacity = '1'; watchElement.setAttribute('data-click-count', '0'); movePreviewToWatch(); setTimeout(updateWatchElement, 100) } else { setTimeout(checkWatchElement, 100); } } function checkFade() { let currentTime = Date.now(); let timeElapsed = currentTime - fadeModSleepStart; const element_navBar = document.querySelector("ytmusic-nav-bar"); current_bg = element_navBar.style.backgroundColor if (timeElapsed >= fadeModSleepTime) { if (current_bg !== fadeColor) { doneWatchStyles = false; doneNonWatchStyles = false; run(false, fadeColor, backgroundColor) } setTimeout(checkFade, 50); } else { if (current_bg !== backgroundColor) { doneWatchStyles = false; doneNonWatchStyles = false; run(false, backgroundColor, fadeColor) } setTimeout(checkFade, 50); } } function fullscreen_div() { let fullscreen = document.createElement('div'); fullscreen.className = 'watch-element'; fullscreen.style.position = 'absolute'; fullscreen.style.top = '0'; fullscreen.style.left = '0'; fullscreen.style.width = '100%'; fullscreen.style.height = '100%'; fullscreen.style.alignItems = 'center'; fullscreen.style.justifyContent = 'center'; fullscreen.style.userSelect = 'none'; fullscreen.style.display = 'flex'; fullscreen.style.flexDirection = 'column'; return fullscreen } function addWatch() { console.log('Adding watch mod...'); watchModActive = true; setTimeout(doWatchStyles(), 100); let watchElement = fullscreen_div(); let watchText = document.createElement("p"); let gearIcon = makeGearIcon(); watchElement.style.backgroundColor = 'black'; // Automatically set / reset to 0 depending on state // watchElement.style.zIndex = 5; watchElement.style.opacity = 0; watchElement.style.transition = 'opacity 1s ease'; watchText.style.color = "#202020"; watchText.style.fontSize = 'xx-large'; gearIcon.style.position = 'absolute'; gearIcon.style.top = "0"; gearIcon.style.right = "0"; gearIcon.style.opacity = 0.2; watchElement.appendChild(watchText) watchElement.appendChild(gearIcon); document.body.appendChild(watchElement); reset_watchModSleepStart(2000); // account for youtube music load time here setTimeout(checkWatchElement, 2000); watchElement.addEventListener('click', (event) => { let clickCount = parseInt(watchElement.getAttribute('data-click-count'), 10); clickCount = isNaN(clickCount) ? 0 : clickCount; clickCount++; watchElement.setAttribute('data-click-count', clickCount.toString()); if (clickCount < watchModClicks) { watchElement.children[0].innerHTML = `Press ${watchModClicks - clickCount} times to exit to YouTube Music UI`; event.stopPropagation(); } else if (clickCount === watchModClicks) { watchElement.children[0].innerHTML = ''; watchElement.style.opacity = 0; reset_watchModSleepStart(); setTimeout(() => { watchElement.style.zIndex = 0; }, 1000) setTimeout(checkWatchElement, 1000); movePreviewFromWatch(); } else { reset_watchModSleepStart(); } }); }; function removeWatch() { console.log('Removing watch mod...'); watchModActive = false; let watchElement = document.querySelector(".watch-element"); if (!watchElement) return; watchElement.remove(); setTimeout(doNonWatchStyles(), 100); } function checkWatch() { if (window.location.pathname.endsWith('watch')) { switch (watchModActive) { case true: break; case false: addWatch(); break; } return true; } else { switch (watchModActive) { case false: break; case true: removeWatch(); break; } return false; } } function updatePreview() { const musicPreviewImage = document.querySelector("#music-preview-image"); if (!musicPreviewImage) {return;} // update the image const image = document.querySelector(".image.style-scope.ytmusic-player-bar"); musicPreviewImage.src = image.src; } function movePreviewToWatch() { const musicPreview = document.querySelector("#music-preview"); const watchElement = document.querySelector(".watch-element"); watchElement.appendChild(musicPreview); musicPreview.style.width = '10vh'; musicPreview.style.position = 'absolute'; musicPreview.style.margin = '0 0 50vh'; musicPreview.style.opacity = '.5'; } function movePreviewFromWatch() { const musicPreview = document.querySelector("#music-preview"); const element_guide_sections = document.querySelector("#sections"); element_guide_sections.appendChild(musicPreview); musicPreview.style.width = '50%'; musicPreview.style.position = ''; musicPreview.style.margin = '25%'; musicPreview.style.marginTop = 'auto'; musicPreview.style.opacity = ''; } function updatePreviewRotation() { const musicPreviewImage = document.querySelector("#music-preview-image"); if (!musicPreviewImage) {return;} previewRotation = !previewRotation; if (previewRotation){ // reversed musicPreviewImage.style.transition = 'transform 5s ease' musicPreviewImage.style.transform = `rotateZ(${360}deg)` } else { musicPreviewImage.style.transition = '' musicPreviewImage.style.transform = `rotateZ(${0}deg)` setTimeout(updatePreviewRotation, 100); } } function setPreviewShadow(bg, musicPreview=undefined) { musicPreview = musicPreview ? musicPreview : document.querySelector("#music-preview"); if (!musicPreview) {return;} musicPreview.style.boxShadow = `0 0 10px ${bg}` } function addPreview(bg) { console.log('Adding spinning disk'); const renderer = document.querySelector(".ytmusic-guide-section-renderer"); if (!renderer) { setTimeout(() => addPreview(bg), 200); return; } // remove youtube junk const element_guide_sections = document.querySelector("#sections"); const elementsToRemove = element_guide_sections.querySelectorAll('.ytmusic-guide-renderer'); elementsToRemove.forEach(element => { element.remove(); }); // make music preview let musicPreview = document.createElement('div'); let musicPreviewImage = document.createElement('img'); musicPreviewImage.alt = "loading mod..."; musicPreviewImage.style.width = "100%" musicPreviewImage.style.height = "100%" musicPreviewImage.style.borderRadius = '50%'; musicPreviewImage.style.objectFit = 'cover'; musicPreviewImage.style.zIndex = '6'; musicPreviewImage.style.display = 'flex'; musicPreviewImage.style.placeItems = 'center' musicPreviewImage.style.justifyContent = 'center' musicPreviewImage.id = "music-preview-image" musicPreview.id = "music-preview" musicPreview.style.display = 'flex'; musicPreview.style.width = '50%'; musicPreview.style.aspectRatio = '1/1'; musicPreview.style.margin = '25%'; musicPreview.style.marginTop = 'auto'; musicPreview.style.borderRadius = '50%'; addFadeShadow(musicPreview); setPreviewShadow(bg, musicPreview); musicPreview.appendChild(musicPreviewImage); element_guide_sections.appendChild(musicPreview); setInterval(updatePreview, 5000); setInterval(updatePreviewRotation, 5000); console.log('Added spinning disk'); } function run(initial=false, bg=undefined, reverse_bg=undefined) { bg = bg ? bg : backgroundColor reverse_bg = reverse_bg ? reverse_bg : fadeColor; if (initial){ const elementToObserve = document.querySelector("#main-panel"); const observer = new MutationObserver(function() { elementToObserve.remove(); }); observer.observe(elementToObserve, {subtree: true, childList: true}); } const element_sideBar = document.querySelector("#contents"); element_sideBar.style.width = "100%"; element_sideBar.style.margin = "0px"; element_sideBar.style.maxWidth = "none"; element_sideBar.style.backgroundColor = bg if (initial) addFade(element_sideBar); const element_sidePanel = document.querySelector("#side-panel"); element_sidePanel.style.width = "100%"; element_sideBar.style.margin = "0px"; element_sidePanel.style.padding = "0px"; element_sidePanel.style.maxWidth = "none"; const element_top_background = document.querySelector("#nav-bar-background"); element_top_background.style.backgroundColor = bg if (initial) addFade(element_top_background); const element_bottom_background = document.querySelector("#player-bar-background"); element_bottom_background.style.backgroundColor = bg if (initial) addFade(element_bottom_background); const element_navBar = document.querySelector("ytmusic-nav-bar"); element_navBar.style.backgroundColor = bg; if (initial) addFade(element_navBar); const element_player_background = document.querySelector("#player-page"); element_player_background.style.backgroundColor = bg; if (initial) addFade(element_player_background); const element_guide_background = document.querySelector("#guide-renderer"); element_guide_background.style.backgroundColor = bg; if (initial) addFade(element_guide_background); const element_bottomBar = document.querySelector('ytmusic-player-bar'); element_bottomBar.style.backgroundColor = bg if (initial) addFade(element_bottomBar); const element_musicList = document.querySelector('ytmusic-tab-renderer'); element_musicList.addEventListener("scroll", reset_watchModSleepStart); //const element_sidePanel = document.querySelectorAll(".content.style-scope.ytmusic-player-page"); //element_sidePanel.style.width = "100%"; //element_sidePanel.style.padding = "0px"; if (initial) { addPreview(reverse_bg); } else { setPreviewShadow(reverse_bg); } const watch = checkWatch(); if (watch) { doWatchStyles(initial, bg); } else { doNonWatchStyles(initial, bg); } if (initial) { addConfig(element_navBar); checkFade(); } } function makeGearIcon() { let gearIcon = document.createElement('a'); gearIcon.innerHTML = ` ` gearIcon.style.display = "flex"; gearIcon.style.alignItems = "center"; gearIcon.children[0].style.backgroundColor = "#ffffff10"; gearIcon.children[0].style.borderRadius = "50px"; gearIcon.children[0].style.marginLeft = "10px"; gearIcon.children[0].style.marginRight = "10px"; gearIcon.addEventListener("click", open_config); addHover(gearIcon); return gearIcon } function addConfig(navElement) { let navCenter = navElement.querySelector('.center-content'); let gearIcon = makeGearIcon(); gearIcon.innerHTML = gearIcon.innerHTML+"YouTube Music mod"; navCenter.appendChild(gearIcon); } function open_config(event) { if (typeof event === "object") { event.stopPropagation(); } if (configOpen) { document.getElementById("confcon").remove(); document.querySelector("ytmusic-app-layout").style.display = ""; configOpen = false; return; } else { configOpen = true;} document.documentElement.scrollTop = 0; document.body.scrollTop = 0; document.querySelector("ytmusic-app-layout").style.display = "none"; let configContainer = fullscreen_div(); let configElement = document.createElement('div'); configContainer.style.zIndex = 6; configContainer.style.backgroundColor = "black"; configContainer.id = "confcon"; configElement.style.width = "500px" configElement.style.maxWidth = "90%"; configElement.style.height = "500px" configElement.id = "confelem"; configElement.style.outline = "1px solid white"; configElement.style.border = "1px solid black"; configElement.style.backgroundColor = backgroundColor; configElement.style.padding = "10px"; addTextAlign(configElement, "h1", "YouTube Music Mod Configuration", "center") let gearIcon = makeGearIcon(); gearIcon.style.position = 'absolute'; gearIcon.style.top = "0"; gearIcon.style.right = "0"; addColorConfig(configElement, "Background color", "backgroundColor", backgroundColor, (value) => { backgroundColor = value; }); addColorConfig(configElement, "Fade color", "fadeColor", fadeColor, (value) => { fadeColor = value; }); addNumberConfig(configElement, "Miliseconds before fade", "fadeModSleepTime", fadeModSleepTime, (value) => { fadeModSleepTime = value; }); addNumberConfig(configElement, "Miliseconds before screensaver", "watchModSleepTime", watchModSleepTime, (value) => { watchModSleepTime = value; }); addNumberConfig(configElement, "Screensaver clicks required", "watchModClicks", watchModClicks, (value) => { watchModClicks = value; }); addTextConfig(configElement, "Fade transition css", "fadeTransition", fadeTransition, (value) => { fadeTransition = value; addFade(); }); addTextConfig(configElement, "Shadow fade transition css", "fadeShadowTransition", fadeShadowTransition, (value) => { fadeShadowTransition = value; addFadeShadow(); }); configContainer.appendChild(gearIcon); configContainer.appendChild(configElement); document.body.appendChild(configContainer); } function addText(configElement, elementName, text) { let textElement = document.createElement(elementName); textElement.innerHTML = text; configElement.appendChild(textElement); return textElement; } function addTextAlign(configElement, elementName, text, align) { let textElement = addText(configElement, elementName, text); textElement.style.textAlign = align; textElement.style.color = textColor; return textElement; } function addInputConfig(configElement, text, key, value, ch) { let inputContainer = document.createElement('div'); let textElement = document.createElement('h2'); let inputElement = document.createElement('input'); inputElement.value = value; inputElement.style.flexGrow = "1"; inputElement.addEventListener("change", (e) => { const result = parseInt(e.target.value); const convertedValue = isNaN(result) ? e.target.value : result; ch(convertedValue); GM_setValue(key, convertedValue); open_config(); open_config(); doneWatchStyles = false; doneNonWatchStyles = false; run(); }) textElement.innerHTML = text; inputElement.style.backgroundColor = backgroundColor; inputElement.style.border = '1px dashed white'; inputElement.style.borderRadius = "50px"; inputElement.style.outline = "none"; inputElement.style.padding = "5px 15px"; textElement.style.color = textColor; inputElement.style.color = textColor; textElement.style.flexGrow = "1"; inputContainer.style.display = "flex"; inputContainer.style.width = "100%"; inputContainer.appendChild(textElement); inputContainer.appendChild(inputElement); configElement.appendChild(inputContainer); return inputElement; } function addColorConfig(configElement, text, key, value, ch) { let colorElement = addInputConfig(configElement, text, key, value, ch); colorElement.type = 'color'; colorElement.style.outline = "1px solid black"; colorElement.style.border = "1px solid white"; return colorElement; } function addNumberConfig(configElement, text, key, value, ch) { let numberElement = addInputConfig(configElement, text, key, value, ch); numberElement.type = 'number'; return numberElement; } function addTextConfig(configElement, text, key, value, ch) { let textElement = addInputConfig(configElement, text, key, value, ch); textElement.type = 'text'; return textElement; } function addHover(myLink) { myLink.addEventListener('mouseover', function() { this.style.cursor = 'pointer'; }); myLink.addEventListener('mouseout', function() { this.style.cursor = 'auto'; }); } function addFade(element) { if (element){ element.style.transition = fadeTransition; element.classList.add('added-fade'); } else { const allElements = document.querySelectorAll('.added-fade'); allElements.forEach((el) => { el.style.transition = fadeTransition; }); } } function addFadeShadow(element) { if (element){ element.style.transition = fadeShadowTransition; element.classList.add('added-fade-shadow'); } else { const allElements = document.querySelectorAll('.added-fade-shadow'); allElements.forEach((el) => { el.style.transition = fadeShadowTransition; }); } } if (window.trustedTypes && window.trustedTypes.createPolicy) { window.trustedTypes.createPolicy('default', { createHTML: string => string, createScriptURL: string => string, createScript: string => string, }); } setTimeout(function () { setInterval(checkWatch, 500); document.addEventListener("pointerdown", reset_watchModSleepStart); document.addEventListener("click", reset_watchModSleepStart); document.addEventListener("mousemove", reset_watchModSleepStart); run(true); }, 100);