mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-11 08:19:01 +08:00
fix(ImageViewer): prevent double menu, improve icons (#9637)
* fix(ImageViewer): prevent double menu, improve icons * refactor: default icon size, standard error messages
This commit is contained in:
parent
649a2a645c
commit
95ff67e99c
@ -1,7 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
CopyOutlined,
|
CopyOutlined,
|
||||||
DownloadOutlined,
|
DownloadOutlined,
|
||||||
FileImageOutlined,
|
|
||||||
RotateLeftOutlined,
|
RotateLeftOutlined,
|
||||||
RotateRightOutlined,
|
RotateRightOutlined,
|
||||||
SwapOutlined,
|
SwapOutlined,
|
||||||
@ -13,11 +12,14 @@ import { loggerService } from '@logger'
|
|||||||
import { download } from '@renderer/utils/download'
|
import { download } from '@renderer/utils/download'
|
||||||
import { Dropdown, Image as AntImage, ImageProps as AntImageProps, Space } from 'antd'
|
import { Dropdown, Image as AntImage, ImageProps as AntImageProps, Space } from 'antd'
|
||||||
import { Base64 } from 'js-base64'
|
import { Base64 } from 'js-base64'
|
||||||
|
import { DownloadIcon, ImageIcon } from 'lucide-react'
|
||||||
import mime from 'mime'
|
import mime from 'mime'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
|
import { CopyIcon } from './Icons'
|
||||||
|
|
||||||
interface ImageViewerProps extends AntImageProps {
|
interface ImageViewerProps extends AntImageProps {
|
||||||
src: string
|
src: string
|
||||||
}
|
}
|
||||||
@ -33,7 +35,7 @@ const ImageViewer: React.FC<ImageViewerProps> = ({ src, style, ...props }) => {
|
|||||||
if (src.startsWith('data:')) {
|
if (src.startsWith('data:')) {
|
||||||
// 处理 base64 格式的图片
|
// 处理 base64 格式的图片
|
||||||
const match = src.match(/^data:(image\/\w+);base64,(.+)$/)
|
const match = src.match(/^data:(image\/\w+);base64,(.+)$/)
|
||||||
if (!match) throw new Error('无效的 base64 图片格式')
|
if (!match) throw new Error('Invalid base64 image format')
|
||||||
const mimeType = match[1]
|
const mimeType = match[1]
|
||||||
const byteArray = Base64.toUint8Array(match[2])
|
const byteArray = Base64.toUint8Array(match[2])
|
||||||
const blob = new Blob([byteArray], { type: mimeType })
|
const blob = new Blob([byteArray], { type: mimeType })
|
||||||
@ -62,17 +64,17 @@ const ImageViewer: React.FC<ImageViewerProps> = ({ src, style, ...props }) => {
|
|||||||
|
|
||||||
window.message.success(t('message.copy.success'))
|
window.message.success(t('message.copy.success'))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('复制图片失败:', error as Error)
|
logger.error('Failed to copy image:', error as Error)
|
||||||
window.message.error(t('message.copy.failed'))
|
window.message.error(t('message.copy.failed'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getContextMenuItems = (src: string) => {
|
const getContextMenuItems = (src: string, size: number = 14) => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
key: 'copy-url',
|
key: 'copy-url',
|
||||||
label: t('common.copy'),
|
label: t('common.copy'),
|
||||||
icon: <CopyOutlined />,
|
icon: <CopyIcon size={size} />,
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
navigator.clipboard.writeText(src)
|
navigator.clipboard.writeText(src)
|
||||||
window.message.success(t('message.copy.success'))
|
window.message.success(t('message.copy.success'))
|
||||||
@ -81,13 +83,13 @@ const ImageViewer: React.FC<ImageViewerProps> = ({ src, style, ...props }) => {
|
|||||||
{
|
{
|
||||||
key: 'download',
|
key: 'download',
|
||||||
label: t('common.download'),
|
label: t('common.download'),
|
||||||
icon: <DownloadOutlined />,
|
icon: <DownloadIcon size={size} />,
|
||||||
onClick: () => download(src)
|
onClick: () => download(src)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'copy-image',
|
key: 'copy-image',
|
||||||
label: t('preview.copy.image'),
|
label: t('preview.copy.image'),
|
||||||
icon: <FileImageOutlined />,
|
icon: <ImageIcon size={size} />,
|
||||||
onClick: () => handleCopyImage(src)
|
onClick: () => handleCopyImage(src)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -98,6 +100,7 @@ const ImageViewer: React.FC<ImageViewerProps> = ({ src, style, ...props }) => {
|
|||||||
<AntImage
|
<AntImage
|
||||||
src={src}
|
src={src}
|
||||||
style={style}
|
style={style}
|
||||||
|
onContextMenu={(e) => e.stopPropagation()}
|
||||||
{...props}
|
{...props}
|
||||||
preview={{
|
preview={{
|
||||||
mask: typeof props.preview === 'object' ? props.preview.mask : false,
|
mask: typeof props.preview === 'object' ? props.preview.mask : false,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user