From 48fabec43100f7a0610809c3e98155325a9e7b70 Mon Sep 17 00:00:00 2001 From: Sergey Krashevich Date: Sat, 13 Jan 2024 18:07:07 +0300 Subject: [PATCH 1/2] fix(clipboard): fix copy to clipboard functionality Added a `copyTextToClipboard` function to handle text copying across different browsers and fallback scenarios. This function utilizes the Clipboard API when available, providing an asynchronous method to copy text securely. For browsers where the Clipboard API is not available or the page is not served over a secure context, a fallback method using a temporary textarea element and `document.execCommand` is employed. Replaced direct use of `navigator.clipboard.writeText` with this function in the 'shareget' click event listener to enhance cross-browser support and error handling. --- www/links.html | 53 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/www/links.html b/www/links.html index bc9c08c3..a2f76f59 100644 --- a/www/links.html +++ b/www/links.html @@ -170,6 +170,57 @@ Telegram: rtmps://xxx-x.rtmp.t.me/s/xxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxx document.getElementById('sharedel').style.display = 'none'; } + function copyTextToClipboard(text) { + // Modern approach with the Clipboard API + if (navigator.clipboard && window.isSecureContext) { + // Navigator clipboard is available + navigator.clipboard.writeText(text).then(function() { + console.log('Async: Copying to clipboard was successful!'); + }, function(err) { + console.error('Async: Could not copy text: ', err); + }); + } else { + // Fallback using document.execCommand() + try { + // Create a temporary element to hold the text to copy + var textarea = document.createElement("textarea"); + // Make it almost invisible and uneditable + 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'; + + // Set the text content and append the textarea to the body + textarea.value = text; + document.body.appendChild(textarea); + + // Select all the text in the textarea + textarea.focus(); + textarea.select(); + + // Attempt to copy the text selected in the textarea + var successful = document.execCommand('copy'); + if (successful) { + console.log('Fallback: Copying text command was successful!'); + } else { + console.error('Fallback: Could not copy text'); + } + + // Cleanup - remove the temporary textarea + document.body.removeChild(textarea); + } catch (err) { + console.error('Fallback: Exception while trying to copy', err); + } + } + } + + document.getElementById('shareadd').addEventListener('click', ev => { ev.preventDefault(); share('POST').then(r => r.json()).then(r => onshareadd(r)); @@ -177,7 +228,7 @@ Telegram: rtmps://xxx-x.rtmp.t.me/s/xxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxx document.getElementById('shareget').addEventListener('click', ev => { ev.preventDefault(); - navigator.clipboard.writeText(ev.target.href); + copyTextToClipboard(ev.target.href); }); document.getElementById('sharedel').addEventListener('click', ev => { From a1983c725d14834cdcecb64519b2c8538ca50381 Mon Sep 17 00:00:00 2001 From: Alex X Date: Mon, 29 Apr 2024 11:54:00 +0300 Subject: [PATCH 2/2] Code refactoring after #878 --- www/links.html | 56 ++++++++++++++------------------------------------ 1 file changed, 15 insertions(+), 41 deletions(-) diff --git a/www/links.html b/www/links.html index 2e9c89ea..940de9fd 100644 --- a/www/links.html +++ b/www/links.html @@ -167,56 +167,30 @@ Telegram: rtmps://xxx-x.rtmp.t.me/s/xxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxx } function copyTextToClipboard(text) { - // Modern approach with the Clipboard API + // https://web.dev/patterns/clipboard/copy-text if (navigator.clipboard && window.isSecureContext) { - // Navigator clipboard is available - navigator.clipboard.writeText(text).then(function() { - console.log('Async: Copying to clipboard was successful!'); - }, function(err) { - console.error('Async: Could not copy text: ', err); + navigator.clipboard.writeText(text).catch(err => { + console.error(err.name, err.message); }); } else { - // Fallback using document.execCommand() + const textarea = document.createElement('textarea'); + textarea.value = text; + textarea.style.opacity = '0'; + document.body.appendChild(textarea); + + textarea.focus(); + textarea.select(); + try { - // Create a temporary element to hold the text to copy - var textarea = document.createElement("textarea"); - // Make it almost invisible and uneditable - 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'; - - // Set the text content and append the textarea to the body - textarea.value = text; - document.body.appendChild(textarea); - - // Select all the text in the textarea - textarea.focus(); - textarea.select(); - - // Attempt to copy the text selected in the textarea - var successful = document.execCommand('copy'); - if (successful) { - console.log('Fallback: Copying text command was successful!'); - } else { - console.error('Fallback: Could not copy text'); - } - - // Cleanup - remove the temporary textarea - document.body.removeChild(textarea); + document.execCommand('copy'); } catch (err) { - console.error('Fallback: Exception while trying to copy', err); + console.error(err.name, err.message); } + + document.body.removeChild(textarea); } } - document.getElementById('shareadd').addEventListener('click', ev => { ev.preventDefault(); share('POST').then(r => r.json()).then(r => onshareadd(r));