Bladeren bron

Move copy into clipboard functionality into its own helper

Lennart Grahl 6 jaren geleden
bovenliggende
commit
96d3b145aa
2 gewijzigde bestanden met toevoegingen van 73 en 32 verwijderingen
  1. 8 32
      src/directives/message.ts
  2. 65 0
      src/helpers/clipboard.ts

+ 8 - 32
src/directives/message.ts

@@ -19,6 +19,8 @@
 
 import {saveAs} from 'file-saver';
 
+import * as clipboard from '../helpers/clipboard';
+
 import {BrowserInfo} from '../helpers/browser_info';
 import {getSenderIdentity} from '../helpers/messages';
 import {BrowserService} from '../services/browser';
@@ -120,40 +122,14 @@ export default [
                             return;
                         }
 
-                        // In order to copy the text to the clipboard,
-                        // put it into a temporary textarea element.
-                        const textArea = document.createElement('textarea');
-                        textArea.value = text;
-                        document.body.appendChild(textArea);
-
-                        if ((this.browserInfo as BrowserInfo).isSafari()) {
-                            // Safari: Create a selection range.
-                            // Inspiration: https://stackoverflow.com/a/34046084/284318
-                            textArea.contentEditable = 'true';
-                            textArea.readOnly = false;
-                            const range = document.createRange();
-                            const selection = self.getSelection();
-                            selection.removeAllRanges();
-                            selection.addRange(range);
-                            textArea.setSelectionRange(0, 999999);
-                        } else {
-                            textArea.focus();
-                            textArea.select();
-                        }
-
-                        // Copy selection to clipboard
-                        let toastString = 'messenger.COPY_ERROR';
+                        // Copy to clipboard
+                        let toastString = 'messenger.COPIED';
                         try {
-                            const successful = document.execCommand('copy');
-                            if (!successful) {
-                                log.warn('Could not copy text to clipboard');
-                            } else {
-                                toastString = 'messenger.COPIED';
-                            }
-                        } catch (err) {
-                            log.warn('Could not copy text to clipboard:', err);
+                            clipboard.copyString(text, (this.browserInfo as BrowserInfo).isSafari());
+                        } catch (error) {
+                            log.warn('Could not copy text to clipboard:', error);
+                            toastString = 'messenger.COPY_ERROR';
                         }
-                        document.body.removeChild(textArea);
 
                         // Show toast
                         const toast = $mdToast.simple()

+ 65 - 0
src/helpers/clipboard.ts

@@ -0,0 +1,65 @@
+/**
+ * This file is part of Threema Web.
+ *
+ * Threema Web is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Threema Web. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Copy a string into the clipboard.
+ *
+ * @param text The string to be copied.
+ * @param useSelectionRange whether a selection range should be used. Required
+ *   for Safari.
+ *
+ * Throws an error in case it was unsuccessful.
+ */
+export function copyString(text: string, useSelectionRange: boolean = false): void {
+    const activeElement = document.activeElement as HTMLElement | null;
+
+    // Create temporary (and hidden) textarea element
+    const textArea = document.createElement('textarea');
+    textArea.value = text;
+    textArea.style.visibility = 'hidden';
+    document.body.appendChild(textArea);
+    try {
+        // Copy the text into the textarea element and select the text
+        if (useSelectionRange) {
+            // Safari: Create a selection range.
+            // Inspiration: https://stackoverflow.com/a/34046084/284318
+            textArea.contentEditable = 'true';
+            textArea.readOnly = false;
+            const range = document.createRange();
+            const selection = self.getSelection();
+            selection.removeAllRanges();
+            selection.addRange(range);
+            textArea.setSelectionRange(0, 999999);
+        } else {
+            textArea.focus();
+            textArea.select();
+        }
+
+        // Copy selection to clipboard
+        if (!document.execCommand('copy')) {
+            throw new Error('Unable to copy into clipboard');
+        }
+    } finally {
+        // Remove temporary textarea element
+        document.body.removeChild(textArea);
+
+        // Restore focus to the previously active element (if any)
+        if (activeElement !== null) {
+            activeElement.focus();
+        }
+    }
+}