Skip to content

Commit 17aa471

Browse files
committed
Fix: Fix Image Generation Button Logic
1 parent f20fcd8 commit 17aa471

File tree

9 files changed

+110
-36
lines changed

9 files changed

+110
-36
lines changed

src/components/chat/ChatMessageArea.tsx

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -610,30 +610,30 @@ export const ChatMessageArea: React.FC<ChatMessageAreaProps> = ({
610610
{t('chat.availableMcpServers')}
611611
</div>
612612
<div className="overflow-y-auto max-h-60">
613-
{Object.values(mcpServers).map((server) => (
614-
<div
615-
key={server.id}
616-
className={`flex items-center px-3 py-2 cursor-pointer rounded-md ${
617-
selectedMcpServers?.includes(server.id)
618-
? 'image-generation-provider-selected'
619-
: 'image-generation-provider-item'
620-
}`}
621-
onClick={() => onToggleMcpServer?.(server.id)}
622-
>
623-
<ServerCog className="w-5 h-5 mr-2" />
624-
<div className="flex flex-col">
625-
<span className="text-sm font-medium">{server.name}</span>
626-
{server.isDefault && (
627-
<span className="text-xs text-gray-500">{t('mcpServer.default')}</span>
628-
)}
629-
{server.isImageGeneration && (
630-
<span className="text-xs text-gray-500">{t('mcpServer.imageGeneration')}</span>
631-
)}
613+
{Object.values(mcpServers)
614+
// Filter out image generation servers - they're handled by the ImageGenerationButton
615+
.filter(server => !server.isImageGeneration)
616+
.map((server) => (
617+
<div
618+
key={server.id}
619+
className={`flex items-center px-3 py-2 cursor-pointer rounded-md ${
620+
selectedMcpServers?.includes(server.id)
621+
? 'image-generation-provider-selected'
622+
: 'image-generation-provider-item'
623+
}`}
624+
onClick={() => onToggleMcpServer?.(server.id)}
625+
>
626+
<ServerCog className="w-5 h-5 mr-2" />
627+
<div className="flex flex-col">
628+
<span className="text-sm font-medium">{server.name}</span>
629+
{server.isDefault && (
630+
<span className="text-xs text-gray-500">{t('mcpServer.default')}</span>
631+
)}
632+
</div>
632633
</div>
633-
</div>
634-
))}
634+
))}
635635

636-
{Object.keys(mcpServers).length === 0 && (
636+
{Object.values(mcpServers).filter(server => !server.isImageGeneration).length === 0 && (
637637
<div className="px-3 py-2 text-sm text-gray-500">
638638
{t('chat.noMcpServersAvailable')}
639639
</div>

src/components/chat/ImageGenerationButton.tsx

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useState, useRef, useEffect } from 'react';
2-
import { Image } from 'lucide-react';
2+
import { Image, ToggleLeft, ToggleRight } from 'lucide-react';
33
import { SettingsService, SETTINGS_CHANGE_EVENT } from '../../services/settings-service';
44
import { AIServiceCapability } from '../../types/capabilities';
55
import ProviderIcon from '../ui/ProviderIcon';
@@ -25,10 +25,11 @@ const ImageGenerationButton: React.FC<ImageGenerationButtonProps> = ({
2525
const [providers, setProviders] = useState<ProviderModel[]>([]);
2626
const [selectedProvider, setSelectedProvider] = useState<string | null>(null);
2727
const [selectedModel, setSelectedModel] = useState<string | null>(null);
28+
const [isEnabled, setIsEnabled] = useState(true);
2829
const popupRef = useRef<HTMLDivElement>(null);
2930
const buttonRef = useRef<HTMLButtonElement>(null);
3031

31-
// Load available image generation providers and models
32+
// Load available image generation providers and models and settings
3233
useEffect(() => {
3334
const loadProviders = () => {
3435
const settingsService = SettingsService.getInstance();
@@ -38,6 +39,13 @@ const ImageGenerationButton: React.FC<ImageGenerationButtonProps> = ({
3839
const settings = settingsService.getSettings();
3940
const providerIds = Object.keys(settings.providers);
4041

42+
// Load current image generation enabled status
43+
setIsEnabled(settings.imageGenerationEnabled !== false);
44+
45+
// Load saved selected provider and model
46+
const savedProvider = settings.imageGenerationProvider;
47+
const savedModel = settings.imageGenerationModel;
48+
4149
for (const providerId of providerIds) {
4250
// Get the provider's settings
4351
const providerSettings = settingsService.getProviderSettings(providerId);
@@ -59,8 +67,11 @@ const ImageGenerationButton: React.FC<ImageGenerationButtonProps> = ({
5967

6068
setProviders(availableProviders);
6169

62-
// Set default selected provider and model if available
63-
if (availableProviders.length > 0) {
70+
// Set saved or default selected provider and model
71+
if (savedProvider && savedModel && availableProviders.some(p => p.providerName === savedProvider && p.modelId === savedModel)) {
72+
setSelectedProvider(savedProvider);
73+
setSelectedModel(savedModel);
74+
} else if (availableProviders.length > 0) {
6475
setSelectedProvider(availableProviders[0].providerName);
6576
setSelectedModel(availableProviders[0].modelId);
6677
}
@@ -99,29 +110,57 @@ const ImageGenerationButton: React.FC<ImageGenerationButtonProps> = ({
99110
setIsPopupOpen(!isPopupOpen);
100111
};
101112

102-
const handleProviderModelSelect = (providerName: string, modelId: string) => {
113+
const handleProviderModelSelect = async (providerName: string, modelId: string) => {
103114
setSelectedProvider(providerName);
104115
setSelectedModel(modelId);
105-
setIsPopupOpen(false);
116+
117+
// Save selected provider and model in settings
118+
const settingsService = SettingsService.getInstance();
119+
await settingsService.updateSettings({
120+
imageGenerationProvider: providerName,
121+
imageGenerationModel: modelId
122+
});
106123

107124
// If onImageGenerate is provided, call it with an empty prompt
108125
// The actual prompt will be filled in by the chat message
109-
if (onImageGenerate) {
126+
if (onImageGenerate && isEnabled) {
110127
onImageGenerate("", providerName, modelId);
111128
}
129+
130+
setIsPopupOpen(false);
131+
};
132+
133+
const toggleImageGeneration = async () => {
134+
const newEnabledState = !isEnabled;
135+
setIsEnabled(newEnabledState);
136+
137+
// Save the enabled state in settings
138+
const settingsService = SettingsService.getInstance();
139+
await settingsService.updateSettings({
140+
imageGenerationEnabled: newEnabledState
141+
});
112142
};
113143

114-
const isButtonEnabled = !disabled && providers.length > 0;
144+
const isButtonEnabled = !disabled && providers.length > 0 && isEnabled;
145+
const buttonClass = `flex items-center justify-center w-8 h-8 rounded-full focus:outline-none ${
146+
isEnabled ? 'image-generation-button' : 'text-gray-400 bg-gray-100'
147+
}`;
115148

116149
return (
117150
<div className="relative">
118151
<button
119152
ref={buttonRef}
120153
type="button"
121154
onClick={togglePopup}
122-
disabled={!isButtonEnabled}
123-
className="flex items-center justify-center w-8 h-8 rounded-full image-generation-button focus:outline-none"
124-
title={isButtonEnabled ? t('chat.generateImage') : t('chat.imageGenerationNotAvailable')}
155+
disabled={!providers.length > 0 || disabled}
156+
className={buttonClass}
157+
title={
158+
!providers.length > 0
159+
? t('chat.imageGenerationNotAvailable')
160+
: isEnabled
161+
? t('chat.generateImage')
162+
: t('chat.imageGenerationDisabled')
163+
}
125164
>
126165
<Image size={20} />
127166
</button>
@@ -133,15 +172,28 @@ const ImageGenerationButton: React.FC<ImageGenerationButtonProps> = ({
133172
style={{ bottom: '100%', left: 0, minWidth: '220px' }}
134173
>
135174
<div className="p-2">
136-
<div className="mb-2 text-sm font-medium text-gray-700">
137-
{t('chat.selectImageProvider')}
175+
<div className="flex items-center justify-between mb-3">
176+
<div className="text-sm font-medium text-gray-700">
177+
{t('chat.selectImageProvider')}
178+
</div>
179+
<button
180+
onClick={toggleImageGeneration}
181+
className="flex items-center text-sm focus:outline-none"
182+
title={isEnabled ? t('chat.disableImageGeneration') : t('chat.enableImageGeneration')}
183+
>
184+
{isEnabled ? (
185+
<ToggleRight className="w-6 h-6 text-blue-500" />
186+
) : (
187+
<ToggleLeft className="w-6 h-6 text-gray-400" />
188+
)}
189+
</button>
138190
</div>
139191
<div className="overflow-y-auto max-h-60">
140192
{providers.map((provider) => (
141193
<div
142194
key={`${provider.providerName}-${provider.modelId}`}
143195
className={`flex items-center px-3 py-2 cursor-pointer rounded-md ${
144-
selectedProvider === provider.providerName && selectedModel === provider.modelId
196+
isEnabled && selectedProvider === provider.providerName && selectedModel === provider.modelId
145197
? 'image-generation-provider-selected'
146198
: 'image-generation-provider-item'
147199
}`}

src/locales/en/translation.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
"pressShiftEnterToChangeLines": "Press Shift+Enter to change lines",
3434
"generateImage": "Generate Image",
3535
"imageGenerationNotAvailable": "Image generation not available",
36+
"imageGenerationDisabled": "Image generation is disabled",
37+
"enableImageGeneration": "Enable image generation",
38+
"disableImageGeneration": "Disable image generation",
3639
"selectImageProvider": "Select Image Provider",
3740
"noImageProvidersAvailable": "No image providers available"
3841
},

src/locales/es/translation.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
"pressShiftEnterToChangeLines": "Presiona Shift+Enter para cambiar de línea",
3434
"generateImage": "Generar Imagen",
3535
"imageGenerationNotAvailable": "Generación de imágenes no disponible",
36+
"imageGenerationDisabled": "La generación de imágenes está desactivada",
37+
"enableImageGeneration": "Activar generación de imágenes",
38+
"disableImageGeneration": "Desactivar generación de imágenes",
3639
"selectImageProvider": "Seleccionar Proveedor de Imágenes",
3740
"noImageProvidersAvailable": "No hay proveedores de imágenes disponibles"
3841
},

src/locales/ja/translation.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
"pressShiftEnterToChangeLines": "Shift+Enterを押して行を変更",
3434
"generateImage": "画像を生成",
3535
"imageGenerationNotAvailable": "画像生成は利用できません",
36+
"imageGenerationDisabled": "画像生成は無効になっています",
37+
"enableImageGeneration": "画像生成を有効にする",
38+
"disableImageGeneration": "画像生成を無効にする",
3639
"selectImageProvider": "画像プロバイダーを選択",
3740
"noImageProvidersAvailable": "利用可能な画像プロバイダーがありません"
3841
},

src/locales/ko/translation.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
"pressShiftEnterToChangeLines": "줄을 바꾸려면 Shift+Enter를 누르세요",
3434
"generateImage": "이미지 생성",
3535
"imageGenerationNotAvailable": "이미지 생성을 사용할 수 없습니다",
36+
"imageGenerationDisabled": "이미지 생성이 비활성화되었습니다",
37+
"enableImageGeneration": "이미지 생성 활성화",
38+
"disableImageGeneration": "이미지 생성 비활성화",
3639
"selectImageProvider": "이미지 제공자 선택",
3740
"noImageProvidersAvailable": "사용 가능한 이미지 제공자가 없습니다"
3841
},

src/locales/zh-CN/translation.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
"pressShiftEnterToChangeLines": "按 Shift+Enter 换行",
3434
"generateImage": "生成图片",
3535
"imageGenerationNotAvailable": "图片生成不可用",
36+
"imageGenerationDisabled": "图片生成已禁用",
37+
"enableImageGeneration": "启用图片生成",
38+
"disableImageGeneration": "禁用图片生成",
3639
"selectImageProvider": "选择图片提供商",
3740
"noImageProvidersAvailable": "没有可用的图片提供商"
3841
},

src/locales/zh-TW/translation.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
"pressShiftEnterToChangeLines": "按 Shift+Enter 換行",
3434
"generateImage": "生成圖片",
3535
"imageGenerationNotAvailable": "圖片生成不可用",
36+
"imageGenerationDisabled": "圖片生成已禁用",
37+
"enableImageGeneration": "啟用圖片生成",
38+
"disableImageGeneration": "禁用圖片生成",
3639
"selectImageProvider": "選擇圖片提供商",
3740
"noImageProvidersAvailable": "沒有可用的圖片提供商"
3841
},

src/types/settings.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ export interface UserSettings {
1010
useStreaming: boolean;
1111
webSearchEnabled: boolean;
1212
enableWebSearch_Preview: boolean;
13+
// Image generation settings
14+
imageGenerationEnabled?: boolean;
15+
imageGenerationProvider?: string;
16+
imageGenerationModel?: string;
1317
// General settings
1418
startWithSystem?: boolean;
1519
startupToTray?: boolean;

0 commit comments

Comments
 (0)