From a2f2bfb1af745060db551643d723706d8538cc19 Mon Sep 17 00:00:00 2001 From: Ken Sternberg Date: Thu, 19 Oct 2023 13:31:22 -0700 Subject: [PATCH] web: isolate clipboard handling We would like to use the clipboard for more than just the token copy button. This commit enables that by separating the "Write to Clipboard" and "Write to Notifications" routines into separate functions, putting "writeToClipboard" into the utilities collection, and clarifying what happens when a custom presses the TokenCopy button. --- .../TokenCopyButton/ak-token-copy-button.ts | 45 ++++++++----------- web/src/elements/utils/writeToClipboard.ts | 26 +++++++++++ 2 files changed, 45 insertions(+), 26 deletions(-) create mode 100644 web/src/elements/utils/writeToClipboard.ts diff --git a/web/src/elements/buttons/TokenCopyButton/ak-token-copy-button.ts b/web/src/elements/buttons/TokenCopyButton/ak-token-copy-button.ts index d12bb4db69fb..0b09716146b9 100644 --- a/web/src/elements/buttons/TokenCopyButton/ak-token-copy-button.ts +++ b/web/src/elements/buttons/TokenCopyButton/ak-token-copy-button.ts @@ -1,12 +1,14 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { MessageLevel } from "@goauthentik/common/messages"; import { showMessage } from "@goauthentik/elements/messages/MessageContainer"; -import { isSafari } from "@goauthentik/elements/utils/isSafari"; +import { writeToClipboard } from "@goauthentik/elements/utils/writeToClipboard"; +import { msg } from "@lit/localize"; import { customElement, property } from "lit/decorators.js"; import { CoreApi, ResponseError, TokenView } from "@goauthentik/api"; +import { APIMessage } from "../../messages/Message"; import BaseTaskButton from "../SpinnerButton/BaseTaskButton"; /** @@ -51,35 +53,26 @@ export class TokenCopyButton extends BaseTaskButton { }); }; - onSuccess(token: unknown) { + async onSuccess(token: unknown) { super.onSuccess(token); if (!isTokenView(token)) { throw new Error(`Unrecognized return from server: ${token}`); } - - // Insecure origins may not have access to the clipboard. Show a message instead. - if (!navigator.clipboard) { - showMessage({ - level: MessageLevel.info, - message: token.key as string, - }); - return; - } - - // Safari only allows navigator.clipboard.write with native clipboard items. - if (isSafari()) { - navigator.clipboard.write([ - new ClipboardItem({ - "text/plain": new Blob([token.key as string], { - type: "text/plain", - }), - }), - ]); - return; - } - - // Default behavior: write the token to the clipboard. - navigator.clipboard.writeText(token.key as string); + const wroteToClipboard = await writeToClipboard(token.key as string); + const info: Pick = wroteToClipboard + ? { + message: msg("The token has been copied to your clipboard"), + } + : { + message: token.key, + description: msg( + "The token was displayed because authentik does not have permission to write to the clipboard", + ), + }; + showMessage({ + level: MessageLevel.info, + ...info, + }); } async onError(error: unknown) { diff --git a/web/src/elements/utils/writeToClipboard.ts b/web/src/elements/utils/writeToClipboard.ts new file mode 100644 index 000000000000..bd916c3bbe28 --- /dev/null +++ b/web/src/elements/utils/writeToClipboard.ts @@ -0,0 +1,26 @@ +import { isSafari } from "./isSafari"; + +export async function writeToClipboard(message: string) { + if (!navigator.clipboard) { + return false; + } + + // Safari only allows navigator.clipboard.write with native clipboard items. + try { + if (isSafari()) { + await navigator.clipboard.write([ + new ClipboardItem({ + "text/plain": new Blob([message], { + type: "text/plain", + }), + }), + ]); + } else { + await navigator.clipboard.writeText(message); + } + return true; + } catch (_) { + /* no op */ + } + return false; +}