From f7ca1b11884466ebfd931438664c299975646d60 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Thu, 7 May 2026 18:23:47 +0900 Subject: [PATCH] =?UTF-8?q?fix(Editor):=20=E8=A7=A3=E5=86=B3=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E5=88=97=E5=8A=9F=E8=83=BD=E5=A4=B1=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../options/routes/script/ScriptEditor.tsx | 99 ++++++++++++++++++- 1 file changed, 94 insertions(+), 5 deletions(-) diff --git a/src/pages/options/routes/script/ScriptEditor.tsx b/src/pages/options/routes/script/ScriptEditor.tsx index 1b3722f50..9cac91079 100644 --- a/src/pages/options/routes/script/ScriptEditor.tsx +++ b/src/pages/options/routes/script/ScriptEditor.tsx @@ -245,6 +245,95 @@ function ScriptEditor() { setTimeout(editor.focus.bind(editor), delayMs); } }; + const getSelectedText = (editor: editor.ICodeEditor) => { + const model = editor.getModel(); + if (!model) return ""; + + const selections = editor.getSelections()?.filter((selection) => !selection.isEmpty()) || []; + return selections.map((selection) => model.getValueInRange(selection)).join(model.getEOL()); + }; + const writeClipboardText = async (text: string) => { + if (navigator.clipboard?.writeText) { + try { + await navigator.clipboard.writeText(text); + return; + } catch { + // Fall through to execCommand fallback below. + } + } + + const textarea = document.createElement("textarea"); + textarea.value = text; + textarea.style.position = "fixed"; + textarea.style.left = "-9999px"; + textarea.style.top = "-9999px"; + document.body.appendChild(textarea); + textarea.focus(); + textarea.select(); + const ok = document.execCommand("copy"); + textarea.remove(); + if (!ok) throw new Error("copy failed"); + }; + const copyEditorSelection = (editor: editor.ICodeEditor) => { + const text = getSelectedText(editor); + if (!text) return; + writeClipboardText(text) + .catch((err) => { + LoggerCore.logger(Logger.E(err)).debug("copy editor selection error"); + }) + .finally(() => { + editor.focus(); + }); + }; + const cutEditorSelection = (editor: editor.ICodeEditor) => { + const text = getSelectedText(editor); + const selections = editor.getSelections()?.filter((selection) => !selection.isEmpty()) || []; + if (!text || !selections.length) return; + writeClipboardText(text) + .then(() => { + editor.pushUndoStop(); + editor.executeEdits( + "menu", + selections.map((selection) => ({ range: selection, text: "" })) + ); + editor.pushUndoStop(); + }) + .catch((err) => { + LoggerCore.logger(Logger.E(err)).debug("cut editor selection error"); + }) + .finally(() => { + editor.focus(); + }); + }; + const pasteEditorClipboard = (editor: editor.ICodeEditor) => { + if (!navigator.clipboard?.readText) { + editor.focus(); + editor.getAction("editor.action.clipboardPasteAction")?.run(); + return; + } + navigator.clipboard + .readText() + .then((text) => { + if (!text) return; + editor.focus(); + editor.trigger("keyboard", "paste", { + text, + pasteOnNewLine: false, + multicursorText: null, + mode: null, + }); + }) + .catch((err) => { + LoggerCore.logger(Logger.E(err)).debug("paste editor clipboard error"); + editor.focus(); + editor.getAction("editor.action.clipboardPasteAction")?.run(); + }); + }; + const triggerEditorCommand = (editor: editor.ICodeEditor, handlerId: string) => { + editor.focus(); + editor.trigger("menu", handlerId, null); + requestAnimationFrame(() => editor.focus()); + }; const [scriptList, setScriptList] = useState([]); const [currentScript, setCurrentScript] = useState