@@ -7,13 +7,11 @@ import { ChevronDown, RefreshCw, Settings, Zap } from "lucide-react";
7
7
import { useTranslation } from "react-i18next" ;
8
8
import { AIService } from "../../services/ai-service" ;
9
9
import { OPENAI_PROVIDER_NAME } from "../../services/providers/openai-service" ;
10
- import { FORGE_PROVIDER_NAME as TENSORBLOCK_PROVIDER_NAME } from "../../services/providers/forge-service" ;
11
10
import { ImageGenerationManager , ImageGenerationStatus , ImageGenerationHandler } from "../../services/image-generation-handler" ;
12
11
import { DatabaseIntegrationService } from "../../services/database-integration" ;
13
12
import { ImageGenerationResult } from "../../types/image" ;
14
13
import ImageGenerateHistoryItem from "../image/ImageGenerateHistoryItem" ;
15
- import { AiServiceProvider } from "../../types/ai-service" ;
16
- import { AiServiceCapability } from "../../types/ai-service" ;
14
+
17
15
18
16
export const ImageGenerationPage = ( ) => {
19
17
const { t } = useTranslation ( ) ;
@@ -33,6 +31,8 @@ export const ImageGenerationPage = () => {
33
31
const [ isLoadingHistory , setIsLoadingHistory ] = useState ( true ) ;
34
32
const [ isSettingsOpen , setIsSettingsOpen ] = useState ( false ) ;
35
33
const [ selectedProvider , setSelectedProvider ] = useState ( OPENAI_PROVIDER_NAME ) ;
34
+ const [ selectedModel , setSelectedModel ] = useState ( "dall-e-3" ) ;
35
+ const [ availableProviders , setAvailableProviders ] = useState < { id : string , name : string } [ ] > ( [ ] ) ;
36
36
37
37
const settingsButtonRef = useRef < HTMLButtonElement > ( null ) ;
38
38
const settingsPopupRef = useRef < HTMLDivElement > ( null ) ;
@@ -62,6 +62,31 @@ export const ImageGenerationPage = () => {
62
62
}
63
63
} , [ ] ) ;
64
64
65
+ // Load available image generation providers
66
+ const loadImageGenerationProviders = useCallback ( async ( ) => {
67
+ const aiService = AIService . getInstance ( ) ;
68
+ const providers = aiService . getImageGenerationProviders ( ) ;
69
+
70
+ const providerOptions = providers . map ( provider => ( {
71
+ id : provider . id ,
72
+ name : provider . name || provider . id
73
+ } ) ) ;
74
+
75
+ setAvailableProviders ( providerOptions ) ;
76
+
77
+ // Set default provider if none is selected or current one isn't available
78
+ if ( ! selectedProvider || ! providerOptions . some ( p => p . id === selectedProvider ) ) {
79
+ if ( providerOptions . length > 0 ) {
80
+ setSelectedProvider ( providerOptions [ 0 ] . id ) ;
81
+ }
82
+ }
83
+ } , [ selectedProvider ] ) ;
84
+
85
+ const handleGetProviderNameById = ( id : string ) => {
86
+ const provider = availableProviders . find ( p => p . id === id ) ;
87
+ return provider ? provider . name : id ;
88
+ }
89
+
65
90
// Initialize image generation manager and load settings
66
91
useEffect ( ( ) => {
67
92
const initialize = async ( ) => {
@@ -88,6 +113,12 @@ export const ImageGenerationPage = () => {
88
113
if ( settings . imageGenerationProvider ) {
89
114
setSelectedProvider ( settings . imageGenerationProvider ) ;
90
115
}
116
+ if ( settings . imageGenerationModel ) {
117
+ setSelectedModel ( settings . imageGenerationModel ) ;
118
+ }
119
+
120
+ // Load available providers
121
+ await loadImageGenerationProviders ( ) ;
91
122
92
123
// Load image generation history from database
93
124
await refreshImageHistory ( ) ;
@@ -100,7 +131,19 @@ export const ImageGenerationPage = () => {
100
131
} ;
101
132
102
133
initialize ( ) ;
103
- } , [ refreshImageHistory ] ) ;
134
+ } , [ refreshImageHistory , loadImageGenerationProviders ] ) ;
135
+
136
+ // Listen for settings changes
137
+ useEffect ( ( ) => {
138
+ const handleSettingsChange = ( ) => {
139
+ loadImageGenerationProviders ( ) ;
140
+ } ;
141
+
142
+ window . addEventListener ( SETTINGS_CHANGE_EVENT , handleSettingsChange ) ;
143
+ return ( ) => {
144
+ window . removeEventListener ( SETTINGS_CHANGE_EVENT , handleSettingsChange ) ;
145
+ } ;
146
+ } , [ loadImageGenerationProviders ] ) ;
104
147
105
148
// Check if API key is available
106
149
useEffect ( ( ) => {
@@ -183,14 +226,9 @@ export const ImageGenerationPage = () => {
183
226
setError ( null ) ;
184
227
185
228
try {
186
- let providerService ;
187
-
188
229
// Get the appropriate service based on selected provider
189
- if ( selectedProvider === TENSORBLOCK_PROVIDER_NAME ) {
190
- providerService = AIService . getInstance ( ) . getProvider ( TENSORBLOCK_PROVIDER_NAME ) ;
191
- } else {
192
- providerService = AIService . getInstance ( ) . getProvider ( OPENAI_PROVIDER_NAME ) ;
193
- }
230
+ const aiService = AIService . getInstance ( ) ;
231
+ const providerService = aiService . getProvider ( selectedProvider ) ;
194
232
195
233
if ( ! providerService ) {
196
234
throw new Error ( `${ selectedProvider } service not available` ) ;
@@ -201,10 +239,10 @@ export const ImageGenerationPage = () => {
201
239
const handler = imageManager . createHandler ( {
202
240
prompt : prompt ,
203
241
seed : randomSeed ,
204
- number : imageCount ,
242
+ number : 1 ,
205
243
aspectRatio : aspectRatio ,
206
244
provider : selectedProvider ,
207
- model : "dall-e-3" ,
245
+ model : selectedModel ,
208
246
} ) ;
209
247
210
248
// Set status to generating
@@ -480,7 +518,7 @@ export const ImageGenerationPage = () => {
480
518
</ div >
481
519
482
520
< div className = "mb-4" >
483
- < label className = "flex items-center block mb-2 text-sm font-medium text-gray-700" >
521
+ < label className = "flex items-center mb-2 text-sm font-medium text-gray-700" >
484
522
{ t ( "imageGeneration.randomSeed" ) }
485
523
< div
486
524
className = "flex items-center justify-center w-4 h-4 ml-1 text-xs text-gray-500 bg-gray-200 rounded-full cursor-help"
@@ -507,15 +545,15 @@ export const ImageGenerationPage = () => {
507
545
</ div >
508
546
509
547
< div className = "mb-4" >
510
- < label className = "flex items-center block mb-2 text-sm font-medium text-gray-700" >
548
+ < label className = "flex items-center mb-2 text-sm font-medium text-gray-700" >
511
549
{ t ( "imageGeneration.provider" ) }
512
550
</ label >
513
551
< div className = "relative" >
514
552
< button
515
553
className = "flex items-center justify-between w-full p-3 text-left provider-dropdown-toggle input-box"
516
554
onClick = { toggleProviderDropdown }
517
555
>
518
- < span > { selectedProvider } </ span >
556
+ < span > { handleGetProviderNameById ( selectedProvider ) } </ span >
519
557
< ChevronDown size = { 18 } className = "text-gray-500" />
520
558
</ button >
521
559
@@ -525,30 +563,31 @@ export const ImageGenerationPage = () => {
525
563
className = "absolute z-20 w-full mt-1 bg-white border border-gray-300 rounded-md shadow-lg"
526
564
>
527
565
< ul className = "py-1" >
528
- < li
529
- className = { `px-3 py-2 cursor-pointer hover:bg-gray-100 ${
530
- selectedProvider === OPENAI_PROVIDER_NAME ? 'bg-gray-50 font-medium' : ''
531
- } `}
532
- onClick = { ( ) => handleProviderSelect ( OPENAI_PROVIDER_NAME ) }
533
- >
534
- OpenAI
535
- </ li >
536
- < li
537
- className = { `px-3 py-2 cursor-pointer hover:bg-gray-100 ${
538
- selectedProvider === TENSORBLOCK_PROVIDER_NAME ? 'bg-gray-50 font-medium' : ''
539
- } `}
540
- onClick = { ( ) => handleProviderSelect ( TENSORBLOCK_PROVIDER_NAME ) }
541
- >
542
- TensorBlock
543
- </ li >
566
+ { availableProviders . length > 0 ? (
567
+ availableProviders . map ( provider => (
568
+ < li
569
+ key = { provider . id }
570
+ className = { `px-3 py-2 cursor-pointer hover:bg-gray-100 ${
571
+ selectedProvider === provider . id ? 'bg-gray-50 font-medium' : ''
572
+ } `}
573
+ onClick = { ( ) => handleProviderSelect ( provider . id ) }
574
+ >
575
+ { provider . name }
576
+ </ li >
577
+ ) )
578
+ ) : (
579
+ < li className = "px-3 py-2 text-gray-500" >
580
+ { t ( "chat.noImageProvidersAvailable" ) }
581
+ </ li >
582
+ ) }
544
583
</ ul >
545
584
</ div >
546
585
) }
547
586
</ div >
548
587
</ div >
549
588
550
589
< div className = "mb-4" >
551
- < label className = "flex items-center block mb-2 text-sm font-medium text-gray-700" >
590
+ < label className = "flex items-center mb-2 text-sm font-medium text-gray-700" >
552
591
{ t ( "imageGeneration.model" ) }
553
592
</ label >
554
593
< div className = "relative" >
0 commit comments