Explorar o código

Merge pull request #770 from smiclea/refactor-clipboard

Refactor clipboard copy and notification handling
Daniel Vincze %!s(int64=2) %!d(string=hai) anos
pai
achega
6166751a13

+ 6 - 9
src/components/modules/EndpointModule/ChooseProvider/MultipleUploadedEndpoints.tsx

@@ -24,7 +24,6 @@ import EndpointLogos from "@src/components/modules/EndpointModule/EndpointLogos"
 import LoadingButton from "@src/components/ui/LoadingButton";
 
 import DomUtils from "@src/utils/DomUtils";
-import notificationStore from "@src/stores/NotificationStore";
 import DropdownLink from "@src/components/ui/Dropdowns/DropdownLink";
 import { Region } from "@src/@types/Region";
 import deleteHoverImage from "./images/delete-hover.svg";
@@ -134,15 +133,13 @@ class MultipleUploadedEndpoints extends React.Component<Props, State> {
   }
 
   copyErrorMessae(e: React.MouseEvent<HTMLDivElement>, message: string) {
-    if (e && e.stopPropagation) e.stopPropagation();
+    if (e?.stopPropagation) e.stopPropagation();
 
-    const succesful = DomUtils.copyTextToClipboard(message);
-
-    if (succesful) {
-      notificationStore.alert("The message has been copied to clipboard.");
-    } else {
-      notificationStore.alert("The message couldn't be copied", "error");
-    }
+    DomUtils.copyTextToClipboard(
+      message,
+      "The message has been copied to clipboard",
+      "Failed to copy the message to clipboard"
+    );
   }
 
   renderButtons() {

+ 4 - 7
src/components/modules/EndpointModule/EndpointModal/EndpointModal.tsx

@@ -323,14 +323,11 @@ class EndpointModal extends React.Component<Props, State> {
     if (!endpointStore.validation) {
       return;
     }
-
-    const succesful = DomUtils.copyTextToClipboard(
-      endpointStore.validation.message
+    DomUtils.copyTextToClipboard(
+      endpointStore.validation.message,
+      "The message has been copied to clipboard",
+      "Failed to copy the message to clipboard"
     );
-
-    if (succesful) {
-      notificationStore.alert("The message has been copied to clipboard.");
-    }
   }
 
   handleCancelClick() {

+ 1 - 12
src/components/modules/EndpointModule/EndpointValidation/EndpointValidation.tsx

@@ -23,7 +23,6 @@ import StatusImage from "@src/components/ui/StatusComponents/StatusImage";
 import { ThemePalette } from "@src/components/Theme";
 import type { Validation as ValidationType } from "@src/@types/Endpoint";
 
-import notificationStore from "@src/stores/NotificationStore";
 import DomUtils from "@src/utils/DomUtils";
 
 const Wrapper = styled.div<any>`
@@ -79,16 +78,6 @@ type Props = {
 };
 @observer
 class EndpointValidation extends React.Component<Props> {
-  handleCopyClick(message: string) {
-    const succesful = DomUtils.copyTextToClipboard(message);
-
-    if (succesful) {
-      notificationStore.alert("The value has been copied to clipboard.");
-    } else {
-      notificationStore.alert("The value couldn't be copied", "error");
-    }
-  }
-
   renderLoading() {
     if (!this.props.loading) {
       return null;
@@ -144,7 +133,7 @@ class EndpointValidation extends React.Component<Props> {
           <Title>Validation Failed</Title>
           <Error
             onClick={() => {
-              this.handleCopyClick(message);
+              DomUtils.copyTextToClipboard(message);
             }}
           >
             {message}

+ 5 - 6
src/components/modules/TransferModule/TaskItem/TaskItem.tsx

@@ -24,7 +24,6 @@ import StatusPill from "@src/components/ui/StatusComponents/StatusPill";
 import CopyValue from "@src/components/ui/CopyValue";
 import ProgressBar from "@src/components/ui/ProgressBar";
 import CopyButton from "@src/components/ui/CopyButton";
-import notificationStore from "@src/stores/NotificationStore";
 import DomUtils from "@src/utils/DomUtils";
 import { ThemePalette, ThemeProps } from "@src/components/Theme";
 import DateUtils from "@src/utils/DateUtils";
@@ -236,11 +235,11 @@ class TaskItem extends React.Component<Props> {
   }
 
   handleExceptionTextClick(exceptionText: string) {
-    const succesful = DomUtils.copyTextToClipboard(exceptionText);
-
-    if (succesful) {
-      notificationStore.alert("The message has been copied to clipboard.");
-    }
+    DomUtils.copyTextToClipboard(
+      exceptionText,
+      "The message has been copied to clipboard",
+      "Failed to copy the message to clipboard"
+    );
   }
 
   renderHeader() {

+ 1 - 6
src/components/ui/CopyMultilineValue/CopyMultilineValue.tsx

@@ -18,7 +18,6 @@ import styled from "styled-components";
 
 import CopyButton from "@src/components/ui/CopyButton";
 import DomUtils from "@src/utils/DomUtils";
-import notificationStore from "@src/stores/NotificationStore";
 
 const CopyButtonStyled = styled(CopyButton)`
   background-position-y: 4px;
@@ -49,12 +48,8 @@ class CopyMultineValue extends React.Component<Props> {
       value = value.replace(/<br\s*\/>/g, "\n").replace(/<.*?>/g, "");
     }
 
-    const succesful = DomUtils.copyTextToClipboard(value);
+    DomUtils.copyTextToClipboard(value);
     if (this.props.onCopy) this.props.onCopy(value);
-
-    if (succesful) {
-      notificationStore.alert("The message has been copied to clipboard.");
-    }
   }
 
   render() {

+ 1 - 8
src/components/ui/CopyValue/CopyValue.tsx

@@ -18,7 +18,6 @@ import styled, { css } from "styled-components";
 
 import CopyButton from "@src/components/ui/CopyButton";
 import DomUtils from "@src/utils/DomUtils";
-import notificationStore from "@src/stores/NotificationStore";
 
 const Wrapper = styled.div<any>`
   cursor: pointer;
@@ -57,14 +56,8 @@ class CopyValue extends React.Component<Props> {
   handleCopyIdClick(e: React.MouseEvent<HTMLDivElement>) {
     if (e && e.stopPropagation) e.stopPropagation();
 
-    const succesful = DomUtils.copyTextToClipboard(this.props.value);
+    DomUtils.copyTextToClipboard(this.props.value);
     if (this.props.onCopy) this.props.onCopy(this.props.value);
-
-    if (succesful) {
-      notificationStore.alert("The value has been copied to clipboard.");
-    } else {
-      notificationStore.alert("The value couldn't be copied", "error");
-    }
   }
 
   render() {

+ 15 - 27
src/utils/DomUtils.ts

@@ -13,6 +13,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 import { Base64 } from "js-base64";
+import notificationStore from "@src/stores/NotificationStore";
 
 class DomUtils {
   static getScrollableParent(
@@ -90,37 +91,24 @@ class DomUtils {
   /**
    * Copies specified text to clipboard
    * @param {string} text The text to copy
+   * @param {string} successMessage The message to display on success
+   * @param {string} errorMessage The message to display on error
    * @return True if successful, false otherwise
    */
-  static copyTextToClipboard(text: string): boolean {
-    const textArea = document.createElement("textarea");
-    textArea.style.position = "fixed";
-    textArea.style.top = "0";
-    textArea.style.left = "0";
-    textArea.style.width = "2em";
-    textArea.style.height = "2em";
-    textArea.style.padding = "0";
-    textArea.style.border = "none";
-    textArea.style.outline = "none";
-    textArea.style.boxShadow = "none";
-    textArea.style.background = "transparent";
-
-    textArea.value = text;
-
-    if (document.body) document.body.appendChild(textArea);
-
-    textArea.select();
-
-    let successful;
-
+  static async copyTextToClipboard(
+    text: string,
+    successMessage = "The value has been copied to clipboard",
+    errorMessage = "Failed to copy the value to clipboard"
+  ): Promise<boolean> {
     try {
-      successful = document.execCommand("copy");
-    } catch (e) {
-      successful = false;
-    } finally {
-      if (document.body) document.body.removeChild(textArea);
+      await navigator.clipboard.writeText(text);
+      notificationStore.alert(successMessage);
+      return true;
+    } catch (err) {
+      console.error("Failed to copy text: ", err);
+      notificationStore.alert(errorMessage, "error");
+      return false;
     }
-    return successful;
   }
 
   static download(text: string, fileName: string) {