// ==UserScript== // @name 🖱右键快速复制/粘贴文本(Common Right Click Copy) // @namespace xiaohuohumax/userscripts/common-right-click-copy // @version 1.1.0 // @author xiaohuohumax // @description 用户可以通过右键点击选中的文本,快速复制到剪贴板,然后在输入框中右键即可快速粘贴剪贴板的文本(PS:对应复制限制的网站暂不支持)。 // @license MIT // @icon https://raw.githubusercontent.com/xiaohuohumax/logo/refs/heads/main/logos/logo.svg // @source https://github.com/xiaohuohumax/userscripts.git // @match http*://*/* // @require https://unpkg.com/sweetalert2@11.15.9/dist/sweetalert2.all.min.js // @grant GM_addValueChangeListener // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_setClipboard // @grant GM_setValue // @run-at document-start // @noframes // @downloadURL https://update.greasyfork.icu/scripts/532794/%F0%9F%96%B1%E5%8F%B3%E9%94%AE%E5%BF%AB%E9%80%9F%E5%A4%8D%E5%88%B6%E7%B2%98%E8%B4%B4%E6%96%87%E6%9C%AC%EF%BC%88Common%20Right%20Click%20Copy%EF%BC%89.user.js // @updateURL https://update.greasyfork.icu/scripts/532794/%F0%9F%96%B1%E5%8F%B3%E9%94%AE%E5%BF%AB%E9%80%9F%E5%A4%8D%E5%88%B6%E7%B2%98%E8%B4%B4%E6%96%87%E6%9C%AC%EF%BC%88Common%20Right%20Click%20Copy%EF%BC%89.meta.js // ==/UserScript== (function (Swal) { 'use strict'; var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); var _GM_addValueChangeListener = /* @__PURE__ */ (() => typeof GM_addValueChangeListener != "undefined" ? GM_addValueChangeListener : void 0)(); var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)(); var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)(); var _GM_setClipboard = /* @__PURE__ */ (() => typeof GM_setClipboard != "undefined" ? GM_setClipboard : void 0)(); var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)(); const ID = "common-right-click-copy"; const VERSION = "1.1.0"; const LAST_VERSION = 1; class Store { constructor() { __publicField(this, "config", null); __publicField(this, "ID", `${ID}-config`); __publicField(this, "listeners", []); this.loadConfig(); _GM_addValueChangeListener(this.ID, (_key, _oldValue, newValue, remote) => { if (remote) { this.config = this.configFormat(newValue); this.listeners.forEach((listener) => listener(this.config)); } }); } loadConfig() { const config = _GM_getValue(this.ID, void 0); this.config = this.configFormat(config); !config && this.saveConfig(); console.log("加载配置:", this.config); } saveConfig() { _GM_setValue(this.ID, this.config); this.listeners.forEach((listener) => listener(this.config)); } addConfigChangeListener(listener) { this.listeners.push(listener); } configFormat(data) { const config = { version: LAST_VERSION, enableCopy: true, enablePaste: true, copyTrigger: "double", pasteTrigger: "double" }; if (!data) { return config; } if (data.version === 0) ; return Object.assign(config, data); } get copyTrigger() { return this.config.copyTrigger; } set copyTrigger(value) { this.config.copyTrigger = value; this.saveConfig(); } get pasteTrigger() { return this.config.pasteTrigger; } set pasteTrigger(value) { this.config.pasteTrigger = value; this.saveConfig(); } get enableCopy() { return this.config.enableCopy; } set enableCopy(value) { this.config.enableCopy = value; this.saveConfig(); } get enablePaste() { return this.config.enablePaste; } set enablePaste(value) { this.config.enablePaste = value; this.saveConfig(); } } const Toast = Swal.mixin({ toast: true, position: "top-end", showConfirmButton: false, timer: 3e3, timerProgressBar: true, didOpen: (toast) => { toast.onmouseenter = Swal.stopTimer; toast.onmouseleave = Swal.resumeTimer; } }); class View { constructor(store2) { __publicField(this, "config", async () => { const { isConfirmed, value } = await Swal.fire({ title: "设置", html: `
是否启用右键复制功能:
复制触发模式:
是否启用右键粘贴功能:
粘贴触发模式:
`, willOpen: (popup) => { const copyTriggerMode = popup.querySelector("#copy-trigger-mode"); const pasteTriggerMode = popup.querySelector("#paste-trigger-mode"); copyTriggerMode.value = this.store.copyTrigger; pasteTriggerMode.value = this.store.pasteTrigger; const enableCopy = popup.querySelector(`input[name="enable-copy"][value="${this.store.enableCopy}"]`); enableCopy.checked = true; const enablePaste = popup.querySelector(`input[name="enable-paste"][value="${this.store.enablePaste}"]`); enablePaste.checked = true; }, preConfirm: () => { const copyTriggerMode = document.getElementById("copy-trigger-mode"); const pasteTriggerMode = document.getElementById("paste-trigger-mode"); const enableCopy = document.querySelector(`input[name="enable-copy"]:checked`); const enablePaste = document.querySelector(`input[name="enable-paste"]:checked`); return { copyTriggerMode: copyTriggerMode.value, pasteTriggerMode: pasteTriggerMode.value, enableCopy: enableCopy.value === "true", enablePaste: enablePaste.value === "true" }; }, showCancelButton: true, confirmButtonText: "保存", cancelButtonText: "取消" }); if (!isConfirmed) { await Toast.fire({ icon: "warning", title: "已取消设置" }); return; } this.store.copyTrigger = value.copyTriggerMode; this.store.pasteTrigger = value.pasteTriggerMode; this.store.enableCopy = value.enableCopy; this.store.enablePaste = value.enablePaste; await Toast.fire({ icon: "success", title: "设置已保存" }); }); this.store = store2; } } const THRESHOLD = 300; const CLEANED = 0; let timer = CLEANED; const store = new Store(); const view = new View(store); console.log(`${ID}(v${VERSION})`); function copy(selection) { selection && _GM_setClipboard(selection, "text", () => { Toast.fire({ icon: "success", title: "复制成功" }); }); } async function paste(target, isContenteditable, isInput) { const clipboardContext = await navigator.clipboard.readText(); if (isContenteditable) { const range = window.getSelection().getRangeAt(0); range.deleteContents(); range.insertNode(document.createTextNode(clipboardContext)); } else if (isInput && (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement)) { target.value = clipboardContext.trim(); } } document.addEventListener("contextmenu", async (e) => { var _a; const target = e.target; if (!target) { return; } const selection = (_a = window.getSelection()) == null ? void 0 : _a.toString(); const isContenteditable = target.hasAttribute("contenteditable"); const isInput = target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement; const isCopy = !!selection && !isInput; const isPaste = isInput || isContenteditable; if (!(isCopy && store.enableCopy || isPaste && store.enablePaste)) { return; } if (timer > CLEANED) { clearTimeout(timer); timer = CLEANED; if (store.copyTrigger === "double" && isCopy) { e.preventDefault(); copy(selection); return; } if (store.pasteTrigger === "double" && isPaste) { e.preventDefault(); paste(target, isContenteditable, isInput); return; } return; } if (store.copyTrigger === "single") { e.preventDefault(); } timer = setTimeout(() => { timer = CLEANED; if (store.copyTrigger === "single" && isCopy) { copy(selection); return; } if (store.pasteTrigger === "single" && isPaste) { paste(target, isContenteditable, isInput); } }, THRESHOLD); }); _GM_registerMenuCommand("修改配置", view.config); })(Swal);