Greasy Fork

来自缓存

Greasy Fork is available in English.

阻止claude输入发送

解决在输入法状态下按Enter键导致消息直接发送的问题;Solve the problem that pressing the Enter key in the input method state causes the message to be sent directly.

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        阻止claude输入发送
// @description 解决在输入法状态下按Enter键导致消息直接发送的问题;Solve the problem that pressing the Enter key in the input method state causes the message to be sent directly.
// @match       https://claude.ai/*
// @author       sinoftj
// @version      2.0
// @namespace http://greasyfork.icu/users/1457414
// ==/UserScript==

(function() {
    'use strict';
    
    // 输入法状态追踪
    let imeActive = false;
    let lastImeEndTime = 0;
    const IME_BUFFER_TIME = 5; // 输入法结束后的缓冲时间(毫秒)
    
    // 检查是否处于输入法状态
    function isInImeContext(e) {
        return imeActive || 
               e.isComposing || 
               e.keyCode === 229 || 
               (Date.now() - lastImeEndTime < IME_BUFFER_TIME);
    }
    
    // 处理输入法事件
    document.addEventListener('compositionstart', function() {
        imeActive = true;
    }, true);
    
    document.addEventListener('compositionend', function() {
        lastImeEndTime = Date.now();
        setTimeout(() => { imeActive = false; }, IME_BUFFER_TIME);
    }, true);
    
    // 拦截Enter键事件 - 捕获阶段
    document.addEventListener('keydown', function(e) {
        if ((e.key === 'Enter' || e.keyCode === 13) && isInImeContext(e)) {
            e.stopImmediatePropagation();
            e.preventDefault();
            return false;
        }
    }, true);
    
    // 备份保护:keypress事件拦截
    document.addEventListener('keypress', function(e) {
        if ((e.key === 'Enter' || e.keyCode === 13) && isInImeContext(e)) {
            e.stopImmediatePropagation();
            e.preventDefault();
            return false;
        }
    }, true);
    
    // 处理标准输入框元素
    function protectInputElement(input) {
        const originalKeyDown = input.onkeydown;
        input.onkeydown = function(e) {
            if ((e.key === 'Enter' || e.keyCode === 13) && isInImeContext(e)) {
                e.stopPropagation();
                e.preventDefault();
                return false;
            }
            if (originalKeyDown) return originalKeyDown.call(this, e);
        };
    }
    
    // 处理contenteditable元素(特别是富文本编辑器)
    function protectContentEditableElement(element) {
        // 为contenteditable元素添加直接事件监听
        element.addEventListener('keydown', function(e) {
            if ((e.key === 'Enter' || e.keyCode === 13) && isInImeContext(e)) {
                e.stopPropagation();
                e.preventDefault();
                return false;
            }
        }, true); // 使用捕获模式,确保在事件被其他处理器捕获前拦截
        
        // 查找并处理可能嵌套的ProseMirror编辑器
        const proseMirrors = element.querySelectorAll('.ProseMirror');
        if (proseMirrors.length > 0) {
            proseMirrors.forEach(editor => {
                editor.addEventListener('keydown', function(e) {
                    if ((e.key === 'Enter' || e.keyCode === 13) && isInImeContext(e)) {
                        e.stopPropagation();
                        e.preventDefault();
                        return false;
                    }
                }, true);
            });
        }
    }
    
    // 处理所有可能的编辑元素
    function protectElement(element) {
        if (!element) return;
        
        if (element.tagName === 'TEXTAREA' || 
            (element.tagName === 'INPUT' && element.type === 'text')) {
            protectInputElement(element);
        } 
        else if (element.getAttribute('contenteditable') === 'true') {
            protectContentEditableElement(element);
        }
        // 特殊处理ProseMirror编辑器
        else if (element.classList && element.classList.contains('ProseMirror')) {
            protectContentEditableElement(element);
        }
    }
    
    // 直接监听iframe中的事件(如果有)
    function setupIframeProtection() {
        try {
            const iframes = document.querySelectorAll('iframe');
            iframes.forEach(iframe => {
                try {
                    if (iframe.contentDocument) {
                        iframe.contentDocument.addEventListener('keydown', function(e) {
                            if ((e.key === 'Enter' || e.keyCode === 13) && isInImeContext(e)) {
                                e.stopPropagation();
                                e.preventDefault();
                                return false;
                            }
                        }, true);
                        
                        iframe.contentDocument.addEventListener('compositionstart', function() {
                            imeActive = true;
                        }, true);
                        
                        iframe.contentDocument.addEventListener('compositionend', function() {
                            lastImeEndTime = Date.now();
                            setTimeout(() => { imeActive = false; }, IME_BUFFER_TIME);
                        }, true);
                    }
                } catch (err) {
                    // 跨域iframe访问可能会失败,忽略错误
                }
            });
        } catch (err) {
            console.error('处理iframe时出错:', err);
        }
    }
    
    // 页面加载后处理现有输入元素
    function initializeProtection() {
        // 保护标准输入元素
        document.querySelectorAll('textarea, input[type="text"]').forEach(protectInputElement);
        
        // 保护contenteditable元素
        document.querySelectorAll('[contenteditable="true"]').forEach(protectContentEditableElement);
        
        // 特别处理ProseMirror编辑器
        document.querySelectorAll('.ProseMirror').forEach(protectContentEditableElement);
        
        // 设置iframe保护
        setupIframeProtection();
        
        // 监控DOM变化,处理新添加的输入元素
        if (window.MutationObserver) {
            const observer = new MutationObserver((mutations) => {
                mutations.forEach((mutation) => {
                    if (mutation.addedNodes && mutation.addedNodes.length > 0) {
                        mutation.addedNodes.forEach((node) => {
                            if (node.nodeType === 1) { // 元素节点
                                protectElement(node);
                                
                                // 处理节点内的所有可能输入元素
                                if (node.querySelectorAll) {
                                    const inputs = node.querySelectorAll('textarea, input[type="text"], [contenteditable="true"], .ProseMirror');
                                    if (inputs.length > 0) {
                                        inputs.forEach(input => protectElement(input));
                                    }
                                }
                            }
                        });
                    }
                    
                    // 特别检查属性变化,以防contenteditable状态变化
                    if (mutation.type === 'attributes' && 
                        mutation.attributeName === 'contenteditable' &&
                        mutation.target.getAttribute('contenteditable') === 'true') {
                        protectContentEditableElement(mutation.target);
                    }
                });
                
                // 检查是否有新的iframe添加
                setupIframeProtection();
            });
            
            observer.observe(document.body, {
                childList: true,
                subtree: true,
                attributes: true,
                attributeFilter: ['contenteditable']
            });
        }
    }
    
    // 确保在DOM完全加载后执行,并给予足够时间加载任何动态内容
    if (document.readyState === 'loading') {
        window.addEventListener('DOMContentLoaded', () => setTimeout(initializeProtection, 1000));
    } else {
        setTimeout(initializeProtection, 1000);
    }
    
    // 监听动态加载的页面部分,比如单页应用的视图变化
    window.addEventListener('load', () => setTimeout(initializeProtection, 1500));
    
    // 监听可能的路由变化(用于SPA应用)
    window.addEventListener('popstate', () => setTimeout(initializeProtection, 500));
    document.addEventListener('visibilitychange', () => {
        if (!document.hidden) setTimeout(initializeProtection, 500);
    });
    
    // 初次执行,尽快保护可能存在的元素
    setTimeout(initializeProtection, 300);
})();