| 1 | import { CheckCircle2, Image as ImageIcon, Pencil, Plus, Trash2 } from 'lucide-react' |
| 2 | import type { ImageModelConfig } from '../../lib/ipc' |
| 3 | import { Button } from '../ui/Button' |
| 4 | import { Card, CardContent, CardHeader, CardTitle } from '../ui/Card' |
| 5 | import { summarizeImageModelConfig } from './model-settings-utils' |
| 6 | import type { SettingsTranslate } from './types' |
| 7 | |
| 8 | interface ImageModelSettingsTabProps { |
| 9 | activeImageModelConfig?: ImageModelConfig |
| 10 | activatingImageId: string | null |
| 11 | deletingImageId: string | null |
| 12 | imageModelConfigs: ImageModelConfig[] |
| 13 | t: SettingsTranslate |
| 14 | onActivate: (id: string) => void |
| 15 | onCreate: () => void |
| 16 | onDelete: (config: ImageModelConfig) => void |
| 17 | onEdit: (config: ImageModelConfig) => void |
| 18 | } |
| 19 | |
| 20 | export function ImageModelSettingsTab({ |
| 21 | activeImageModelConfig, |
| 22 | activatingImageId, |
| 23 | deletingImageId, |
| 24 | imageModelConfigs, |
| 25 | t, |
| 26 | onActivate, |
| 27 | onCreate, |
| 28 | onDelete, |
| 29 | onEdit |
| 30 | }: ImageModelSettingsTabProps): React.JSX.Element { |
| 31 | return ( |
| 32 | <Card className="mb-4"> |
| 33 | <CardHeader className="flex-row items-center justify-between p-5 pb-3"> |
| 34 | <div> |
| 35 | <CardTitle className="flex items-center gap-1.5 text-base"> |
| 36 | <ImageIcon className="h-4 w-4 text-[#5d7b4d]" /> |
| 37 | {t('settings.imageModelAccess')} |
| 38 | </CardTitle> |
| 39 | <p className="mt-1 text-xs text-[#6f8f64]"> |
| 40 | {t('settings.imageModelUsageHint')} |
| 41 | </p> |
| 42 | {activeImageModelConfig && ( |
| 43 | <span className="mt-2 inline-flex max-w-full truncate rounded-full border border-[#96b77f]/55 bg-[#eef6e8] px-2.5 py-1 text-xs font-medium text-[#4f6b45]"> |
| 44 | {t('settings.currentActiveImageModel', { name: activeImageModelConfig.name })} |
| 45 | </span> |
| 46 | )} |
| 47 | </div> |
| 48 | <Button size="sm" onClick={onCreate}> |
| 49 | <Plus className="mr-1.5 h-4 w-4" /> |
| 50 | {t('settings.addImageModel')} |
| 51 | </Button> |
| 52 | </CardHeader> |
| 53 | <CardContent className="space-y-2.5 p-5 pt-0"> |
| 54 | {imageModelConfigs.length === 0 ? ( |
| 55 | <div className="rounded-lg border border-dashed border-[#d8ccb5]/85 bg-[#fff9ef]/70 p-6 text-sm text-muted-foreground"> |
| 56 | {t('settings.noImageModels')} |
| 57 | </div> |
| 58 | ) : ( |
| 59 | imageModelConfigs.map((config) => ( |
| 60 | <div |
| 61 | key={config.id} |
| 62 | className={ |
| 63 | config.active |
| 64 | ? 'flex flex-col gap-3 rounded-lg border border-[#96b77f]/80 bg-[#eef6e8] p-3 shadow-[inset_3px_0_0_#6f8f64] sm:flex-row sm:items-center sm:justify-between' |
| 65 | : 'flex flex-col gap-3 rounded-lg border border-[#d8ccb5]/80 bg-[#fffdf8]/78 p-3 sm:flex-row sm:items-center sm:justify-between' |
| 66 | } |
| 67 | > |
| 68 | <div className="min-w-0"> |
| 69 | <div className="flex flex-wrap items-center gap-2"> |
| 70 | {config.active && <CheckCircle2 className="h-4 w-4 text-[#5d7b4d]" />} |
| 71 | <p className="font-medium text-[#33402a]">{config.name}</p> |
| 72 | <span className="rounded-full bg-[#e9efde] px-2 py-0.5 text-[11px] uppercase text-[#506141]"> |
| 73 | {config.provider} |
| 74 | </span> |
| 75 | </div> |
| 76 | <p className="mt-1 truncate text-xs text-muted-foreground"> |
| 77 | {summarizeImageModelConfig(config.modelConfig)} |
| 78 | </p> |
| 79 | </div> |
| 80 | <div className="flex shrink-0 flex-wrap gap-2"> |
| 81 | <Button |
| 82 | size="sm" |
| 83 | variant={config.active ? 'secondary' : 'outline'} |
| 84 | disabled={config.active || activatingImageId === config.id} |
| 85 | onClick={() => onActivate(config.id)} |
| 86 | > |
| 87 | {config.active |
| 88 | ? t('settings.activeImageModel') |
| 89 | : t('settings.activateImageModel')} |
| 90 | </Button> |
| 91 | <Button size="sm" variant="ghost" onClick={() => onEdit(config)}> |
| 92 | <Pencil className="h-4 w-4" /> |
| 93 | </Button> |
| 94 | <Button |
| 95 | size="sm" |
| 96 | variant="ghost" |
| 97 | disabled={deletingImageId === config.id} |
| 98 | onClick={() => onDelete(config)} |
| 99 | > |
| 100 | <Trash2 className="h-4 w-4" /> |
| 101 | </Button> |
| 102 | </div> |
| 103 | </div> |
| 104 | )) |
| 105 | )} |
| 106 | </CardContent> |
| 107 | </Card> |
| 108 | ) |
| 109 | } |
| 110 |