您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Send with Ctrl+Enter in ChatGPT, Claude, Gemini, Copilot, Perplexity, and others.
当前为
// ==UserScript== // @name Chat UI Ctrl+Enter Sender // @namespace http://tampermonkey.net/ // @version 1.1 // @description Send with Ctrl+Enter in ChatGPT, Claude, Gemini, Copilot, Perplexity, and others. // @author Chippppp // @license MIT // @match *://*/* // @icon https://www.google.com/s2/favicons?sz=64&domain=chatgpt.com // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // ==/UserScript== (() => { "use strict"; const defaultDomains = [ "https://chatgpt.com", "https://claude.ai", "https://gemini.google.com", "https://www.bing.com", "https://www.perplexity.ai" ]; let domains = GM_getValue("domains", defaultDomains.slice()); GM_registerMenuCommand("Manage domains", () => { showDomainSettingsUI(domains); }); function showDomainSettingsUI(domains) { const dialog = document.createElement("dialog"); dialog.style.width = "400px"; dialog.style.height = "500px"; dialog.style.overflowY = "auto"; dialog.innerHTML = ` <form method="dialog" style="display: flex; flex-direction: column; height: 100%; padding: 10px;"> <h2 style="margin: 0 0 10px 0;">Domain Settings</h2> <div id="domain-list" style="margin-bottom: 10px; flex-grow: 1; overflow-y: auto; border: 1px solid #ccc; padding: 10px;"></div> <div style="margin-bottom: 10px; display: flex;"> <input id="new-domain-input" type="text" value="${location.origin}" style="flex-grow: 1; margin-right: 5px; padding: 5px; color: black; background-color: white; border: 1px solid #ccc;"> <button id="add-domain" type="button" style="padding: 5px;">Add domain</button> </div> <div style="margin-bottom: 10px;"> <button id="reset-domains" type="button" style="padding: 5px;">Reset to default</button> </div> <div style="text-align: right;"> <button id="close-dialog" type="submit" value="close" style="padding: 5px;">Close</button> </div> </form> `; document.body.appendChild(dialog); dialog.showModal(); dialog.getElementById("add-domain").addEventListener("click", () => { const newDomainInput = dialog.querySelector("#new-domain-input").value; if (!newDomainInput) { alert("Invalid input") } else if (!domains.includes(newDomainInput)) { domains.push(newDomainInput); GM_setValue("domains", domains); alert(`Domain added: ${newDomainInput}`); updateDomainList(dialog, domains); dialog.querySelector("#new-domain-input").value = location.origin; } else { alert(`Domain already exists: ${newDomainInput}`); } }); dialog.getElementById("reset-domains").addEventListener("click", () => { if (confirm("Are you sure you want to reset domains to default?")) { domains = defaultDomains.slice(); GM_setValue("domains", domains); alert("Domains have been reset to default."); updateDomainList(dialog, domains); dialog.querySelector("#new-domain-input").value = location.origin; } }); dialog.addEventListener("close", () => { dialog.remove(); }); updateDomainList(dialog, domains); } function createDomainItemHTML(domain) { return ` <div class="domain-item" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 5px;"> <span>${domain}</span> <div> <button class="edit-domain" data-domain="${domain}" style="margin-right: 5px;">Edit</button> <button class="remove-domain" data-domain="${domain}">Remove</button> </div> </div> `; } function updateDomainList(dialog, domains) { const domainList = dialog.querySelector("#domain-list"); domainList.innerHTML = domains.map(domain => createDomainItemHTML(domain)).join(""); domainList.querySelectorAll(".remove-domain").forEach(button => { button.addEventListener("click", (event) => { const domainToRemove = event.target.getAttribute("data-domain"); if (confirm(`Are you sure you want to remove ${domainToRemove}?`)) { const index = domains.indexOf(domainToRemove); if (index !== -1) { domains.splice(index, 1); GM_setValue("domains", domains); alert(`Domain removed: ${domainToRemove}`); } else { alert(`Domain not found: ${domainToRemove}`); } } updateDomainList(dialog, domains); }); }); domainList.querySelectorAll(".edit-domain").forEach(button => { button.addEventListener("click", (event) => { const domainToEdit = event.target.getAttribute("data-domain"); const newDomainName = prompt(`Edit domain: ${domainToEdit}`, domainToEdit); if (newDomainName === null) { updateDomainList(dialog, domains); return; } if (!newDomainName) { alert("Invalid input"); } else if (!domains.includes(newDomainName)) { const index = domains.indexOf(domainToEdit); if (index !== -1) { domains[index] = newDomainName; GM_setValue("domains", domains); alert(`Domain edited: ${domainToEdit} to ${newDomainName}`); } else { alert(`Domain not found: ${domainToEdit}`); } } else { alert(`Domain already exists: ${newDomainName}`); } updateDomainList(dialog, domains); }); }); } if (!domains.some(domain => location.origin === domain)) return; console.log("Chat UI Ctrl+Enter Sender Enabled"); window.addEventListener("keydown", e => { if (!e.key === "Enter" || e.ctrlKey) return; let target = e.composedPath ? e.composedPath()[0] || e.target : e.target; if (/INPUT|TEXTAREA|SELECT|LABEL/.test(target.tagName) || target.getAttribute && target.getAttribute("contenteditable") === "true") { event.stopPropagation(); } }, true); })();