Keyboard Wizard - Text Effects

Effect Color Trace Sound

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         Keyboard Wizard - Text Effects
// @namespace    http://tampermonkey.net/
// @version      2.1
// @description  Effect Color Trace Sound
// @author       Mustafa Hakan
// @match        *://*/*
// @grant        GM_getValue
// @grant        GM_setValue
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    // Ayarlar
    const CFG = {
        effect: GM_getValue('kb_effect', 'fire'),
        hidePass: GM_getValue('kb_hidepass', true),
        sound: GM_getValue('kb_sound', true),
        trail: GM_getValue('kb_trail', true),
        particles: GM_getValue('kb_particles', true)
    };

    const EFFECTS = {
        fire: { name: '🔥 Ateş', color: '#ff4500', glow: '#ff8c00', trail: ['🔥','✨','💥'], sound: 'crackle' },
        ice: { name: '❄️ Buz', color: '#00d4ff', glow: '#87ceeb', trail: ['❄️','💎','✨'], sound: 'chime' },
        neon: { name: '💜 Neon', color: '#ff00ff', glow: '#ff69b4', trail: ['💜','💗','✨'], sound: 'buzz' },
        matrix: { name: '💚 Matrix', color: '#00ff41', glow: '#00cc33', trail: ['💚','⌨️','💻'], sound: 'type' },
        gold: { name: '👑 Altın', color: '#ffd700', glow: '#ffec8b', trail: ['👑','💰','✨'], sound: 'coin' },
        rainbow: { name: '🌈 Gökkuşağı', color: 'rainbow', glow: '#fff', trail: ['🌈','🎨','✨'], sound: 'magic' },
        shadow: { name: '🌑 Gölge', color: '#333', glow: '#000', trail: ['🌑','🖤','💨'], sound: 'whisper' },
        magic: { name: '🔮 Sihir', color: '#a855f7', glow: '#c084fc', trail: ['🔮','⭐','💫'], sound: 'sparkle' }
    };

    let activeEffect = EFFECTS[CFG.effect] || EFFECTS.fire;
    let audioCtx = null;
    let styleElement = null;

    // ---------- TEK STİL ETİKETİ ----------
    function updateStyles() {
        if (!styleElement) {
            styleElement = document.createElement('style');
            styleElement.id = 'kb-main-style';
            document.head.appendChild(styleElement);
        }
        const color = activeEffect.color === 'rainbow' ? '#fff' : activeEffect.color;
        const glow = activeEffect.glow;
        styleElement.textContent = `
            input:focus, textarea:focus, [contenteditable="true"]:focus {
                caret-color: ${color} !important;
                text-shadow: 0 0 5px ${glow} !important;
                transition: text-shadow 0.3s !important;
            }
            input[type="password"]:focus {
                letter-spacing: 3px !important;
                font-family: monospace !important;
            }
            ::selection {
                background: ${color}44 !important;
                color: ${color} !important;
            }
            ${activeEffect.color === 'rainbow' ? `
            .kb-rainbow-focus:focus {
                animation: kbRainbowText 2s linear infinite !important;
            }
            ` : ''}
            @keyframes kbSlideIn {
                from { opacity: 0; transform: translateX(20px); }
                to { opacity: 1; transform: translateX(0); }
            }
            @keyframes kbFloat {
                0%,100% { transform: translateY(0); }
                50% { transform: translateY(-6px); }
            }
            @keyframes kbRainbowText {
                0% { text-shadow: 0 0 5px #ff0000; }
                16% { text-shadow: 0 0 5px #ff7700; }
                33% { text-shadow: 0 0 5px #ffff00; }
                50% { text-shadow: 0 0 5px #00ff00; }
                66% { text-shadow: 0 0 5px #0077ff; }
                83% { text-shadow: 0 0 5px #8b00ff; }
                100% { text-shadow: 0 0 5px #ff0000; }
            }
        `;
    }

    // ---------- SES ----------
    function initAudio() {
        if (audioCtx) return;
        try {
            audioCtx = new (window.AudioContext || window.webkitAudioContext)();
            if (audioCtx.state === 'suspended') {
                const resume = () => {
                    audioCtx.resume();
                    document.removeEventListener('click', resume);
                    document.removeEventListener('keydown', resume);
                };
                document.addEventListener('click', resume);
                document.addEventListener('keydown', resume);
            }
        } catch(e) { /* sessizce başarısız */ }
    }

    function playSound(type) {
        if (!CFG.sound || !audioCtx || audioCtx.state !== 'running') return;
        try {
            const osc = audioCtx.createOscillator();
            const gain = audioCtx.createGain();
            gain.gain.setValueAtTime(0.02, audioCtx.currentTime);
            gain.gain.exponentialRampToValueAtTime(0.0001, audioCtx.currentTime + 0.1);
            switch(type) {
                case 'crackle': osc.type = 'sawtooth'; osc.frequency.setValueAtTime(100 + Math.random()*200, audioCtx.currentTime); break;
                case 'chime': osc.type = 'sine'; osc.frequency.setValueAtTime(800 + Math.random()*400, audioCtx.currentTime); break;
                case 'buzz': osc.type = 'square'; osc.frequency.setValueAtTime(60 + Math.random()*30, audioCtx.currentTime); break;
                case 'type': osc.type = 'triangle'; osc.frequency.setValueAtTime(300 + Math.random()*200, audioCtx.currentTime); break;
                case 'coin': osc.type = 'sine'; osc.frequency.setValueAtTime(1000 + Math.random()*500, audioCtx.currentTime); break;
                case 'magic': osc.type = 'sine'; osc.frequency.setValueAtTime(400 + Math.random()*600, audioCtx.currentTime); osc.frequency.linearRampToValueAtTime(1200, audioCtx.currentTime + 0.1); break;
                case 'sparkle': osc.type = 'triangle'; osc.frequency.setValueAtTime(1500 + Math.random()*1000, audioCtx.currentTime); break;
                case 'whisper': osc.type = 'sine'; osc.frequency.setValueAtTime(80 + Math.random()*40, audioCtx.currentTime); gain.gain.setValueAtTime(0.01, audioCtx.currentTime); break;
                default: osc.type = 'sine'; osc.frequency.setValueAtTime(500, audioCtx.currentTime);
            }
            osc.connect(gain);
            gain.connect(audioCtx.destination);
            osc.start();
            osc.stop(audioCtx.currentTime + 0.1);
        } catch(e) {}
    }

    // ---------- İZ VE PARÇACIK ----------
    function spawnTrail(x, y) {
        if (!CFG.trail) return;
        const emoji = activeEffect.trail[Math.floor(Math.random() * activeEffect.trail.length)];
        const el = document.createElement('span');
        el.textContent = emoji;
        Object.assign(el.style, {
            position: 'fixed', left: x+'px', top: y+'px', pointerEvents: 'none',
            zIndex: '2147483647', fontSize: (12 + Math.random()*16)+'px',
            opacity: '1', transition: 'all 0.8s ease-out'
        });
        document.body.appendChild(el);
        requestAnimationFrame(() => {
            el.style.transform = `translate(${(Math.random()-0.5)*60}px, ${-30-Math.random()*40}px) rotate(${(Math.random()-0.5)*40}deg)`;
            el.style.opacity = '0';
        });
        setTimeout(() => el.remove(), 800);
    }

    function spawnParticle(x, y) {
        if (!CFG.particles || activeEffect.color !== 'rainbow') return;
        const colors = ['#ff0000','#ff7700','#ffff00','#00ff00','#0077ff','#8b00ff'];
        const color = colors[Math.floor(Math.random() * colors.length)];
        const particle = document.createElement('div');
        Object.assign(particle.style, {
            position: 'fixed', left: x+'px', top: y+'px', pointerEvents: 'none',
            zIndex: '2147483646', width: '6px', height: '6px', background: color,
            borderRadius: '50%', boxShadow: `0 0 10px ${color}, 0 0 20px ${color}`,
            transition: 'all 0.6s ease-out'
        });
        document.body.appendChild(particle);
        requestAnimationFrame(() => {
            particle.style.transform = `translate(${(Math.random()-0.5)*80}px, -${20+Math.random()*40}px) scale(0)`;
            particle.style.opacity = '0';
        });
        setTimeout(() => particle.remove(), 600);
    }

    // ---------- İMLEÇ POZİSYONU ----------
    function getCursorPosition() {
        try {
            const sel = window.getSelection();
            if (sel && sel.rangeCount > 0) {
                const rect = sel.getRangeAt(0).getBoundingClientRect();
                if (rect) return { x: rect.right, y: rect.top };
            }
        } catch(e) {}
        return null;
    }

    // ---------- TUŞ OLAYI ----------
    function onKeyDown(e) {
        if (e.target.closest('#kb-panel')) return;
        if (CFG.hidePass && e.target.type === 'password') {
            e.target.style.fontFamily = 'monospace';
            e.target.style.letterSpacing = '2px';
            e.target.style.textShadow = `0 0 8px ${activeEffect.glow}`;
        }
        const pos = getCursorPosition();
        if (pos && e.key.length === 1 && !e.ctrlKey && !e.altKey && !e.metaKey) {
            spawnTrail(pos.x, pos.y);
            if (CFG.sound) playSound(activeEffect.sound);
            spawnParticle(pos.x, pos.y);
        }
    }

    // ---------- PANEL VE BUTON (OLAY DELEGASYONU) ----------
    function createPanel() {
        if (document.getElementById('kb-panel')) return;

        const panel = document.createElement('div');
        panel.id = 'kb-panel';
        Object.assign(panel.style, {
            position: 'fixed', bottom: '100px', right: '30px', background: 'rgba(15,15,20,0.95)',
            border: `2px solid ${activeEffect.color}`, borderRadius: '16px', padding: '15px',
            zIndex: '2147483645', font: '13px system-ui', color: '#fff', minWidth: '220px',
            backdropFilter: 'blur(20px)', boxShadow: `0 15px 40px rgba(0,0,0,0.7), 0 0 20px ${activeEffect.glow}`,
            animation: 'kbSlideIn 0.3s ease-out'
        });

        // Başlık
        const title = document.createElement('div');
        title.textContent = '🧙 Klavye Büyücüsü';
        Object.assign(title.style, { fontWeight: '700', marginBottom: '10px', color: activeEffect.color });
        panel.appendChild(title);

        // Buton kabı (olay delegasyonu için)
        const btnContainer = document.createElement('div');
        btnContainer.style.cssText = 'display: flex; flex-direction: column; gap: 5px;';
        for (const [key, eff] of Object.entries(EFFECTS)) {
            const btn = document.createElement('button');
            btn.textContent = eff.name;
            btn.setAttribute('data-effect', key);
            Object.assign(btn.style, {
                padding: '10px', borderRadius: '10px', border: `1px solid ${CFG.effect === key ? eff.color : '#444'}`,
                background: CFG.effect === key ? eff.color+'22' : '#222', color: eff.color,
                cursor: 'pointer', transition: '0.2s', textAlign: 'left', font: '13px system-ui'
            });
            // Hover efektleri (döngü içinde ama sorunsuz)
            btn.addEventListener('mouseenter', () => { if (CFG.effect !== key) btn.style.background = '#333'; });
            btn.addEventListener('mouseleave', () => { if (CFG.effect !== key) btn.style.background = '#222'; });
            btnContainer.appendChild(btn);
        }
        panel.appendChild(btnContainer);

        // Olay delegasyonu: buton tıklamalarını yakala
        btnContainer.addEventListener('click', (e) => {
            const btn = e.target.closest('button[data-effect]');
            if (!btn) return;
            const newEffect = btn.dataset.effect;
            if (newEffect === CFG.effect) return;
            CFG.effect = newEffect;
            activeEffect = EFFECTS[newEffect];
            GM_setValue('kb_effect', newEffect);
            updateStyles();
            updateUI();
            panel.remove();
            createPanel(); // yeniden oluştur
        });

        // Ayarlar (checkbokslar)
        const opts = document.createElement('div');
        opts.style.cssText = 'margin-top: 10px; display: flex; flex-direction: column; gap: 6px; color: #aaa; font-size: 11px;';

        const createCheck = (label, cfgKey, storageKey) => {
            const labelEl = document.createElement('label');
            labelEl.style.cssText = 'display: flex; justify-content: space-between; align-items: center;';
            const input = document.createElement('input');
            input.type = 'checkbox';
            input.checked = CFG[cfgKey];
            input.addEventListener('change', (e) => {
                CFG[cfgKey] = e.target.checked;
                GM_setValue(storageKey, e.target.checked);
                if (storageKey === 'kb_sound' && e.target.checked && !audioCtx) initAudio();
            });
            labelEl.appendChild(document.createTextNode(label));
            labelEl.appendChild(input);
            return labelEl;
        };

        opts.appendChild(createCheck('🔒 Şifre Gizleme', 'hidePass', 'kb_hidepass'));
        opts.appendChild(createCheck('🔊 Ses Efekti', 'sound', 'kb_sound'));
        opts.appendChild(createCheck('✨ İz Efekti', 'trail', 'kb_trail'));
        opts.appendChild(createCheck('💫 Parçacık', 'particles', 'kb_particles'));
        panel.appendChild(opts);

        const closeBtn = document.createElement('button');
        closeBtn.textContent = 'Kapat';
        Object.assign(closeBtn.style, {
            marginTop: '10px', width: '100%', padding: '8px', borderRadius: '8px',
            border: '1px solid #444', background: '#222', color: '#888', cursor: 'pointer'
        });
        closeBtn.addEventListener('click', () => panel.remove());
        panel.appendChild(closeBtn);

        document.body.appendChild(panel);
    }

    // ---------- TETİKLEYİCİ DÜĞME ----------
    function createTrigger() {
        if (document.getElementById('kb-trigger')) return;
        const btn = document.createElement('div');
        btn.id = 'kb-trigger';
        btn.textContent = '🧙';
        Object.assign(btn.style, {
            position: 'fixed', bottom: '30px', right: '30px', width: '45px', height: '45px',
            background: activeEffect.color === 'rainbow' ? '#333' : activeEffect.color+'22',
            border: `2px solid ${activeEffect.color}`, borderRadius: '50%',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontSize: '22px', cursor: 'pointer', zIndex: '2147483644',
            boxShadow: `0 0 15px ${activeEffect.glow}`, transition: '0.3s',
            animation: 'kbFloat 3s ease-in-out infinite'
        });
        btn.addEventListener('click', () => {
            if (document.getElementById('kb-panel')) {
                document.getElementById('kb-panel').remove();
            } else {
                if (CFG.sound && !audioCtx) initAudio();
                createPanel();
            }
        });
        btn.addEventListener('mouseenter', () => { btn.style.transform = 'scale(1.15)'; });
        btn.addEventListener('mouseleave', () => { btn.style.transform = 'scale(1)'; });
        document.body.appendChild(btn);
    }

    // ---------- ARABİRİM GÜNCELLEME ----------
    function updateUI() {
        const trigger = document.getElementById('kb-trigger');
        if (trigger) {
            trigger.style.borderColor = activeEffect.color;
            trigger.style.boxShadow = `0 0 15px ${activeEffect.glow}`;
            trigger.style.background = activeEffect.color === 'rainbow' ? '#333' : activeEffect.color+'22';
        }
        const panel = document.getElementById('kb-panel');
        if (panel) {
            panel.style.borderColor = activeEffect.color;
            panel.style.boxShadow = `0 15px 40px rgba(0,0,0,0.7), 0 0 20px ${activeEffect.glow}`;
            const title = panel.querySelector('div:first-child');
            if (title) title.style.color = activeEffect.color;
            // Butonların border ve background güncellemesi (opsiyonel)
            const btns = panel.querySelectorAll('button[data-effect]');
            btns.forEach(btn => {
                const key = btn.dataset.effect;
                const eff = EFFECTS[key];
                if (key === CFG.effect) {
                    btn.style.border = `1px solid ${eff.color}`;
                    btn.style.background = eff.color+'22';
                } else {
                    btn.style.border = '1px solid #444';
                    btn.style.background = '#222';
                }
            });
        }
    }

    // ---------- GÖKKUŞAĞI ODAK YÖNETİMİ ----------
    function initRainbowFocus() {
        if (activeEffect.color !== 'rainbow') return;
        const addClass = (e) => {
            if (e.target.matches('input, textarea, [contenteditable="true"]')) {
                e.target.classList.add('kb-rainbow-focus');
            }
        };
        const removeClass = (e) => {
            if (e.target.matches('input, textarea, [contenteditable="true"]')) {
                e.target.classList.remove('kb-rainbow-focus');
            }
        };
        document.addEventListener('focusin', addClass);
        document.addEventListener('focusout', removeClass);
    }

    // ---------- BAŞLAT ----------
    function init() {
        updateStyles();
        createTrigger();
        document.addEventListener('keydown', onKeyDown);
        initRainbowFocus();
        if (CFG.sound) initAudio();
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => setTimeout(init, 500));
    } else {
        setTimeout(init, 500);
    }
})();