YouTube Vertical Toggle Videos/Comments

Toggle between "Videos" and "comments" sections on YouTube when screen width less than 1000px, is useful when on a Vertical Screen

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         YouTube Vertical Toggle Videos/Comments
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Toggle between "Videos" and "comments" sections on YouTube when screen width less than 1000px, is useful when on a Vertical Screen
// @author       Nate2898
// @match        *://*.youtube.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @license      MIT
// @grant        none
// @namespace    https://greatest.deepsurf.us/en/users/1083698
// @downloadURL
// @updateURL
// ==/UserScript==

(function() {
    'use strict';

    // Add CSS to only show the toggle button when screen is < 1000px
    const style = document.createElement('style');
    style.textContent = `
        #toggle-videos-comments-container { display: none !important; }
        @media (max-width: 1000px) {
            #toggle-videos-comments-container { display: flex !important; }
        }
    `;
    document.head.appendChild(style);

    // Keys for saving default preference
    const STATE_KEY = 'ytToggleState'; // stores last-used when user toggles main switch (optional)
    const DEFAULT_KEY = 'ytDefaultSection'; // stores user's chosen default: 'videos' or 'comments'

    // Initialize default if missing
    try {
        if (!localStorage.getItem(DEFAULT_KEY)) localStorage.setItem(DEFAULT_KEY, 'videos');
    } catch {}

    // Save the toggle state (videos or comments) when the main slider is used
    function saveState(isComments) {
        try {
            localStorage.setItem(STATE_KEY, isComments ? 'comments' : 'videos');
        } catch {}
    }

    // Load the previously saved toggle state
    function loadState() {
        try {
            return localStorage.getItem(STATE_KEY);
        } catch {
            return null;
        }
    }

    // Get/set default preferred section
    function getDefault() {
        try { return localStorage.getItem(DEFAULT_KEY) || 'videos'; } catch { return 'videos'; }
    }
    function setDefault(val) {
        try { localStorage.setItem(DEFAULT_KEY, val); } catch {}
    }

    // Show both videos and comments sections
    function showBoth() {
        ['#related', '#comments'].forEach(sel => {
            const el = document.querySelector(sel);
            if (el) el.style.display = '';
        });
    }

    // Apply the saved toggle state to show either comments or videos
    function applyState() {
        // Use the user's chosen default as the authoritative initial state.
        const state = getDefault();
        const videos = document.querySelector('#related');
        const comments = document.querySelector('#comments');
        const toggle = document.querySelector('#toggle-videos-comments-container input[type=checkbox].main-toggle');
        if (!videos || !comments || !toggle) return;
        const showComments = (state === 'comments');
        videos.style.display = showComments ? 'none' : '';
        comments.style.display = showComments ? '' : 'none';
        toggle.checked = showComments;
        toggle.dispatchEvent(new Event('change'));
    }

    // Create the toggle button UI and checkbox
    function createToggleButton() {
        if (document.querySelector('#toggle-videos-comments-container')) return;

        const container = document.createElement('div');
        container.id = 'toggle-videos-comments-container';
        Object.assign(container.style, {
            display: 'flex',
            flexDirection: 'row',
            alignItems: 'center',
            margin: '5px 0',
            justifyContent: 'center',
            gap: '10px'
        });

        // Add "Default" button to set preferred main section
        const defaultButton = document.createElement('button');
        defaultButton.type = 'button';
        defaultButton.title = 'Set default section to be displayed on page load and reload';
        Object.assign(defaultButton.style, {
            padding: '6px 10px',
            borderRadius: '6px',
            border: 'none',
            cursor: 'pointer',
            background: '#333',
            color: '#fff',
            fontSize: '13px'
        });
        // initialize label and visual state
        function updateDefaultButtonLabel() {
            const def = getDefault();
            defaultButton.textContent = 'Default: ' + (def === 'comments' ? 'Comments' : 'Videos');
            // visually indicate which default is active
            if (def === 'comments') {
                defaultButton.style.background = '#2196F3';
            } else {
                defaultButton.style.background = '#fc0703';
            }
        }
        defaultButton.addEventListener('click', () => {
            // toggle default (persist only). Do NOT immediately apply — user requested it apply on reload/new load only.
            const newDef = getDefault() === 'comments' ? 'videos' : 'comments';
            setDefault(newDef);
            updateDefaultButtonLabel();
        });

        // Add label text next to the toggle
        const label = document.createElement('div');
        label.textContent = 'Videos/Comments';
        Object.assign(label.style, {
            fontSize: '16px',
            fontWeight: 'bold',
            color: '#FFF'
        });

        // Create the toggle switch
        const sliderLabel = document.createElement('label');
        Object.assign(sliderLabel.style, {
            position: 'relative',
            display: 'inline-block',
            width: '60px',
            height: '20px'
        });

        const input = document.createElement('input');
        input.classList.add('main-toggle');
        input.type = 'checkbox';
        input.style.opacity = '0';
        input.style.width = '0';
        input.style.height = '0';
        input.addEventListener('change', () => {
            const videos = document.querySelector('#related');
            const comments = document.querySelector('#comments');
            if (!videos || !comments) return;
            if (input.checked) {
                videos.style.display = 'none';
                comments.style.display = '';
                saveState(true);
            } else {
                videos.style.display = '';
                comments.style.display = 'none';
                saveState(false);
            }
        });

        // Style the toggle track and thumb
        const track = document.createElement('span');
        Object.assign(track.style, {
            position: 'absolute',
            cursor: 'pointer',
            top: '0',
            left: '0',
            right: '0',
            bottom: '0',
            backgroundColor: '#fc0703', //Video slider color
            transition: '0.4s',
            borderRadius: '20px'
        });

        const thumb = document.createElement('span');
        Object.assign(thumb.style, {
            position: 'absolute',
            height: '15px',
            width: '15px',
            left: '4px',
            bottom: '3px',
            backgroundColor: '#FFF', // Slider dot color
            transition: '0.4s',
            borderRadius: '50%'
        });

        // Update appearance when toggle changes
        input.addEventListener('change', () => {
            if (input.checked) {
                track.style.backgroundColor = '#2196F3';  //Comments slider color
                thumb.style.transform = 'translateX(36px)';
            } else {
                track.style.backgroundColor = '#fc0703';  //Video slider color
                thumb.style.transform = 'translateX(0)';
            }
        });

        track.appendChild(thumb);
        sliderLabel.appendChild(input);
        sliderLabel.appendChild(track);

    // Append all elements to the container
    updateDefaultButtonLabel();
    container.appendChild(defaultButton);
    container.appendChild(label);
    container.appendChild(sliderLabel);

        // Insert the toggle below the main video content
        const above = document.querySelector('#above-the-fold');
        if (above) above.insertAdjacentElement('afterend', container);

    // Apply toggle state if small screen
    if (window.matchMedia('(max-width: 1000px)').matches) applyState();
    }

    // Observe for page changes and create toggle accordingly
    let currentUrl = location.href;
    const observer = new MutationObserver(() => {
        if (location.href !== currentUrl) {
            currentUrl = location.href;
            handleUrlChange();
        }
        createToggleButton();
    });

    // Clean up and reset when navigating
    function handleUrlChange() {
        const old = document.querySelector('#toggle-videos-comments-container');
        if (old) old.remove();
        showBoth();
        createToggleButton();
    }

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

    // Re-apply state when resizing below 1000px
    window.matchMedia('(max-width: 1000px)').addEventListener('change', e => {
        if (e.matches) applyState();
        else showBoth();
    });
})();