YouTube - Repositions the Volume button

Removes previous button, makes next button circular, and moves volume control after next button on YouTube

当前为 2025-07-26 提交的版本,查看 最新版本

// ==UserScript==
// @name         YouTube - Repositions the Volume button
// @namespace    Violentmonkey Scripts
// @version      1.0
// @description  Removes previous button, makes next button circular, and moves volume control after next button on YouTube
// @author       lainpilled
// @license      MIT
// @match        https://www.youtube.com/*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function () {
    'use strict';

    function alignPopover() {
        const volumeButton = document.querySelector('.ytp-volume-icon');
        const volumePopover = document.querySelector('.ytp-volume-popover');

        if (volumeButton && volumePopover) {
            const buttonRect = volumeButton.getBoundingClientRect();
            const containerRect = volumeButton.parentElement.getBoundingClientRect();

            // Calculate relative left offset within player controls
            const offsetLeft = buttonRect.left - containerRect.left + (volumeButton.offsetWidth / 2) - (volumePopover.offsetWidth / 2);
            volumePopover.style.left = `${offsetLeft}px`;
        }
    }

    function removePrevButton() {
        const prevButton = document.querySelector('.ytp-prev-button');
        if (prevButton) {
            prevButton.style.display = 'none';
        }
    }

    function makeNextButtonCircular() {
        const nextButton = document.querySelector('.ytp-next-button');
        if (nextButton) {
            // Make the button perfectly circular
            nextButton.style.borderRadius = '50%';
            nextButton.style.overflow = 'hidden';
            nextButton.style.width = '48px';
            nextButton.style.height = '48px';
            nextButton.style.display = 'flex';
            nextButton.style.alignItems = 'center';
            nextButton.style.justifyContent = 'center';
        }
    }

    function moveVolumeButton() {
        const volumeButton = document.querySelector('.ytp-volume-icon');
        const nextButton = document.querySelector('.ytp-next-button');
        const volumePopover = document.querySelector('.ytp-volume-popover');

        if (volumeButton && nextButton && volumePopover) {
            if (nextButton.nextSibling !== volumeButton) {
                nextButton.parentNode.insertBefore(volumeButton, nextButton.nextSibling);
                volumeButton.parentNode.insertBefore(volumePopover, volumeButton.nextSibling);

                const referenceButton = document.querySelector('.ytp-play-button') || nextButton;
                if (referenceButton) {
                    const computedStyle = window.getComputedStyle(referenceButton);
                    volumeButton.style.display = 'inline-flex';
                    volumeButton.style.alignItems = 'center';
                    volumeButton.style.justifyContent = 'center';
                    volumeButton.style.verticalAlign = computedStyle.verticalAlign || 'middle';
                    volumeButton.style.lineHeight = computedStyle.lineHeight || 'normal';
                }
            }

            volumeButton.addEventListener('mouseenter', alignPopover);
            volumeButton.addEventListener('click', alignPopover);

            const observer = new MutationObserver(alignPopover);
            observer.observe(volumePopover, {
                attributes: true,
                attributeFilter: ['style']
            });

        } else {
            setTimeout(moveVolumeButton, 500);
        }
    }

    function initializeScript() {
        removePrevButton();
        makeNextButtonCircular();
        moveVolumeButton();

        const observer = new MutationObserver(() => {
            removePrevButton();
            makeNextButtonCircular();
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }

    setTimeout(initializeScript, 1000);
})();