11import { useState , useEffect } from 'react' ;
22import { Switch } from '@/components/ui' ;
33import { Input } from '@/components/ui/input' ;
4+ import { Textarea } from '@/components/ui/textarea' ;
5+ import {
6+ Select ,
7+ SelectContent ,
8+ SelectItem ,
9+ SelectTrigger ,
10+ SelectValue ,
11+ } from '@/components/ui/select' ;
412import { ClientIcon } from '@/components/icons/client-icons' ;
513import type { ClientType } from '@/lib/transport' ;
614import type { ClientConfig } from '../types' ;
@@ -9,6 +17,12 @@ import { useTranslation } from 'react-i18next';
917interface ClientsConfigSectionProps {
1018 clients : ClientConfig [ ] ;
1119 onUpdateClient : ( clientId : ClientType , updates : Partial < ClientConfig > ) => void ;
20+ cloak ?: {
21+ mode : 'auto' | 'always' | 'never' ;
22+ strictMode : boolean ;
23+ sensitiveWords : string ;
24+ } ;
25+ onUpdateCloak ?: ( updates : Partial < ClientsConfigSectionProps [ 'cloak' ] > ) => void ;
1226}
1327
1428// Separate component for multiplier input to manage local state
@@ -57,21 +71,24 @@ function MultiplierInput({
5771 ) ;
5872}
5973
60- export function ClientsConfigSection ( { clients, onUpdateClient } : ClientsConfigSectionProps ) {
74+ export function ClientsConfigSection ( {
75+ clients,
76+ onUpdateClient,
77+ cloak,
78+ onUpdateCloak,
79+ } : ClientsConfigSectionProps ) {
6180 const { t } = useTranslation ( ) ;
6281 return (
6382 < div >
64- < div className = "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 " >
65- { clients . map ( ( client ) => (
83+ < div className = "rounded-xl border border-border overflow-hidden bg-card " >
84+ { clients . map ( ( client , index ) => (
6685 < div
6786 key = { client . id }
68- className = { `rounded-xl border transition-all duration-200 flex flex-col ${
69- client . enabled
70- ? 'bg-card border-border shadow-sm'
71- : 'bg-muted/30 border-transparent opacity-80 hover:opacity-100 hover:bg-muted/50'
72- } `}
87+ className = { `px-4 py-4 transition-colors duration-200 ${
88+ client . enabled ? 'bg-card' : 'bg-muted/30'
89+ } ${ index > 0 ? 'border-t border-border' : '' } `}
7390 >
74- < div className = "flex items-center justify-between p-4 border-b border-transparent " >
91+ < div className = "flex items-center justify-between" >
7592 < div className = "flex items-center gap-3" >
7693 < ClientIcon type = { client . id } size = { 32 } />
7794 < span
@@ -90,10 +107,12 @@ export function ClientsConfigSection({ clients, onUpdateClient }: ClientsConfigS
90107
91108 { /* Expandable/Visible Content */ }
92109 < div
93- className = { `px-4 pb-4 transition-all duration-200 ${ client . enabled ? 'opacity-100' : 'opacity-50 grayscale pointer-events-none' } ` }
110+ className = { `pt-4 transition-all duration-200 ${
111+ client . enabled ? 'opacity-100' : 'opacity-50 grayscale pointer-events-none'
112+ } `}
94113 >
95- < div className = "space-y-3 " >
96- < div className = "bg-muted/50 rounded-lg p-3 border border-border/50" >
114+ < div className = "grid grid-cols-1 md:grid-cols-2 gap-4 " >
115+ < div >
97116 < label className = "text-xs font-medium text-muted-foreground block mb-1.5 uppercase tracking-wide" >
98117 { t ( 'provider.endpointOverride' ) }
99118 </ label >
@@ -106,7 +125,7 @@ export function ClientsConfigSection({ clients, onUpdateClient }: ClientsConfigS
106125 className = "text-sm w-full bg-card h-9"
107126 />
108127 </ div >
109- < div className = "bg-muted/50 rounded-lg p-3 border border-border/50" >
128+ < div >
110129 < label className = "text-xs font-medium text-muted-foreground block mb-1.5 uppercase tracking-wide" >
111130 { t ( 'provider.multiplier' , 'Price Multiplier' ) }
112131 </ label >
@@ -123,6 +142,65 @@ export function ClientsConfigSection({ clients, onUpdateClient }: ClientsConfigS
123142 </ div >
124143 </ div >
125144 </ div >
145+
146+ { client . id === 'claude' && cloak && onUpdateCloak && (
147+ < div className = "mt-5 space-y-4" >
148+ < div className = "border-t border-border/60" />
149+ < div >
150+ < label className = "text-xs font-medium text-muted-foreground block mb-1.5 uppercase tracking-wide" >
151+ { t ( 'provider.cloakMode' ) }
152+ </ label >
153+ < Select
154+ value = { cloak . mode }
155+ onValueChange = { ( value ) =>
156+ onUpdateCloak ( { mode : value as 'auto' | 'always' | 'never' } )
157+ }
158+ >
159+ < SelectTrigger className = "w-full" >
160+ < SelectValue placeholder = { t ( 'provider.cloakModeAuto' ) } />
161+ </ SelectTrigger >
162+ < SelectContent >
163+ < SelectItem value = "auto" > { t ( 'provider.cloakModeAuto' ) } </ SelectItem >
164+ < SelectItem value = "always" > { t ( 'provider.cloakModeAlways' ) } </ SelectItem >
165+ < SelectItem value = "never" > { t ( 'provider.cloakModeNever' ) } </ SelectItem >
166+ </ SelectContent >
167+ </ Select >
168+ < p className = "text-xs text-muted-foreground mt-1" >
169+ { t ( 'provider.cloakModeDesc' ) }
170+ </ p >
171+ </ div >
172+
173+ < div className = "flex items-center justify-between gap-3" >
174+ < div className = "space-y-1" >
175+ < p className = "text-sm font-medium text-foreground" >
176+ { t ( 'provider.cloakStrictMode' ) }
177+ </ p >
178+ < p className = "text-xs text-muted-foreground" >
179+ { t ( 'provider.cloakStrictModeDesc' ) }
180+ </ p >
181+ </ div >
182+ < Switch
183+ checked = { cloak . strictMode }
184+ onCheckedChange = { ( checked ) => onUpdateCloak ( { strictMode : checked } ) }
185+ />
186+ </ div >
187+
188+ < div >
189+ < label className = "text-xs font-medium text-muted-foreground block mb-1.5 uppercase tracking-wide" >
190+ { t ( 'provider.cloakSensitiveWords' ) }
191+ </ label >
192+ < Textarea
193+ value = { cloak . sensitiveWords }
194+ onChange = { ( e ) => onUpdateCloak ( { sensitiveWords : e . target . value } ) }
195+ placeholder = { t ( 'provider.cloakSensitiveWordsPlaceholder' ) }
196+ className = "min-h-[88px]"
197+ />
198+ < p className = "text-xs text-muted-foreground mt-1" >
199+ { t ( 'provider.cloakSensitiveWordsDesc' ) }
200+ </ p >
201+ </ div >
202+ </ div >
203+ ) }
126204 </ div >
127205 </ div >
128206 ) ) }
0 commit comments