From c45ef949f359326926c486cd95a08ce102fb7127 Mon Sep 17 00:00:00 2001 From: Andreas Kienle Date: Tue, 9 Sep 2025 15:35:28 +0200 Subject: [PATCH 1/3] Refactor and fix clipboard --- public/locales/en.json | 11 ++---- .../ControlPlanes/CopyKubeconfigButton.tsx | 13 ++----- .../KubectlCommandInfo/KubectlTerminal.tsx | 17 ++-------- src/components/Shared/CopyButton.tsx | 15 +++----- src/components/Yaml/YamlViewer.tsx | 10 ++---- src/hooks/useCopyToClipboard.ts | 34 +++++++++++++++++++ 6 files changed, 51 insertions(+), 49 deletions(-) create mode 100644 src/hooks/useCopyToClipboard.ts diff --git a/public/locales/en.json b/public/locales/en.json index ccea36bc..5a1b2f67 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -82,8 +82,6 @@ }, "CopyKubeconfigButton": { "kubeconfigButton": "Kubeconfig", - "copiedMessage": "Copied to Clipboard", - "failedMessage": "Failed to copy, Error:", "menuDownload": "Download", "menuCopy": "Copy to clipboard" }, @@ -205,10 +203,6 @@ "treeExecution": "Execution", "noExecutionFound": "No Executions found" }, - "CopyButton": { - "copiedMessage": "Copied To Clipboard", - "failedMessage": "Failed to copy" - }, "DeleteWorkspaceDialog": { "title": "Delete a Workspace", "introSection1": "The below instructions will help you delete the workspace \"{{workspaceName}}\" from project namespace \"{{projectNamespace}}\" using kubectl.", @@ -341,7 +335,9 @@ "unhealthy": "Unhealthy", "progress": "Managed", "remaining": "Remaining", - "active": "Active" + "active": "Active", + "copyToClipboardSuccessToast": "Copied to clipboard", + "copyToClipboardFailedToast": "Failed to copy to clipboard" }, "errors": { "installError": "Install error", @@ -360,7 +356,6 @@ "cancel": "Cancel" }, "yaml": { - "copiedToClipboard": "YAML copied to clipboard!", "YAML": "File" }, "createMCP": { diff --git a/src/components/ControlPlanes/CopyKubeconfigButton.tsx b/src/components/ControlPlanes/CopyKubeconfigButton.tsx index 8000f1ec..2ec0a4eb 100644 --- a/src/components/ControlPlanes/CopyKubeconfigButton.tsx +++ b/src/components/ControlPlanes/CopyKubeconfigButton.tsx @@ -1,5 +1,5 @@ import { Button, Menu, MenuItem } from '@ui5/webcomponents-react'; -import { useToast } from '../../context/ToastContext.tsx'; +import { useCopyToClipboard } from '../../hooks/useCopyToClipboard.ts'; import { useRef, useState } from 'react'; import '@ui5/webcomponents-icons/dist/copy'; import '@ui5/webcomponents-icons/dist/accept'; @@ -9,7 +9,7 @@ import { useTranslation } from 'react-i18next'; export default function CopyKubeconfigButton() { const popoverRef = useRef(null); const [open, setOpen] = useState(false); - const { show } = useToast(); + const { copyToClipboard } = useCopyToClipboard(); const { t } = useTranslation(); // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -37,14 +37,7 @@ export default function CopyKubeconfigButton() { return; } if (event.detail.item.dataset.action === 'copy') { - try { - navigator.clipboard.writeText(mcp.kubeconfig ?? ''); - show(t('CopyKubeconfigButton.copiedMessage')); - } catch (error) { - //TODO: handle error, show error to user - show(`${t('CopyKubeconfigButton.failedMessage')} ${error}`); - console.error(error); - } + void copyToClipboard(mcp.kubeconfig ?? ''); } setOpen(false); diff --git a/src/components/Dialogs/KubectlCommandInfo/KubectlTerminal.tsx b/src/components/Dialogs/KubectlCommandInfo/KubectlTerminal.tsx index 11442178..ef87e68b 100644 --- a/src/components/Dialogs/KubectlCommandInfo/KubectlTerminal.tsx +++ b/src/components/Dialogs/KubectlCommandInfo/KubectlTerminal.tsx @@ -1,5 +1,5 @@ import { FlexBox, Button } from '@ui5/webcomponents-react'; -import { useToast } from '../../../context/ToastContext'; +import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard.ts'; import '@ui5/webcomponents-icons/dist/copy'; import { ThemingParameters } from '@ui5/webcomponents-react-base'; @@ -8,18 +8,7 @@ interface KubeCtlTerminalProps { } export const KubectlTerminal = ({ command }: KubeCtlTerminalProps) => { - const { show } = useToast(); - - const handleCopy = () => { - navigator.clipboard.writeText(command).then( - () => { - show('Command copied to clipboard'); - }, - (err) => { - console.error('Could not copy text: ', err); - }, - ); - }; + const { copyToClipboard } = useCopyToClipboard(); const FormattedCommand = () => { if (command.startsWith("echo '") && command.includes('apiVersion:')) { @@ -91,7 +80,7 @@ export const KubectlTerminal = ({ command }: KubeCtlTerminalProps) => { }} /> - ); }; diff --git a/src/components/Yaml/YamlViewer.tsx b/src/components/Yaml/YamlViewer.tsx index fa1cefa7..090dc85d 100644 --- a/src/components/Yaml/YamlViewer.tsx +++ b/src/components/Yaml/YamlViewer.tsx @@ -4,18 +4,14 @@ import { materialLight, materialDark } from 'react-syntax-highlighter/dist/esm/s import { Button, FlexBox } from '@ui5/webcomponents-react'; import styles from './YamlViewer.module.css'; -import { useToast } from '../../context/ToastContext.tsx'; +import { useCopyToClipboard } from '../../hooks/useCopyToClipboard.ts'; import { useTranslation } from 'react-i18next'; import { useTheme } from '../../hooks/useTheme.ts'; type YamlViewerProps = { yamlString: string; filename: string }; const YamlViewer: FC = ({ yamlString, filename }) => { - const toast = useToast(); const { t } = useTranslation(); const { isDarkTheme } = useTheme(); - const copyToClipboard = () => { - navigator.clipboard.writeText(yamlString); - toast.show(t('yaml.copiedToClipboard')); - }; + const { copyToClipboard } = useCopyToClipboard(); const downloadYaml = () => { const blob = new Blob([yamlString], { type: 'text/yaml' }); const url = window.URL.createObjectURL(blob); @@ -31,7 +27,7 @@ const YamlViewer: FC = ({ yamlString, filename }) => { return (
-