diff --git a/src/renderer/src/components/Popups/TextEditPopup.tsx b/src/renderer/src/components/Popups/TextEditPopup.tsx index ff19c2554a..f2ecae4fc6 100644 --- a/src/renderer/src/components/Popups/TextEditPopup.tsx +++ b/src/renderer/src/components/Popups/TextEditPopup.tsx @@ -1,7 +1,13 @@ +import { LoadingOutlined } from '@ant-design/icons' +import { useDefaultModel } from '@renderer/hooks/useAssistant' +import { useSettings } from '@renderer/hooks/useSettings' +import { fetchTranslate } from '@renderer/services/ApiService' +import { getDefaultTranslateAssistant } from '@renderer/services/AssistantService' import { Modal, ModalProps } from 'antd' import TextArea from 'antd/es/input/TextArea' import { TextAreaProps } from 'antd/lib/input' import { TextAreaRef } from 'antd/lib/input/TextArea' +import { Languages } from 'lucide-react' import { useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' @@ -23,7 +29,17 @@ const PopupContainer: React.FC = ({ text, textareaProps, modalProps, reso const [open, setOpen] = useState(true) const { t } = useTranslation() const [textValue, setTextValue] = useState(text) + const [isTranslating, setIsTranslating] = useState(false) const textareaRef = useRef(null) + const { translateModel } = useDefaultModel() + const { targetLanguage, showTranslateConfirm } = useSettings() + const isMounted = useRef(true) + + useEffect(() => { + return () => { + isMounted.current = false + } + }, []) const onOk = () => { setOpen(false) @@ -62,6 +78,49 @@ const PopupContainer: React.FC = ({ text, textareaProps, modalProps, reso } } + const handleTranslate = async () => { + if (!textValue.trim() || isTranslating) return + + if (showTranslateConfirm) { + const confirmed = await window?.modal?.confirm({ + title: t('translate.confirm.title'), + content: t('translate.confirm.content'), + centered: true + }) + if (!confirmed) return + } + + if (!translateModel) { + window.message.error({ + content: t('translate.error.not_configured'), + key: 'translate-message' + }) + return + } + + if (isMounted.current) { + setIsTranslating(true) + } + + try { + const assistant = getDefaultTranslateAssistant(targetLanguage, textValue) + const translatedText = await fetchTranslate({ content: textValue, assistant }) + if (isMounted.current) { + setTextValue(translatedText) + } + } catch (error) { + console.error('Translation failed:', error) + window.message.error({ + content: t('translate.error.failed'), + key: 'translate-message' + }) + } finally { + if (isMounted.current) { + setIsTranslating(false) + } + } + } + TextEditPopup.hide = onCancel return ( @@ -78,16 +137,24 @@ const PopupContainer: React.FC = ({ text, textareaProps, modalProps, reso afterClose={onClose} afterOpenChange={handleAfterOpenChange} centered> -