Keyboard Wizard - Text Effects

Effect Color Trace Sound

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

You will need to install an extension such as Tampermonkey to install this script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

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