diff --git a/src/components/profile/editor-viewer.tsx b/src/components/profile/editor-viewer.tsx index d5d16495b..ece5f0b05 100644 --- a/src/components/profile/editor-viewer.tsx +++ b/src/components/profile/editor-viewer.tsx @@ -1,6 +1,7 @@ import MonacoEditor from "@monaco-editor/react"; import { CloseFullscreenRounded, + ContentPasteRounded, FormatPaintRounded, OpenInFullRounded, } from "@mui/icons-material"; @@ -347,6 +348,33 @@ export const EditorViewer = (props: Props) => { } }); + // Explicit paste action: works even when Monaco's context-menu paste cannot read clipboard. + const handlePaste = useLockFn(async () => { + try { + if (!editorRef.current || effectiveReadOnly) return; + const text = await navigator.clipboard.readText(); + if (!text) return; + const editor = editorRef.current; + const model = editor.getModel(); + const selections = editor.getSelections(); + if (!model || !selections || selections.length === 0) return; + // Group edits to allow single undo step + editor.pushUndoStop(); + editor.executeEdits( + "explicit-paste", + selections.map((sel) => ({ + range: sel, + text, + forceMoveMarkers: true, + })), + ); + editor.pushUndoStop(); + editor.focus(); + } catch (err) { + showNotice.error(err); + } + }); + const handleClose = useLockFn(async () => { try { onClose(); @@ -480,6 +508,16 @@ export const EditorViewer = (props: Props) => { variant="contained" sx={{ position: "absolute", left: "14px", bottom: "8px" }} > + handlePaste()} + > + +