Dreaming Spanish - Widescreen Layout

Makes the video player fill the available space for both YouTube and Shaka players, requests 1080p quality for YouTube, with toggles to hide/show sidebars, and automatically clicks the 'Not now' button on popups, ensuring playback resumes.

// ==UserScript==
// @name         Dreaming Spanish - Widescreen Layout
// @namespace    http://tampermonkey.net/
// @version      1.7
// @description  Makes the video player fill the available space for both YouTube and Shaka players, requests 1080p quality for YouTube, with toggles to hide/show sidebars, and automatically clicks the 'Not now' button on popups, ensuring playback resumes.
// @author       OthorWight & Gemini
// @match        https://www.dreamingspanish.com/*
// @grant        GM_addStyle
// @run-at       document-end
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const MASTER_TOGGLE_ID = 'ds-widescreen-master-toggle';
    const MASTER_ENABLED_KEY = 'dsWidescreenEnabled';
    const MASTER_ENABLED_CLASS = 'ds-widescreen-active';

    const STYLE_ID = 'ds-widescreen-features-styles-987';
    const LEFT_SIDEBAR_HIDDEN_CLASS = 'ds-widescreen-left-hidden';
    const RIGHT_SIDEBAR_HIDDEN_CLASS = 'ds-widescreen-right-hidden';

    let lastUrl = location.href;

    function isMasterEnabled() {
        return localStorage.getItem(MASTER_ENABLED_KEY) !== 'false';
    }

    function waitForElement(selector, conditionFn = (el) => true) {
        return new Promise(resolve => {
            const element = document.querySelector(selector);
            if (element && conditionFn(element)) {
                return resolve(element);
            }
            const observer = new MutationObserver(() => {
                const targetElement = document.querySelector(selector);
                if (targetElement && conditionFn(targetElement)) {
                    observer.disconnect();
                    resolve(targetElement);
                }
            });
            observer.observe(document.body, { childList: true, subtree: true });
        });
    }

    function setHighQuality(iframe) {
        // This function specifically targets YouTube iframes
        if (!iframe || !iframe.src || !iframe.src.includes('youtube.com')) return;

        let src = iframe.src;
        if (!src.includes('vq=hd1080')) {
            iframe.src = src + (src.includes('?') ? '&' : '?') + 'vq=hd1080';
            console.log("DS Widescreen Script: Requested 1080p quality for YouTube player.");
        }
    }

    function addFeatures() {
        if (document.getElementById(STYLE_ID)) return;
        console.log("DS Widescreen Script: Applying features to watch page.");

        GM_addStyle(`
            /* Main layout adjustments */
            body.${MASTER_ENABLED_CLASS} .ds-page.ds-watch-page { max-width: 100% !important; margin: 0 auto; padding: 0px !important; }
            body.${MASTER_ENABLED_CLASS} .ds-watch-page__sections { gap: 0rem !important; }
            body.${MASTER_ENABLED_CLASS} .ds-video-section { flex: 1 1 auto; min-width: 500px; gap: 0rem !important; }
            body.${MASTER_ENABLED_CLASS} .ds-playlist-section, body.ds-widescreen-active .ds-sidebar-area, body.ds-widescreen-active .ds-content-area { transition: all 0.3s ease-in-out; }
            body.${MASTER_ENABLED_CLASS} .ds-playlist-section { flex: 0 0 340px; overflow: hidden; }

            /* New Shaka Player Support */
            body.${MASTER_ENABLED_CLASS} .ds-video-section__embed,
            body.${MASTER_ENABLED_CLASS} .embed-responsive,
            body.${MASTER_ENABLED_CLASS} .ds-shaka-player {
                height: 100% !important;
                width: 100% !important;
            }

            /* Sidebar toggle buttons */
            #ds-toggle-left-sidebar, #ds-toggle-right-playlist { position: fixed; top: 50%; transform: translateY(-50%); width: 30px; height: 30px; background-color: #ff9301; color: #000000; display: flex; align-items: center; justify-content: center; font-size: 18px; font-weight: bold; font-family: monospace; cursor: pointer; z-index: 9999; transition: all 0.3s ease-in-out; user-select: none; border: 2px solid #000000; border-radius: 50%; }
            #ds-toggle-left-sidebar:hover, #ds-toggle-right-playlist:hover { background-color: #ef8301; box-shadow: 0px 0px 8px rgba(0,0,0,0.3); }
            #ds-toggle-left-sidebar::after, #ds-toggle-right-playlist::after { content: 'Hide'; position: absolute; bottom: 120%; left: 50%; transform: translateX(-50%); background-color: #222; color: #fff; padding: 4px 8px; border-radius: 4px; font-size: 12px; font-family: sans-serif; white-space: nowrap; opacity: 0; visibility: hidden; transition: opacity 0.2s, visibility 0.2s; pointer-events: none; }
            #ds-toggle-left-sidebar:hover::after, #ds-toggle-right-playlist:hover::after { opacity: 1; visibility: visible; }
            #ds-toggle-left-sidebar { left: calc(var(--sidebar-width, 256px) - 40px); }
            #ds-toggle-left-sidebar::before { content: '<<'; }
            #ds-toggle-right-playlist { right: calc(340px - 40px); }
            #ds-toggle-right-playlist::before { content: '>>'; }

            /* Hidden states for sidebars */
            body.${LEFT_SIDEBAR_HIDDEN_CLASS} .ds-sidebar-area { transform: translateX(-100%); }
            body.${LEFT_SIDEBAR_HIDDEN_CLASS} .ds-content-area { padding-left: 0 !important; }
            body.${LEFT_SIDEBAR_HIDDEN_CLASS} #ds-toggle-left-sidebar { left: 5px; }
            body.${LEFT_SIDEBAR_HIDDEN_CLASS} #ds-toggle-left-sidebar::before { content: '>>'; }
            body.${LEFT_SIDEBAR_HIDDEN_CLASS} #ds-toggle-left-sidebar::after { content: 'Show'; }
            body.${RIGHT_SIDEBAR_HIDDEN_CLASS} .ds-playlist-section { flex-basis: 0 !important; min-width: 0 !important; }
            body.${RIGHT_SIDEBAR_HIDDEN_CLASS} #ds-toggle-right-playlist { right: 5px; }
            body.${RIGHT_SIDEBAR_HIDDEN_CLASS} #ds-toggle-right-playlist::before { content: '<<'; }
            body.${RIGHT_SIDEBAR_HIDDEN_CLASS} #ds-toggle-right-playlist::after { content: 'Show'; }
        `).id = STYLE_ID;

        const leftToggleButton = document.createElement('div');
        leftToggleButton.id = 'ds-toggle-left-sidebar';
        leftToggleButton.addEventListener('click', () => {
            const isHidden = document.body.classList.toggle(LEFT_SIDEBAR_HIDDEN_CLASS);
            localStorage.setItem('dsLeftSidebarHidden', isHidden);
        });

        const rightToggleButton = document.createElement('div');
        rightToggleButton.id = 'ds-toggle-right-playlist';
        rightToggleButton.addEventListener('click', () => {
            const isHidden = document.body.classList.toggle(RIGHT_SIDEBAR_HIDDEN_CLASS);
            localStorage.setItem('dsRightSidebarHidden', isHidden);
        });

        if (localStorage.getItem('dsLeftSidebarHidden') === 'true') document.body.classList.add(LEFT_SIDEBAR_HIDDEN_CLASS);
        if (localStorage.getItem('dsRightSidebarHidden') === 'true') document.body.classList.add(RIGHT_SIDEBAR_HIDDEN_CLASS);

        document.body.append(leftToggleButton, rightToggleButton);
    }

    function removeFeatures() {
        const styleTag = document.getElementById(STYLE_ID);
        if (styleTag) styleTag.remove();

        const leftBtn = document.getElementById('ds-toggle-left-sidebar');
        if (leftBtn) leftBtn.remove();
        const rightBtn = document.getElementById('ds-toggle-right-playlist');
        if (rightBtn) rightBtn.remove();

        document.body.classList.remove(LEFT_SIDEBAR_HIDDEN_CLASS, RIGHT_SIDEBAR_HIDDEN_CLASS);
        console.log("DS Widescreen Script: Features removed.");
    }

    function handlePageChange() {
        const masterToggle = document.getElementById(MASTER_TOGGLE_ID);
        if (!masterToggle) return;

        const isWatchPage = location.href.includes('/watch?');
        masterToggle.style.display = isWatchPage ? 'flex' : 'none';

        if (isWatchPage) {
            if (isMasterEnabled()) {
                // Look for either the old YouTube player or the new Shaka player embed container
                waitForElement('.ds-youtube-player, .ds-video-section__embed').then(addFeatures);

                // This part only affects the old YouTube player, it will be ignored by the new one
                const iframeSelector = '.ds-video-section iframe';
                const iframeCondition = (el) => el.src && el.src.includes('youtube.com');
                waitForElement(iframeSelector, iframeCondition).then(setHighQuality).catch(() => {
                    console.log("DS Widescreen Script: YouTube player not found, skipping HD quality request.");
                });

            } else {
                removeFeatures();
            }
        } else {
            removeFeatures();
        }
    }

    function addMasterToggleStyles() {
        GM_addStyle(`
            #${MASTER_TOGGLE_ID} {
                display: none; position: fixed; top: 10px; left: 10px;
                width: 40px; height: 25px; background-color: #d9534f;
                color: white; align-items: center; justify-content: center;
                font-size: 11px; font-weight: bold; font-family: sans-serif;
                cursor: pointer; z-index: 10001; border-radius: 5px;
                border: 1px solid #333; user-select: none; transition: background-color 0.3s ease;
            }
            body.${MASTER_ENABLED_CLASS} #${MASTER_TOGGLE_ID} {
                background-color: #5cb85c;
            }
        `);
    }

    function createMasterToggle() {
        const toggleButton = document.createElement('div');
        toggleButton.id = MASTER_TOGGLE_ID;

        const updateButtonState = (enabled) => {
            document.body.classList.toggle(MASTER_ENABLED_CLASS, enabled);
            toggleButton.textContent = enabled ? 'ON' : 'OFF';
            toggleButton.title = enabled ? 'Click to disable Widescreen features' : 'Click to enable Widescreen features';
        };

        toggleButton.addEventListener('click', () => {
            const currentlyEnabled = isMasterEnabled();
            localStorage.setItem(MASTER_ENABLED_KEY, !currentlyEnabled);
            updateButtonState(!currentlyEnabled);
            handlePageChange();
        });

        document.body.appendChild(toggleButton);
        updateButtonState(isMasterEnabled());
    }

    // --- Auto-click "Not now" button & Resume Playback ---
    function autoClickNotNow() {
        const checkInterval = 2000; // Check every 2 seconds

        setInterval(() => {
            const buttons = document.querySelectorAll('button');
            for (const button of buttons) {
                if (button.innerText && button.innerText.trim().toLowerCase() === 'not now') {
                    console.log("DS Widescreen Script: 'Not now' button found. Clicking it automatically.");
                    button.click();

                    setTimeout(() => {
                        const videoElement = document.querySelector('video.ds-shaka-player__video');
                        if (videoElement && videoElement.paused) {
                            console.log("DS Widescreen Script: Video is paused after popup, resuming playback.");
                            videoElement.play();
                        }
                    }, 100);
                }
            }
        }, checkInterval);
    }

    // --- Script Initialization ---
    addMasterToggleStyles();
    createMasterToggle();

    const bodyObserver = new MutationObserver(() => {
        if (location.href !== lastUrl) {
            lastUrl = location.href;
            handlePageChange();
        }
    });
    bodyObserver.observe(document.body, { childList: true, subtree: true });

    handlePageChange();

    autoClickNotNow();

})();