Skip to content

Commit 6c486a5

Browse files
committed
Fix: Add translation copy button & fix dalle3 model duplicate
1 parent f618961 commit 6c486a5

File tree

10 files changed

+49
-50
lines changed

10 files changed

+49
-50
lines changed

src/components/pages/SettingsPage.tsx

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
22
import { Server, MessageSquare, Languages } from 'lucide-react';
33
import { SettingsService } from '../../services/settings-service';
44
import { ProviderSettings } from '../../types/settings';
5-
import { ApiManagement, ModelManagement, ChatSettings, LanguageSettings } from '../settings';
5+
import { ApiManagement, ChatSettings, LanguageSettings } from '../settings';
66
import { DatabaseIntegrationService } from '../../services/database-integration';
77
import { AIService } from '../../services/ai-service';
88
import { v4 as uuidv4 } from 'uuid';
@@ -21,7 +21,6 @@ export const SettingsPage: React.FC<SettingsPageProps> = ({
2121
const [activeTab, setActiveTab] = useState<SettingsTab>('api');
2222
const [selectedProvider, setSelectedProvider] = useState<string>('TensorBlock');
2323
const [providerSettings, setProviderSettings] = useState<Record<string, ProviderSettings>>({});
24-
const [selectedModel, setSelectedModel] = useState('');
2524
const [useWebSearch, setUseWebSearch] = useState(true);
2625
const [isDbInitialized, setIsDbInitialized] = useState(false);
2726
const [hasApiKeyChanged, setHasApiKeyChanged] = useState(false);
@@ -55,7 +54,6 @@ export const SettingsPage: React.FC<SettingsPageProps> = ({
5554
const settings = settingsService.getSettings();
5655
setSelectedProvider(settings.selectedProvider);
5756
setProviderSettings(settings.providers);
58-
setSelectedModel(settings.selectedModel);
5957
setUseWebSearch(settings.enableWebSearch_Preview);
6058
setHasApiKeyChanged(false);
6159
lastOpenedSettings.current = true;
@@ -73,11 +71,6 @@ export const SettingsPage: React.FC<SettingsPageProps> = ({
7371
setSelectedProvider(provider);
7472
};
7573

76-
// Handle model selection change
77-
const handleModelChange = (modelId: string) => {
78-
setSelectedModel(modelId);
79-
};
80-
8174
// Handle web search setting change
8275
const handleWebSearchChange = (enabled: boolean) => {
8376
console.log('Web search setting changed to: ', enabled);
@@ -308,14 +301,6 @@ export const SettingsPage: React.FC<SettingsPageProps> = ({
308301
<LanguageSettings />
309302
</div>
310303
)}
311-
312-
{/* Model Management Tab */}
313-
{activeTab === 'models' && (
314-
<ModelManagement
315-
selectedModel={selectedModel}
316-
onModelChange={handleModelChange}
317-
/>
318-
)}
319304
</div>
320305
</div>
321306
</div>

src/components/pages/TranslationPage.tsx

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useState, useEffect } from 'react';
22
import { SettingsService, SETTINGS_CHANGE_EVENT } from '../../services/settings-service';
3-
import { Orbit, Languages, ArrowRight } from 'lucide-react';
3+
import { Orbit, Languages, ArrowRight, Copy, Check } from 'lucide-react';
44
import { useTranslation } from 'react-i18next';
55
import { v4 as uuidv4 } from 'uuid';
66
import { Message, MessageRole } from '../../types/chat';
@@ -16,6 +16,7 @@ export const TranslationPage: React.FC = () => {
1616
const [targetLanguage, setTargetLanguage] = useState('en');
1717
const [error, setError] = useState<Error | null>(null);
1818
const [isApiKeyMissing, setIsApiKeyMissing] = useState(true);
19+
const [isCopied, setIsCopied] = useState(false);
1920

2021
// Check if API key is available
2122
useEffect(() => {
@@ -32,6 +33,20 @@ export const TranslationPage: React.FC = () => {
3233
};
3334
}, []);
3435

36+
// Handle copy to clipboard
37+
const handleCopy = () => {
38+
if (!translatedText) return;
39+
40+
navigator.clipboard.writeText(translatedText)
41+
.then(() => {
42+
setIsCopied(true);
43+
setTimeout(() => setIsCopied(false), 2000);
44+
})
45+
.catch(err => {
46+
console.error('Failed to copy text: ', err);
47+
});
48+
};
49+
3550
// Handle translation
3651
const handleTranslate = async () => {
3752
if (!sourceText.trim()) return;
@@ -216,27 +231,6 @@ export const TranslationPage: React.FC = () => {
216231
className="flex-1 w-full p-3 mb-4 form-textarea-border input-box"
217232
style={{ minHeight: '200px', resize: 'none' }}
218233
/>
219-
220-
{/* Translation button */}
221-
{/* <div className="flex justify-center">
222-
<button
223-
onClick={handleTranslate}
224-
disabled={isTranslating || !sourceText.trim() || isApiKeyMissing}
225-
className="px-8 py-2.5 text-white confirm-btn flex items-center"
226-
>
227-
{isTranslating ? (
228-
<>
229-
<Orbit size={18} className="mr-2 animate-spin" />
230-
{t('translation.translating')}
231-
</>
232-
) : (
233-
<>
234-
<Languages size={18} className="mr-2" />
235-
{t('translation.translateButton')}
236-
</>
237-
)}
238-
</button>
239-
</div> */}
240234
</div>
241235
</div>
242236

@@ -272,15 +266,29 @@ export const TranslationPage: React.FC = () => {
272266
)}
273267

274268
{/* Translation result */}
275-
<div className="flex-1 p-3 overflow-auto form-textarea-border major-area-bg-color">
269+
<div className="relative flex-1 p-3 overflow-auto form-textarea-border major-area-bg-color">
276270
{isTranslating ? (
277271
<div className="flex items-center justify-center h-full">
278272
<div className="w-8 h-8 border-4 rounded-full border-primary-300 border-t-primary-600 animate-spin"></div>
279273
</div>
280274
) : (
281275
<div className="h-full">
282276
{translatedText ? (
283-
<p className="text-primary-800">{translatedText}</p>
277+
<>
278+
<p className="pr-10 text-primary-800">{translatedText}</p>
279+
<button
280+
onClick={handleCopy}
281+
disabled={!translatedText}
282+
className="absolute p-2 transition-colors rounded-md top-3 right-3 hover:bg-surface-100"
283+
title={t('translation.copy')}
284+
>
285+
{isCopied ? (
286+
<Check size={18} className="text-green-600" />
287+
) : (
288+
<Copy size={18} className="text-surface-600" />
289+
)}
290+
</button>
291+
</>
284292
) : (
285293
<div className="flex items-center justify-center h-full">
286294
<p className="text-surface-400">{t('translation.resultPlaceholder')}</p>

src/components/settings/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
export * from './ApiManagement';
2-
export * from './ModelManagement';
32
export * from './ChatSettings';
43
export * from './LanguageSettings';

src/locales/en/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"translating": "Translating...",
4141
"inputPlaceholder": "Enter text to translate...",
4242
"resultPlaceholder": "Translation will appear here",
43+
"copy": "Copy",
4344
"apiKeyMissing": "Please set your API key for the selected provider in the settings.",
4445
"autoDetect": "Auto-detect",
4546
"english": "English",

src/locales/es/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"translating": "Traduciendo...",
4141
"inputPlaceholder": "Introduce el texto a traducir...",
4242
"resultPlaceholder": "La traducción aparecerá aquí",
43+
"copy": "Copiar",
4344
"apiKeyMissing": "Por favor, configura tu clave API para el proveedor seleccionado en la configuración.",
4445
"autoDetect": "Detección automática",
4546
"english": "Inglés",

src/locales/ja/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"translating": "翻訳中...",
4141
"inputPlaceholder": "翻訳するテキストを入力...",
4242
"resultPlaceholder": "翻訳結果がここに表示されます",
43+
"copy": "コピー",
4344
"apiKeyMissing": "選択したプロバイダーのAPIキーを設定で設定してください。",
4445
"autoDetect": "自動検出",
4546
"english": "英語",

src/locales/ko/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"translating": "번역 중...",
4141
"inputPlaceholder": "번역할 텍스트를 입력하세요...",
4242
"resultPlaceholder": "번역 결과가 여기에 표시됩니다",
43+
"copy": "복사",
4344
"apiKeyMissing": "선택한 제공자의 API 키를 설정에서 설정하세요.",
4445
"autoDetect": "자동 감지",
4546
"english": "영어",

src/locales/zh-CN/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"translating": "翻译中...",
4141
"inputPlaceholder": "输入要翻译的文本...",
4242
"resultPlaceholder": "翻译结果将显示在这里",
43+
"copy": "复制",
4344
"apiKeyMissing": "请在设置中为所选提供商设置您的 API 密钥。",
4445
"autoDetect": "自动检测",
4546
"english": "英语",

src/locales/zh-TW/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"translating": "翻譯中...",
4141
"inputPlaceholder": "輸入要翻譯的文字...",
4242
"resultPlaceholder": "翻譯結果將顯示在這裡",
43+
"copy": "複製",
4344
"apiKeyMissing": "請在設定中為所選提供商設置您的 API 金鑰。",
4445
"autoDetect": "自動偵測",
4546
"english": "英文",

src/services/settings-service.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -312,15 +312,16 @@ export class SettingsService {
312312
}
313313

314314
if(provider === 'OpenAI') {
315-
316-
this.settings.providers[provider].models!.push({
317-
modelName: 'DALL-E 3',
318-
modelId: 'dall-e-3',
319-
modelCategory: 'Image Generation',
320-
modelDescription: 'DALL-E 3 is OpenAI\'s advanced image generation model.',
321-
modelCapabilities: [AIServiceCapability.ImageGeneration],
322-
modelRefUUID: uuidv4(),
323-
});
315+
if(!this.settings.providers[provider].models!.find(model => model.modelId === 'dall-e-3')) {
316+
this.settings.providers[provider].models!.push({
317+
modelName: 'DALL-E 3',
318+
modelId: 'dall-e-3',
319+
modelCategory: 'Image Generation',
320+
modelDescription: 'DALL-E 3 is OpenAI\'s advanced image generation model.',
321+
modelCapabilities: [AIServiceCapability.ImageGeneration],
322+
modelRefUUID: uuidv4(),
323+
});
324+
}
324325
}
325326
}
326327
}

0 commit comments

Comments
 (0)