Keyboard Wizard - Text Effects

Effect Color Trace Sound

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

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