1
1
import React , { useState , useRef , useEffect } from 'react' ;
2
- import { Image } from 'lucide-react' ;
2
+ import { Image , ToggleLeft , ToggleRight } from 'lucide-react' ;
3
3
import { SettingsService , SETTINGS_CHANGE_EVENT } from '../../services/settings-service' ;
4
4
import { AIServiceCapability } from '../../types/capabilities' ;
5
5
import ProviderIcon from '../ui/ProviderIcon' ;
@@ -25,10 +25,11 @@ const ImageGenerationButton: React.FC<ImageGenerationButtonProps> = ({
25
25
const [ providers , setProviders ] = useState < ProviderModel [ ] > ( [ ] ) ;
26
26
const [ selectedProvider , setSelectedProvider ] = useState < string | null > ( null ) ;
27
27
const [ selectedModel , setSelectedModel ] = useState < string | null > ( null ) ;
28
+ const [ isEnabled , setIsEnabled ] = useState ( true ) ;
28
29
const popupRef = useRef < HTMLDivElement > ( null ) ;
29
30
const buttonRef = useRef < HTMLButtonElement > ( null ) ;
30
31
31
- // Load available image generation providers and models
32
+ // Load available image generation providers and models and settings
32
33
useEffect ( ( ) => {
33
34
const loadProviders = ( ) => {
34
35
const settingsService = SettingsService . getInstance ( ) ;
@@ -38,6 +39,13 @@ const ImageGenerationButton: React.FC<ImageGenerationButtonProps> = ({
38
39
const settings = settingsService . getSettings ( ) ;
39
40
const providerIds = Object . keys ( settings . providers ) ;
40
41
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
+
41
49
for ( const providerId of providerIds ) {
42
50
// Get the provider's settings
43
51
const providerSettings = settingsService . getProviderSettings ( providerId ) ;
@@ -59,8 +67,11 @@ const ImageGenerationButton: React.FC<ImageGenerationButtonProps> = ({
59
67
60
68
setProviders ( availableProviders ) ;
61
69
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 ) {
64
75
setSelectedProvider ( availableProviders [ 0 ] . providerName ) ;
65
76
setSelectedModel ( availableProviders [ 0 ] . modelId ) ;
66
77
}
@@ -99,29 +110,57 @@ const ImageGenerationButton: React.FC<ImageGenerationButtonProps> = ({
99
110
setIsPopupOpen ( ! isPopupOpen ) ;
100
111
} ;
101
112
102
- const handleProviderModelSelect = ( providerName : string , modelId : string ) => {
113
+ const handleProviderModelSelect = async ( providerName : string , modelId : string ) => {
103
114
setSelectedProvider ( providerName ) ;
104
115
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
+ } ) ;
106
123
107
124
// If onImageGenerate is provided, call it with an empty prompt
108
125
// The actual prompt will be filled in by the chat message
109
- if ( onImageGenerate ) {
126
+ if ( onImageGenerate && isEnabled ) {
110
127
onImageGenerate ( "" , providerName , modelId ) ;
111
128
}
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
+ } ) ;
112
142
} ;
113
143
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
+ } `;
115
148
116
149
return (
117
150
< div className = "relative" >
118
151
< button
119
152
ref = { buttonRef }
120
153
type = "button"
121
154
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
+ }
125
164
>
126
165
< Image size = { 20 } />
127
166
</ button >
@@ -133,15 +172,28 @@ const ImageGenerationButton: React.FC<ImageGenerationButtonProps> = ({
133
172
style = { { bottom : '100%' , left : 0 , minWidth : '220px' } }
134
173
>
135
174
< 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 >
138
190
</ div >
139
191
< div className = "overflow-y-auto max-h-60" >
140
192
{ providers . map ( ( provider ) => (
141
193
< div
142
194
key = { `${ provider . providerName } -${ provider . modelId } ` }
143
195
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
145
197
? 'image-generation-provider-selected'
146
198
: 'image-generation-provider-item'
147
199
} `}
0 commit comments