diff --git a/superset-frontend/src/utils/common.js b/superset-frontend/src/utils/common.js index 9c98739d225c..603ec7c54992 100644 --- a/superset-frontend/src/utils/common.js +++ b/superset-frontend/src/utils/common.js @@ -145,4 +145,10 @@ export const detectOS = () => { return 'Unknown OS'; }; +export const isSafari = () => { + const { userAgent } = navigator; + + return userAgent && /^((?!chrome|android).)*safari/i.test(userAgent); +}; + export const isNullish = value => value === null || value === undefined; diff --git a/superset-frontend/src/utils/copy.ts b/superset-frontend/src/utils/copy.ts index f6895c8a7f33..0980f2ab1707 100644 --- a/superset-frontend/src/utils/copy.ts +++ b/superset-frontend/src/utils/copy.ts @@ -17,21 +17,29 @@ * under the License. */ +import { isSafari } from './common'; + // Use the new Clipboard API if the browser supports it const copyTextWithClipboardApi = async (getText: () => Promise) => { - try { - // Safari (WebKit) does not support delayed generation of clipboard. - // This means that writing to the clipboard, from the moment the user - // interacts with the app, must be instantaneous. - // However, neither writeText nor write accepts a Promise, so - // we need to create a ClipboardItem that accepts said Promise to - // delay the text generation, as needed. - // Source: https://bugs.webkit.org/show_bug.cgi?id=222262 - const clipboardItem = new ClipboardItem({ - 'text/plain': getText(), - }); - await navigator.clipboard.write([clipboardItem]); - } catch { + // Safari (WebKit) does not support delayed generation of clipboard. + // This means that writing to the clipboard, from the moment the user + // interacts with the app, must be instantaneous. + // However, neither writeText nor write accepts a Promise, so + // we need to create a ClipboardItem that accepts said Promise to + // delay the text generation, as needed. + // Source: https://bugs.webkit.org/show_bug.cgi?id=222262P + if (isSafari()) { + try { + const clipboardItem = new ClipboardItem({ + 'text/plain': getText(), + }); + await navigator.clipboard.write([clipboardItem]); + } catch { + // Fallback to default clipboard API implementation + const text = await getText(); + await navigator.clipboard.writeText(text); + } + } else { // For Blink, the above method won't work, but we can use the // default (intended) API, since the delayed generation of the // clipboard is now supported.