WTR-Lab Reader & UI Enhancer

Adds a responsive configuration panel to adjust the width of the reader content and bottom navigation bar on wtr-lab.com.

// ==UserScript==
// @name         WTR-Lab Reader & UI Enhancer
// @namespace    http://tampermonkey.net/
// @version      2.1
// @description  Adds a responsive configuration panel to adjust the width of the reader content and bottom navigation bar on wtr-lab.com.
// @author       MasuRiii
// @license      MIT
// @match        https://wtr-lab.com/en/novel/*/*/chapter-*
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @icon         https://www.google.com/s2/favicons?sz=64&domain=wtr-lab.com
// ==/UserScript==

(function() {
    'use strict';

    // --- CONFIGURATION ---
    const DEBUG_KEY = 'wtr_lab_enhancer_debug';
    const STEP_WIDTH = 50;
    const MIN_WIDTH = 300;

    // Configuration for elements that can be modified
    const configs = {
        reader: {
            key: 'wtr_lab_reader_width',
            selector: '.fix-size.card',
            defaultWidth: 760,
            label: 'Reader Content Width'
        },
        nav: {
            key: 'wtr_lab_nav_width',
            selector: 'nav.bottom-reader-nav .fix-size',
            defaultWidth: 760,
            label: 'Bottom Navigator Width'
        }
    };

    // --- DEBUG LOGGER ---
    let isDebugEnabled = GM_getValue(DEBUG_KEY, false);
    const log = (...args) => {
        if (isDebugEnabled) {
            console.log('[WTR-Lab Enhancer]', ...args);
        }
    };

    const toggleDebugLogging = () => {
        isDebugEnabled = !isDebugEnabled;
        GM_setValue(DEBUG_KEY, isDebugEnabled);
        alert(`Debug logging is now ${isDebugEnabled ? 'ENABLED' : 'DISABLED'}.`);
        log(`Debug logging state changed to: ${isDebugEnabled}`);
    };

    // --- CORE LOGIC ---

    // Applies a CSS rule to the page to set the width for a given element.
    const applyStyle = (configName, width) => {
        const styleId = `custom-width-styler-${configName}`;
        let styleElement = document.getElementById(styleId);

        if (!styleElement) {
            styleElement = document.createElement('style');
            styleElement.id = styleId;
            document.head.appendChild(styleElement);
        }

        const config = configs[configName];
        styleElement.textContent = `
            ${config.selector} {
                max-width: ${width}px !important;
            }
        `;
        log(`Style applied for '${configName}': max-width set to ${width}px`);
    };

    // Saves a value to Tampermonkey's storage.
    const saveValue = (key, value) => {
        GM_setValue(key, value);
        log(`Value saved for key '${key}':`, value);
    };

    // Loads a value from Tampermonkey's storage.
    const loadValue = (key, defaultValue) => {
        return GM_getValue(key, defaultValue);
    };

    // --- UI CONFIGURATION PANEL ---

    // Creates and injects the panel's HTML and CSS into the page.
    const createConfigPanel = () => {
        const panelHTML = `
            <div id="wtr-config-overlay" style="display: none;">
              <div id="wtr-config-panel">
                <h2>WTR-Lab Enhancer Settings</h2>
                <div id="wtr-config-sections"></div>
                <button id="wtr-config-close-btn" class="wtr-config-button">Close</button>
              </div>
            </div>
        `;
        document.body.insertAdjacentHTML('beforeend', panelHTML);

        const panelCSS = `
            #wtr-config-overlay {
                position: fixed; top: 0; left: 0; width: 100%; height: 100%;
                background-color: rgba(0, 0, 0, 0.7); z-index: 9999;
                display: flex; justify-content: center; align-items: center;
            }
            #wtr-config-panel {
                background: #2c2c2c; color: #f1f1f1; padding: 25px;
                border-radius: 8px; width: 90%; max-width: 500px;
                box-shadow: 0 5px 15px rgba(0,0,0,0.5); font-family: sans-serif;
                display: flex; flex-direction: column; gap: 20px;
            }
            #wtr-config-panel h2 { margin: 0 0 10px 0; text-align: center; }
            .wtr-config-section {
                display: flex; flex-direction: column; gap: 8px;
                padding: 15px; border: 1px solid #444; border-radius: 5px;
            }
            .wtr-config-controls {
                display: flex; gap: 10px; align-items: center;
                flex-wrap: wrap; /* Allows controls to wrap on small screens */
            }
            .wtr-config-controls input[type="number"] {
                flex-grow: 1; /* Allows input to fill available space */
                min-width: 60px;
                text-align: center; background: #444; color: #fff;
                border: 1px solid #666; border-radius: 4px; padding: 8px;
            }
            .wtr-config-button {
                padding: 8px 12px; border: none; border-radius: 4px; cursor: pointer;
                background-color: #007bff; color: white; font-weight: bold;
                flex-shrink: 0; /* Prevents buttons from shrinking */
            }
            .wtr-config-button.control {
                width: 40px; /* Smaller, fixed width for +/- buttons */
            }
            .wtr-config-button.reset { background-color: #dc3545; }
            #wtr-config-close-btn { background-color: #6c757d; align-self: center; width: 100px; }
        `;
        GM_addStyle(panelCSS);

        // Dynamically create control sections based on the configs object
        const sectionsContainer = document.getElementById('wtr-config-sections');
        for (const [name, config] of Object.entries(configs)) {
            const sectionHTML = `
                <div class="wtr-config-section">
                  <label for="wtr-${name}-width-input">${config.label} (px)</label>
                  <div class="wtr-config-controls">
                    <button id="wtr-${name}-decrease-btn" class="wtr-config-button control">-</button>
                    <input type="number" id="wtr-${name}-width-input" min="${MIN_WIDTH}" step="10">
                    <button id="wtr-${name}-increase-btn" class="wtr-config-button control">+</button>
                    <button id="wtr-${name}-reset-btn" class="wtr-config-button reset">Reset</button>
                  </div>
                </div>
            `;
            sectionsContainer.insertAdjacentHTML('beforeend', sectionHTML);
        }

        // Attach event listeners
        attachPanelEventListeners();
    };

    // Wires up all the buttons and inputs in the panel.
    const attachPanelEventListeners = () => {
        const overlay = document.getElementById('wtr-config-overlay');
        overlay.addEventListener('click', (e) => {
            if (e.target === overlay) hideConfigPanel();
        });
        document.getElementById('wtr-config-close-btn').addEventListener('click', hideConfigPanel);

        // Helper function to update and save settings
        const updateSetting = (configName, newWidth) => {
            const validatedWidth = Math.max(MIN_WIDTH, parseInt(newWidth, 10));
            if (isNaN(validatedWidth)) return;

            const config = configs[configName];
            applyStyle(configName, validatedWidth);
            saveValue(config.key, validatedWidth);
            // *** FIX: Use configName to target the correct input field ***
            document.getElementById(`wtr-${configName}-width-input`).value = validatedWidth;
        };

        // Set up controls for each configured element
        for (const [name, config] of Object.entries(configs)) {
            const input = document.getElementById(`wtr-${name}-width-input`);
            const decreaseBtn = document.getElementById(`wtr-${name}-decrease-btn`);
            const increaseBtn = document.getElementById(`wtr-${name}-increase-btn`);
            const resetBtn = document.getElementById(`wtr-${name}-reset-btn`);

            increaseBtn.addEventListener('click', () => {
                const currentWidth = parseInt(input.value, 10);
                updateSetting(name, currentWidth + STEP_WIDTH);
            });

            decreaseBtn.addEventListener('click', () => {
                const currentWidth = parseInt(input.value, 10);
                updateSetting(name, currentWidth - STEP_WIDTH);
            });

            resetBtn.addEventListener('click', () => {
                updateSetting(name, config.defaultWidth);
            });

            input.addEventListener('change', () => {
                updateSetting(name, input.value);
            });
        }
    };

    // Shows the configuration panel and populates it with current values.
    const showConfigPanel = () => {
        log('Showing configuration panel.');
        // Populate inputs with current values
        for (const [name, config] of Object.entries(configs)) {
            const currentWidth = loadValue(config.key, config.defaultWidth);
            document.getElementById(`wtr-${name}-width-input`).value = currentWidth;
        }
        document.getElementById('wtr-config-overlay').style.display = 'flex';
    };

    // Hides the configuration panel.
    const hideConfigPanel = () => {
        log('Hiding configuration panel.');
        document.getElementById('wtr-config-overlay').style.display = 'none';
    };

    // --- INITIALIZATION ---
    const init = () => {
        log('Initializing script...');

        // Create and inject the panel into the page
        createConfigPanel();

        // Apply initial styles on page load
        for (const [name, config] of Object.entries(configs)) {
            const initialWidth = loadValue(config.key, config.defaultWidth);
            applyStyle(name, initialWidth);
            log(`Initial width for '${name}' set to ${initialWidth}px`);
        }

        // Register the new, unified menu commands
        GM_registerMenuCommand('Configure Settings', showConfigPanel);
        GM_registerMenuCommand('Toggle Debug Logging', toggleDebugLogging);

        log('Initialization complete.');
    };

    // Run the script
    init();
})();