refactor(clipboard): 重构剪贴板工具函数并优化相关组件
将 copyToClipboard 拆分为 copyTextToClipboard 和 copyImageToClipboard 移除 useClipboard hook 并将消息处理移至调用方 优化组件中的剪贴板操作错误处理逻辑
This commit is contained in:
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
|||||||
import { IconButton, Tooltip } from '@mui/material';
|
import { IconButton, Tooltip } from '@mui/material';
|
||||||
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
||||||
import CheckIcon from '@mui/icons-material/Check';
|
import CheckIcon from '@mui/icons-material/Check';
|
||||||
import { copyToClipboard } from '@/utils/clipboard';
|
import { copyTextToClipboard } from '@/utils/clipboard';
|
||||||
import type { SnackbarOptions } from '@/components/GlobalSnackbar';
|
import type { SnackbarOptions } from '@/components/GlobalSnackbar';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,11 +45,15 @@ export const CopyButton: React.FC<CopyButtonProps> = ({
|
|||||||
|
|
||||||
const handleCopy = async () => {
|
const handleCopy = async () => {
|
||||||
if (text) {
|
if (text) {
|
||||||
const success = await copyToClipboard(text, showMessage);
|
await copyTextToClipboard(text)
|
||||||
if (success) {
|
.then(() => {
|
||||||
|
showMessage?.('复制成功', { severity: 'success' });
|
||||||
setCopied(true);
|
setCopied(true);
|
||||||
setTimeout(() => setCopied(false), 1500);
|
setTimeout(() => setCopied(false), 1500);
|
||||||
}
|
})
|
||||||
|
.catch(() => {
|
||||||
|
showMessage?.('复制失败', { severity: 'error' });
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
showMessage?.('无内容可复制', { severity: 'error' });
|
showMessage?.('无内容可复制', { severity: 'error' });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
|||||||
import QRious from 'qrious';
|
import QRious from 'qrious';
|
||||||
import { qrCodePageStyles } from '@/config/pageTheme';
|
import { qrCodePageStyles } from '@/config/pageTheme';
|
||||||
import type { SnackbarOptions } from '@/components/GlobalSnackbar';
|
import type { SnackbarOptions } from '@/components/GlobalSnackbar';
|
||||||
|
import { copyImageToClipboard } from '@/utils/clipboard';
|
||||||
|
|
||||||
interface UrlToQrCodeSectionProps {
|
interface UrlToQrCodeSectionProps {
|
||||||
expanded: boolean;
|
expanded: boolean;
|
||||||
@@ -80,27 +81,21 @@ const UrlToQrCodeSection = ({
|
|||||||
link.href = qrCodeDataUrl;
|
link.href = qrCodeDataUrl;
|
||||||
link.download = 'qrcode.png';
|
link.download = 'qrcode.png';
|
||||||
link.click();
|
link.click();
|
||||||
showMessage('二维码下载成功', { severity: 'success', autoHideDuration: 300 });
|
showMessage('二维码下载成功', { severity: 'success' });
|
||||||
};
|
};
|
||||||
|
|
||||||
const copyQrCode = async () => {
|
const copyQrCode = async () => {
|
||||||
if (!qrCodeDataUrl) return;
|
if (!qrCodeDataUrl) return;
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(qrCodeDataUrl);
|
const response = await fetch(qrCodeDataUrl);
|
||||||
const blob = await response.blob();
|
const blob = await response.blob();
|
||||||
|
await copyImageToClipboard(blob)
|
||||||
await navigator.clipboard.write([
|
.then(() => {
|
||||||
new ClipboardItem({
|
showMessage('二维码已复制到剪贴板', { severity: 'success' });
|
||||||
'image/png': blob,
|
})
|
||||||
}),
|
.catch(() => {
|
||||||
]);
|
showMessage('复制二维码失败,请重试', { severity: 'error' });
|
||||||
|
});
|
||||||
showMessage('二维码已复制到剪贴板', { severity: 'success', autoHideDuration: 1000 });
|
|
||||||
} catch (error) {
|
|
||||||
console.error('复制二维码失败:', error);
|
|
||||||
showMessage('复制二维码失败,请重试', { severity: 'error', autoHideDuration: 300 });
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
+29
-27
@@ -1,37 +1,39 @@
|
|||||||
import type { SnackbarOptions } from '@/components/GlobalSnackbar';
|
|
||||||
import { useSnackbarState } from '@/components/GlobalSnackbar';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 复制文本到剪贴板
|
* 复制文本到剪贴板
|
||||||
* @param text 要复制的文本
|
* @param text 要复制的文本
|
||||||
* @param showMessage 显示消息的函数
|
|
||||||
* @returns Promise<boolean> 是否复制成功
|
* @returns Promise<boolean> 是否复制成功
|
||||||
*/
|
*/
|
||||||
export const copyToClipboard = async (
|
export const copyTextToClipboard = async (text: string): Promise<boolean> => {
|
||||||
text: string,
|
return new Promise((resolve, reject) => {
|
||||||
showMessage?: (message: string, options?: SnackbarOptions) => void,
|
navigator.clipboard
|
||||||
): Promise<boolean> => {
|
.writeText(text)
|
||||||
try {
|
.then(() => {
|
||||||
await navigator.clipboard.writeText(text);
|
resolve(true);
|
||||||
showMessage?.('已复制', { severity: 'success' });
|
})
|
||||||
return true;
|
.catch(() => {
|
||||||
} catch (error) {
|
reject(false);
|
||||||
console.error('复制失败:', error);
|
});
|
||||||
showMessage?.('复制失败', { severity: 'error' });
|
});
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义 Hook: 用于处理剪贴板操作
|
* 复制图片到剪贴板
|
||||||
* @returns 包含复制函数和 snackbarProps 的对象
|
* @param blob 要复制的图片
|
||||||
|
* @returns Promise<boolean> 是否复制成功
|
||||||
*/
|
*/
|
||||||
export const useClipboard = () => {
|
export const copyImageToClipboard = async (blob: Blob): Promise<boolean> => {
|
||||||
const { snackbarProps, showMessage } = useSnackbarState({ autoHideDuration: 1500 });
|
return new Promise((resolve, reject) => {
|
||||||
|
navigator.clipboard
|
||||||
const copy = async (text: string): Promise<boolean> => {
|
.write([
|
||||||
return copyToClipboard(text, showMessage);
|
new ClipboardItem({
|
||||||
};
|
'image/png': blob,
|
||||||
|
}),
|
||||||
return { copy, snackbarProps };
|
])
|
||||||
|
.then(() => {
|
||||||
|
resolve(true);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
reject(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user