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

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Greasemonkey lub Violentmonkey.

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Violentmonkey.

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Violentmonkey.

Aby zainstalować ten skrypt, wymagana będzie instalacja rozszerzenia Tampermonkey lub Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

Aby zainstalować ten skrypt, musisz zainstalować rozszerzenie menedżera skryptów użytkownika.

(Mam już menedżera skryptów użytkownika, pozwól mi to zainstalować!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

Będziesz musiał zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

Będziesz musiał zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

Musisz zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

(Mam już menedżera stylów użytkownika, pozwól mi to zainstalować!)

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