@@ -5,35 +5,33 @@ import { useTranslation, Trans } from "react-i18next"
55import { VSCodeLink } from "@vscode/webview-ui-toolkit/react"
66import { StandardTooltip } from "../ui/standard-tooltip"
77
8- interface CommandPattern {
9- pattern : string
10- description ?: string
11- }
12-
138interface CommandPatternSelectorProps {
14- patterns : CommandPattern [ ]
9+ command : string
1510 allowedCommands : string [ ]
1611 deniedCommands : string [ ]
17- onAllowPatternChange : ( pattern : string ) => void
18- onDenyPatternChange : ( pattern : string ) => void
12+ onAllowCommandChange : ( command : string ) => void
13+ onDenyCommandChange : ( command : string ) => void
1914}
2015
2116export const CommandPatternSelector : React . FC < CommandPatternSelectorProps > = ( {
22- patterns ,
17+ command ,
2318 allowedCommands,
2419 deniedCommands,
25- onAllowPatternChange ,
26- onDenyPatternChange ,
20+ onAllowCommandChange ,
21+ onDenyCommandChange ,
2722} ) => {
2823 const { t } = useTranslation ( )
2924 const [ isExpanded , setIsExpanded ] = useState ( false )
25+ const [ editedCommand , setEditedCommand ] = useState ( command )
3026
31- const getPatternStatus = ( pattern : string ) : "allowed" | "denied" | "none" => {
32- if ( allowedCommands . includes ( pattern ) ) return "allowed"
33- if ( deniedCommands . includes ( pattern ) ) return "denied"
27+ const getCommandStatus = ( cmd : string ) : "allowed" | "denied" | "none" => {
28+ if ( allowedCommands . includes ( cmd ) ) return "allowed"
29+ if ( deniedCommands . includes ( cmd ) ) return "denied"
3430 return "none"
3531 }
3632
33+ const currentStatus = getCommandStatus ( editedCommand )
34+
3735 return (
3836 < div className = "border-t border-vscode-panel-border bg-vscode-sideBar-background/30" >
3937 < button
@@ -80,53 +78,48 @@ export const CommandPatternSelector: React.FC<CommandPatternSelectorProps> = ({
8078 </ button >
8179
8280 { isExpanded && (
83- < div className = "px-3 pb-3 space-y-2" >
84- { patterns . map ( ( item ) => {
85- const status = getPatternStatus ( item . pattern )
86- return (
87- < div key = { item . pattern } className = "ml-5 flex items-center gap-2" >
88- < div className = "flex-1" >
89- < span className = "font-mono text-xs text-vscode-foreground" > { item . pattern } </ span >
90- { item . description && (
91- < span className = "text-xs text-vscode-descriptionForeground ml-2" >
92- - { item . description }
93- </ span >
94- ) }
95- </ div >
96- < div className = "flex items-center gap-1" >
97- < button
98- className = { cn ( "p-1 rounded transition-all" , {
99- "bg-green-500/20 text-green-500 hover:bg-green-500/30" :
100- status === "allowed" ,
101- "text-vscode-descriptionForeground hover:text-green-500 hover:bg-green-500/10" :
102- status !== "allowed" ,
103- } ) }
104- onClick = { ( ) => onAllowPatternChange ( item . pattern ) }
105- aria-label = { t (
106- status === "allowed"
107- ? "chat:commandExecution.removeFromAllowed"
108- : "chat:commandExecution.addToAllowed" ,
109- ) } >
110- < Check className = "size-3.5" />
111- </ button >
112- < button
113- className = { cn ( "p-1 rounded transition-all" , {
114- "bg-red-500/20 text-red-500 hover:bg-red-500/30" : status === "denied" ,
115- "text-vscode-descriptionForeground hover:text-red-500 hover:bg-red-500/10" :
116- status !== "denied" ,
117- } ) }
118- onClick = { ( ) => onDenyPatternChange ( item . pattern ) }
119- aria-label = { t (
120- status === "denied"
121- ? "chat:commandExecution.removeFromDenied"
122- : "chat:commandExecution.addToDenied" ,
123- ) } >
124- < X className = "size-3.5" />
125- </ button >
126- </ div >
127- </ div >
128- )
129- } ) }
81+ < div className = "px-3 pb-3" >
82+ < div className = "ml-5 flex items-center gap-2" >
83+ < div className = "flex-1" >
84+ < input
85+ type = "text"
86+ value = { editedCommand }
87+ onChange = { ( e ) => setEditedCommand ( e . target . value ) }
88+ className = "font-mono text-xs bg-vscode-input-background text-vscode-input-foreground border border-vscode-input-border rounded px-2 py-1 w-full focus:outline-none focus:border-vscode-focusBorder"
89+ placeholder = { command }
90+ />
91+ </ div >
92+ < div className = "flex items-center gap-1" >
93+ < button
94+ className = { cn ( "p-1 rounded transition-all" , {
95+ "bg-green-500/20 text-green-500 hover:bg-green-500/30" : currentStatus === "allowed" ,
96+ "text-vscode-descriptionForeground hover:text-green-500 hover:bg-green-500/10" :
97+ currentStatus !== "allowed" ,
98+ } ) }
99+ onClick = { ( ) => onAllowCommandChange ( editedCommand ) }
100+ aria-label = { t (
101+ currentStatus === "allowed"
102+ ? "chat:commandExecution.removeFromAllowed"
103+ : "chat:commandExecution.addToAllowed" ,
104+ ) } >
105+ < Check className = "size-3.5" />
106+ </ button >
107+ < button
108+ className = { cn ( "p-1 rounded transition-all" , {
109+ "bg-red-500/20 text-red-500 hover:bg-red-500/30" : currentStatus === "denied" ,
110+ "text-vscode-descriptionForeground hover:text-red-500 hover:bg-red-500/10" :
111+ currentStatus !== "denied" ,
112+ } ) }
113+ onClick = { ( ) => onDenyCommandChange ( editedCommand ) }
114+ aria-label = { t (
115+ currentStatus === "denied"
116+ ? "chat:commandExecution.removeFromDenied"
117+ : "chat:commandExecution.addToDenied" ,
118+ ) } >
119+ < X className = "size-3.5" />
120+ </ button >
121+ </ div >
122+ </ div >
130123 </ div >
131124 ) }
132125 </ div >
0 commit comments