您需要先安装一个扩展,例如 篡改猴、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);
- })();