YouTube - Repositions the Volume button

Moves volume control after next button on YouTube and removes previous button

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

(function () {
    'use strict';

    let mainObserver;
    let volumeObserver;
    let retryCount = 0;
    const MAX_RETRIES = 20;

    const elements = {
        volumeButton: null,
        nextButton: null,
        volumePopover: null,
        prevButton: null
    };

    function updateElementCache() {
        elements.volumeButton = document.querySelector('.ytp-volume-icon');
        elements.nextButton = document.querySelector('.ytp-next-button');
        elements.volumePopover = document.querySelector('.ytp-volume-popover');
        elements.prevButton = document.querySelector('.ytp-prev-button');
    }

    function alignPopover() {
        if (!elements.volumeButton || !elements.volumePopover) return;

        const buttonRect = elements.volumeButton.getBoundingClientRect();
        const containerRect = elements.volumeButton.parentElement.getBoundingClientRect();

        const offsetLeft = buttonRect.left - containerRect.left +
                          (elements.volumeButton.offsetWidth / 2) -
                          (elements.volumePopover.offsetWidth / 2);
        elements.volumePopover.style.left = `${offsetLeft}px`;
    }

    function removePrevButton() {
        if (elements.prevButton) {
            elements.prevButton.style.display = 'none';
        }
    }

    function makeNextButtonCircular() {
        if (!elements.nextButton) return;

        Object.assign(elements.nextButton.style, {
            borderRadius: '50%',
            overflow: 'hidden',
            width: '48px',
            height: '48px',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center'
        });
    }

    function moveVolumeButton() {
        updateElementCache();

        if (!elements.volumeButton || !elements.nextButton || !elements.volumePopover) {
            if (retryCount < MAX_RETRIES) {
                retryCount++;
                setTimeout(moveVolumeButton, 500);
            }
            return;
        }

        retryCount = 0;

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

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

        elements.volumeButton.removeEventListener('mouseenter', alignPopover);
        elements.volumeButton.removeEventListener('click', alignPopover);

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

        if (volumeObserver) {
            volumeObserver.disconnect();
        }

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

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

        if (mainObserver) {
            mainObserver.disconnect();
        }

        mainObserver = new MutationObserver(() => {
            updateElementCache();
            removePrevButton();
            makeNextButtonCircular();
        });

        const playerContainer = document.querySelector('#movie_player') || document.body;
        mainObserver.observe(playerContainer, {
            childList: true,
            subtree: true
        });
    }

    let lastUrl = location.href;
    new MutationObserver(() => {
        const url = location.href;
        if (url !== lastUrl) {
            lastUrl = url;
            setTimeout(initializeScript, 1000);
        }
    }).observe(document, { subtree: true, childList: true });

    setTimeout(initializeScript, 1000);

    window.addEventListener('beforeunload', () => {
        if (mainObserver) mainObserver.disconnect();
        if (volumeObserver) volumeObserver.disconnect();
    });
})();