GGN Theme Switcher

Modify page body class to specified class and provide theme switching functionality

// ==UserScript==
// @name         GGN Theme Switcher
// @namespace    http://tampermonkey.net/
// @version      2.1
// @description  Modify page body class to specified class and provide theme switching functionality
// @author       Robin27
// @license      MIT
// @match        *://gazellegames.net/*
// @match        *://*.gazellegames.net/*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // ===== Configuration Area =====
    // Get configuration from storage, use default values if not exists
    let TARGET_BODY_CLASS = GM_getValue('TARGET_BODY_CLASS', '');
    // ==============================

    // Register configuration menu commands
    GM_registerMenuCommand('Configure Target Theme Class', function() {
        const newClassName = prompt('Enter target theme class name (e.g.: master_3944):', TARGET_BODY_CLASS);
        if (newClassName !== null && newClassName.trim() !== '') {
            TARGET_BODY_CLASS = newClassName.trim();
            GM_setValue('TARGET_BODY_CLASS', TARGET_BODY_CLASS);
            alert('Configuration saved! Refresh the page to take effect.\nCurrent setting: ' + TARGET_BODY_CLASS);
            console.log('✅ Theme class name updated to:', TARGET_BODY_CLASS);
        }
    });

    // Theme ID list - all theme IDs extracted from comments
    const THEME_IDS = [
        // FRANCHISE type
        'franchise_3', 'franchise_16', 'franchise_19', 'franchise_50', 'franchise_53', 'franchise_55', 'franchise_57', 'franchise_58', 'franchise_65', 'franchise_75', 'franchise_91', 'franchise_126', 'franchise_135', 'franchise_179', 'franchise_198', 'franchise_211', 'franchise_344', 'franchise_360', 'franchise_491', 'franchise_587', 'franchise_595', 'franchise_646', 'franchise_833', 'franchise_836', 'franchise_896', 'franchise_986', 'franchise_1519', 'franchise_2521', 'franchise_2773', 'franchise_3155', 'franchise_5276', 'franchise_6816', 'franchise_9300', 'franchise_12545', 'franchise_12565',
        // MASTER type
        'master_117', 'master_465', 'master_680', 'master_691', 'master_904', 'master_2639', 'master_2940', 'master_3073', 'master_3787', 'master_3805', 'master_3944', 'master_4715', 'master_4742', 'master_4752', 'master_5127', 'master_5154', 'master_6427', 'master_6928', 'master_7718', 'master_7884', 'master_15933', 'master_20225', 'master_23228', 'master_29116', 'master_30510', 'master_39874', 'master_43997', 'master_50731', 'master_56065', 'master_65286', 'master_99091',
        // SERIES type
        'series_11', 'series_12', 'series_22', 'series_26', 'series_27', 'series_31', 'series_35', 'series_66', 'series_70', 'series_169', 'series_177', 'series_178', 'series_183', 'series_184', 'series_185', 'series_188', 'series_191', 'series_196', 'series_204', 'series_205', 'series_208', 'series_228', 'series_234', 'series_237', 'series_260', 'series_268', 'series_279', 'series_291', 'series_298', 'series_302', 'series_327', 'series_418', 'series_483', 'series_548', 'series_555', 'series_565', 'series_575', 'series_581', 'series_630', 'series_827', 'series_857', 'series_877', 'series_882', 'series_885', 'series_987', 'series_1109', 'series_1316', 'series_1434', 'series_1503', 'series_2786', 'series_2918', 'series_3308', 'series_3327', 'series_3369', 'series_4624', 'series_4949', 'series_5588', 'series_5635', 'series_6614', 'series_7385', 'series_12344',
        // TGROUP type
        'tgroup_107', 'tgroup_172', 'tgroup_3609', 'tgroup_4231', 'tgroup_6454', 'tgroup_6526', 'tgroup_9559', 'tgroup_11495', 'tgroup_14972', 'tgroup_18505', 'tgroup_18702', 'tgroup_22694', 'tgroup_23617', 'tgroup_30661', 'tgroup_33733', 'tgroup_65589', 'tgroup_71747', 'tgroup_108726'
    ];

    // Current theme index, -1 means using default theme
    let currentThemeIndex = -1;

    console.log('🚀 GGN Page Enhancer started, target class:', GM_getValue('TARGET_BODY_CLASS', 'master_3944'));

    // High-frequency checking - using requestAnimationFrame
    function checkAndModify() {
        if (document.body) {
            const currentClass = document.body.className;
            const targetClass = GM_getValue('TARGET_BODY_CLASS', 'master_3944');
            
            // Use default theme on index.php page
            if (window.location.pathname.includes('index.php')) {
                if (currentClass === '' || currentClass === 'warned' || currentClass.includes('master_112041')) {
                    document.body.className = targetClass;
                    currentThemeIndex = -1; // Keep default state
                    console.log('✅ Homepage theme set successfully - using default theme:', targetClass);
                }
            } else {
                // Other pages use original logic
                if (currentClass === '') {
                    document.body.className = targetClass;
                    console.log('✅ Added successfully - body has no class, added "' + targetClass + '"');
                } else if (currentClass === 'warned') {
                    document.body.className = targetClass;
                    console.log('✅ Replaced successfully - from "warned" to "' + targetClass + '"');
                } else if (currentClass.includes('master_112041')) {
                    // If class contains master_112041, replace it with custom class
                    const newClass = currentClass.replace(/master_112041/g, targetClass);
                    document.body.className = newClass;
                    console.log('✅ Replaced successfully - from class containing "master_112041" to "' + targetClass + '"');
                    console.log('Original class:', currentClass, '→ New class:', newClass);
                }
            }
        }
        // If page is not fully loaded, continue checking
        if (document.readyState !== 'complete') {
            requestAnimationFrame(checkAndModify);
        } else {
            console.log('🏁 Page loading completed, script finished');
        }
    }
    // Start high-frequency checking
    checkAndModify();

    // ------------------------------------------------------------------------------------------
    // Theme switching functionality

    // Wait for specific elements to load
    function waitForElement(selector, callback) {
        const element = document.querySelector(selector);
        if (element) {
            callback(element);
        } else {
            setTimeout(() => waitForElement(selector, callback), 100);
        }
    }

    // Create theme switcher button
    function createThemeSwitcherButton() {
        // Check if on index.php page
        if (!window.location.pathname.includes('index.php')) {
            return;
        }

        // Create button element
        const themeButton = document.createElement('button');
        themeButton.id = 'ggn-theme-switcher';
        themeButton.textContent = 'Switch Theme';
        themeButton.title = 'Left click: Switch theme | Right click: Copy current theme ID';
        
        // Set button styles
        themeButton.style.cssText = `
            position: fixed;
            top: 300px;
            right: 20px;
            z-index: 9999;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border: none;
            border-radius: 8px;
            padding: 16px 24px;
            font-size: 16px;
            font-weight: bold;
            cursor: pointer;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
            transition: all 0.3s ease;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            width: 140px;
            min-height: 50px;
            display: flex;
            align-items: center;
            justify-content: center;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        `;

        // Add hover effects
        themeButton.addEventListener('mouseenter', function() {
            this.style.transform = 'translateY(-2px)';
            this.style.boxShadow = '0 6px 20px rgba(0, 0, 0, 0.3)';
        });

        themeButton.addEventListener('mouseleave', function() {
            this.style.transform = 'translateY(0)';
            this.style.boxShadow = '0 4px 15px rgba(0, 0, 0, 0.2)';
        });

        // Add left click event
        themeButton.addEventListener('click', function() {
            switchToNextTheme();
        });

        // Add right click event - copy current theme ID
        themeButton.addEventListener('contextmenu', function(e) {
            e.preventDefault(); // Prevent default context menu
            
            let currentThemeId;
            if (currentThemeIndex === -1) {
                // If still using default theme
                currentThemeId = GM_getValue('TARGET_BODY_CLASS', 'master_3944');
            } else {
                // If already switched to theme in the list
                currentThemeId = THEME_IDS[currentThemeIndex];
            }
            
            // Copy to clipboard
            navigator.clipboard.writeText(currentThemeId).then(function() {
                // Create temporary notification
                const originalText = themeButton.textContent;
                themeButton.textContent = 'Copied!';
                themeButton.style.background = 'linear-gradient(135deg, #4CAF50 0%, #45a049 100%)';
                
                // Restore after 1 second
                setTimeout(function() {
                    themeButton.textContent = originalText;
                    themeButton.style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
                }, 1000);
                
                console.log(`📋 Theme ID copied: ${currentThemeId}`);
            }).catch(function(err) {
                console.error('Copy failed:', err);
                // If clipboard API fails, use traditional method
                const textArea = document.createElement('textarea');
                textArea.value = currentThemeId;
                document.body.appendChild(textArea);
                textArea.select();
                document.execCommand('copy');
                document.body.removeChild(textArea);
                
                // Show notification
                const originalText = themeButton.textContent;
                themeButton.textContent = 'Copied!';
                themeButton.style.background = 'linear-gradient(135deg, #4CAF50 0%, #45a049 100%)';
                
                setTimeout(function() {
                    themeButton.textContent = originalText;
                    themeButton.style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
                }, 1000);
                
                console.log(`📋 Theme ID copied: ${currentThemeId}`);
            });
        });

        // Add button to page
        document.body.appendChild(themeButton);
        console.log('✅ Theme switcher button created');
    }

    // Switch to next theme
    function switchToNextTheme() {
        // If first click (starting from default theme), start from index 0
        if (currentThemeIndex === -1) {
            currentThemeIndex = 0;
        } else {
            // Move to next theme index
            currentThemeIndex = (currentThemeIndex + 1) % THEME_IDS.length;
        }
        
        const newTheme = THEME_IDS[currentThemeIndex];
        
        // Update body class
        document.body.className = newTheme;
        
        // Update button text to show current theme info
        const themeButton = document.getElementById('ggn-theme-switcher');
        if (themeButton) {
            const themeType = newTheme.split('_')[0];
            const themeNumber = newTheme.split('_')[1];
            // Use more concise display
            themeButton.textContent = `${themeType}_${themeNumber}`;
            themeButton.title = `Current theme: ${newTheme} (${currentThemeIndex + 1}/${THEME_IDS.length})`;
            
            // Button width is fixed at 140px, no need for dynamic adjustment
        }
        
        console.log(`🎨 Theme switched to: ${newTheme} (${currentThemeIndex + 1}/${THEME_IDS.length})`);
    }

    // Wait for page to load completely before creating theme switcher button
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', createThemeSwitcherButton);
    } else {
        createThemeSwitcherButton();
    }
})();