浏览代码

fix: allow copying text outside the component (#3275)

David Luzar 4 年之前
父节点
当前提交
add1785ace
共有 2 个文件被更改,包括 25 次插入1 次删除
  1. 2 1
      src/actions/actionClipboard.tsx
  2. 23 0
      src/components/App.tsx

+ 2 - 1
src/actions/actionClipboard.tsx

@@ -17,7 +17,8 @@ export const actionCopy = register({
     };
   },
   contextItemLabel: "labels.copy",
-  keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.code === CODES.C,
+  // don't supply a shortcut since we handle this conditionally via onCopy event
+  keyTest: undefined,
 });
 
 export const actionCut = register({

+ 23 - 0
src/components/App.tsx

@@ -1047,6 +1047,21 @@ class App extends React.Component<ExcalidrawProps, AppState> {
   });
 
   private onCopy = withBatchedUpdates((event: ClipboardEvent) => {
+    const activeSelection = document.getSelection();
+    // if there's a selected text is outside the component, prevent our copy
+    // action
+    if (
+      activeSelection?.anchorNode &&
+      // it can happen that certain interactions will create a selection
+      // outside (or potentially inside) the component without actually
+      // selecting anything (i.e. the selection range is collapsed). Copying
+      // in such case wouldn't copy anything to the clipboard anyway, so prevent
+      // our copy handler only if the selection isn't collapsed
+      !activeSelection.isCollapsed &&
+      !this.excalidrawContainerRef.current!.contains(activeSelection.anchorNode)
+    ) {
+      return;
+    }
     if (isWritableElement(event.target)) {
       return;
     }
@@ -2118,6 +2133,14 @@ class App extends React.Component<ExcalidrawProps, AppState> {
   ) => {
     event.persist();
 
+    // remove any active selection when we start to interact with canvas
+    // (mainly, we care about removing selection outside the component which
+    //  would prevent our copy handling otherwise)
+    const selection = document.getSelection();
+    if (selection?.anchorNode) {
+      selection.removeAllRanges();
+    }
+
     this.maybeOpenContextMenuAfterPointerDownOnTouchDevices(event);
     this.maybeCleanupAfterMissingPointerUp(event);