Compare commits

...

1 Commits

Author SHA1 Message Date
icarus
afd44780d6 feat: improve ImageViewer context menu UX
- Reorder menu items to prioritize "Copy as Image" as the first action
- Rename "Copy" to "Copy Image Source" for better clarity
- Remove unused ImageIcon import
- Add i18n support for "preview.copy.src" across all locales

This change improves the user experience by making the most common
action (copy image) the first option in the context menu, while also
clarifying what each copy action does.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 15:36:25 +08:00
11 changed files with 28 additions and 18 deletions

View File

@@ -14,7 +14,7 @@ import { convertImageToPng } from '@renderer/utils/image'
import type { ImageProps as AntImageProps } from 'antd' import type { ImageProps as AntImageProps } from 'antd'
import { Dropdown, Image as AntImage, Space } from 'antd' import { Dropdown, Image as AntImage, Space } from 'antd'
import { Base64 } from 'js-base64' import { Base64 } from 'js-base64'
import { DownloadIcon, ImageIcon } from 'lucide-react' import { DownloadIcon } 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'
@@ -73,9 +73,15 @@ const ImageViewer: React.FC<ImageViewerProps> = ({ src, style, ...props }) => {
const getContextMenuItems = (src: string, size: number = 14) => { const getContextMenuItems = (src: string, size: number = 14) => {
return [ return [
{ {
key: 'copy-url', key: 'copy-image',
label: t('common.copy'), label: t('common.copy'),
icon: <CopyIcon size={size} />, icon: <CopyIcon size={size} />,
onClick: () => handleCopyImage(src)
},
{
key: 'copy-url',
label: t('preview.copy.src'),
icon: <CopyIcon size={size} />,
onClick: () => { onClick: () => {
navigator.clipboard.writeText(src) navigator.clipboard.writeText(src)
window.toast.success(t('message.copy.success')) window.toast.success(t('message.copy.success'))
@@ -86,12 +92,6 @@ const ImageViewer: React.FC<ImageViewerProps> = ({ src, style, ...props }) => {
label: t('common.download'), label: t('common.download'),
icon: <DownloadIcon size={size} />, icon: <DownloadIcon size={size} />,
onClick: () => download(src) onClick: () => download(src)
},
{
key: 'copy-image',
label: t('preview.copy.image'),
icon: <ImageIcon size={size} />,
onClick: () => handleCopyImage(src)
} }
] ]
} }

View File

@@ -2509,7 +2509,8 @@
}, },
"preview": { "preview": {
"copy": { "copy": {
"image": "Copy as image" "image": "Copy as image",
"src": "Copy Image Source"
}, },
"dialog": "Open Dialog", "dialog": "Open Dialog",
"label": "Preview", "label": "Preview",

View File

@@ -2509,7 +2509,8 @@
}, },
"preview": { "preview": {
"copy": { "copy": {
"image": "复制为图片" "image": "复制为图片",
"src": "复制图片源"
}, },
"dialog": "打开预览窗口", "dialog": "打开预览窗口",
"label": "预览", "label": "预览",

View File

@@ -2509,7 +2509,8 @@
}, },
"preview": { "preview": {
"copy": { "copy": {
"image": "複製為圖片" "image": "複製為圖片",
"src": "複製圖片來源"
}, },
"dialog": "開啟預覽窗口", "dialog": "開啟預覽窗口",
"label": "預覽", "label": "預覽",

View File

@@ -2509,7 +2509,8 @@
}, },
"preview": { "preview": {
"copy": { "copy": {
"image": "Als Bild kopieren" "image": "Als Bild kopieren",
"src": "Bildquelle kopieren"
}, },
"dialog": "Vorschaufenster öffnen", "dialog": "Vorschaufenster öffnen",
"label": "Vorschau", "label": "Vorschau",

View File

@@ -2509,7 +2509,8 @@
}, },
"preview": { "preview": {
"copy": { "copy": {
"image": "Αντιγραφή ως εικόνα" "image": "Αντιγραφή ως εικόνα",
"src": "Αντιγραφή πηγής εικόνας"
}, },
"dialog": "Άνοιγμα παραθύρου προεπισκόπησης", "dialog": "Άνοιγμα παραθύρου προεπισκόπησης",
"label": "Προεπισκόπηση", "label": "Προεπισκόπηση",

View File

@@ -2509,7 +2509,8 @@
}, },
"preview": { "preview": {
"copy": { "copy": {
"image": "Copiar como imagen" "image": "Copiar como imagen",
"src": "Copia la fuente de la imagen"
}, },
"dialog": "Abrir la ventana de vista previa", "dialog": "Abrir la ventana de vista previa",
"label": "Vista previa", "label": "Vista previa",

View File

@@ -2509,7 +2509,8 @@
}, },
"preview": { "preview": {
"copy": { "copy": {
"image": "Copier en tant qu'image" "image": "Copier en tant qu'image",
"src": "Copier la source de l'image"
}, },
"dialog": "Ouvrir la fenêtre d'aperçu", "dialog": "Ouvrir la fenêtre d'aperçu",
"label": "Aperçu", "label": "Aperçu",

View File

@@ -2509,7 +2509,8 @@
}, },
"preview": { "preview": {
"copy": { "copy": {
"image": "画像としてコピー" "image": "画像としてコピー",
"src": "画像ソースをコピー"
}, },
"dialog": "ダイアログを開く", "dialog": "ダイアログを開く",
"label": "プレビュー", "label": "プレビュー",

View File

@@ -2509,7 +2509,8 @@
}, },
"preview": { "preview": {
"copy": { "copy": {
"image": "Copiar como imagem" "image": "Copiar como imagem",
"src": "Copiar Origem da Imagem"
}, },
"dialog": "Abrir janela de pré-visualização", "dialog": "Abrir janela de pré-visualização",
"label": "Pré-visualização", "label": "Pré-visualização",

View File

@@ -2509,7 +2509,8 @@
}, },
"preview": { "preview": {
"copy": { "copy": {
"image": "Скопировать как изображение" "image": "Скопировать как изображение",
"src": "Копировать источник изображения"
}, },
"dialog": "Открыть диалог", "dialog": "Открыть диалог",
"label": "Предварительный просмотр", "label": "Предварительный просмотр",