11import React from "react"
2- import { ListChecks , LayoutList , Settings , CheckCheck } from "lucide-react"
2+ import { ListChecks , LayoutList , Settings , CheckCheck , X } from "lucide-react"
33
44import { vscode } from "@/utils/vscode"
55import { cn } from "@/lib/utils"
66import { useExtensionState } from "@/context/ExtensionStateContext"
77import { useAppTranslation } from "@/i18n/TranslationContext"
88import { useRooPortal } from "@/components/ui/hooks/useRooPortal"
9- import { Popover , PopoverContent , PopoverTrigger , StandardTooltip } from "@/components/ui"
9+ import { Popover , PopoverContent , PopoverTrigger , StandardTooltip , ToggleSwitch } from "@/components/ui"
1010import { AutoApproveSetting , autoApproveSettingsConfig } from "../settings/AutoApproveToggle"
1111import { useAutoApprovalToggles } from "@/hooks/useAutoApprovalToggles"
12+ import { useAutoApprovalState } from "@/hooks/useAutoApprovalState"
1213
1314interface AutoApproveDropdownProps {
1415 disabled ?: boolean
@@ -124,20 +125,24 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
124125 Object . keys ( autoApproveSettingsConfig ) . forEach ( ( key ) => {
125126 onAutoApproveToggle ( key as AutoApproveSetting , false )
126127 } )
127- // Disable master auto-approval
128- if ( autoApprovalEnabled ) {
129- setAutoApprovalEnabled ( false )
130- vscode . postMessage ( { type : "autoApprovalEnabled" , bool : false } )
131- }
132- } , [ onAutoApproveToggle , autoApprovalEnabled , setAutoApprovalEnabled ] )
128+ } , [ onAutoApproveToggle ] )
133129
134130 const handleOpenSettings = React . useCallback (
135131 ( ) =>
136132 window . postMessage ( { type : "action" , action : "settingsButtonClicked" , values : { section : "autoApprove" } } ) ,
137133 [ ] ,
138134 )
139135
136+ // Handle the main auto-approval toggle
137+ const handleAutoApprovalToggle = React . useCallback ( ( ) => {
138+ const newValue = ! ( autoApprovalEnabled ?? false )
139+ setAutoApprovalEnabled ( newValue )
140+ vscode . postMessage ( { type : "autoApprovalEnabled" , bool : newValue } )
141+ } , [ autoApprovalEnabled , setAutoApprovalEnabled ] )
142+
140143 // Calculate enabled and total counts as separate properties
144+ const settingsArray = Object . values ( autoApproveSettingsConfig )
145+
141146 const enabledCount = React . useMemo ( ( ) => {
142147 return Object . values ( toggles ) . filter ( ( value ) => ! ! value ) . length
143148 } , [ toggles ] )
@@ -146,8 +151,7 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
146151 return Object . keys ( toggles ) . length
147152 } , [ toggles ] )
148153
149- // Split settings into two columns
150- const settingsArray = Object . values ( autoApproveSettingsConfig )
154+ const { effectiveAutoApprovalEnabled } = useAutoApprovalState ( toggles , autoApprovalEnabled )
151155
152156 return (
153157 < Popover open = { open } onOpenChange = { setOpen } data-testid = "auto-approve-dropdown-root" >
@@ -164,11 +168,18 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
164168 : "opacity-90 hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)] cursor-pointer" ,
165169 triggerClassName ,
166170 ) } >
167- < CheckCheck className = "size-3 flex-shrink-0" />
171+ { ! effectiveAutoApprovalEnabled ? (
172+ < X className = "size-3 flex-shrink-0" />
173+ ) : (
174+ < CheckCheck className = "size-3 flex-shrink-0" />
175+ ) }
176+
168177 < span className = "truncate min-w-0" >
169- { enabledCount === totalCount
170- ? t ( "chat:autoApprove.triggerLabelAll" )
171- : t ( "chat:autoApprove.triggerLabel" , { count : enabledCount } ) }
178+ { ! effectiveAutoApprovalEnabled
179+ ? t ( "chat:autoApprove.triggerLabelOff" )
180+ : enabledCount === totalCount
181+ ? t ( "chat:autoApprove.triggerLabelAll" )
182+ : t ( "chat:autoApprove.triggerLabel" , { count : enabledCount } ) }
172183 </ span >
173184 </ PopoverTrigger >
174185 </ StandardTooltip >
@@ -206,10 +217,13 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
206217 "transition-all duration-150" ,
207218 "opacity-100 hover:opacity-70" ,
208219 "cursor-pointer" ,
220+ ! effectiveAutoApprovalEnabled &&
221+ "opacity-50 cursor-not-allowed hover:opacity-50" ,
209222 isEnabled
210223 ? "bg-vscode-button-background text-vscode-button-foreground"
211224 : "bg-vscode-button-background/15 text-vscode-foreground hover:bg-vscode-list-hoverBackground" ,
212225 ) }
226+ disabled = { ! effectiveAutoApprovalEnabled }
213227 data-testid = { `auto-approve-${ key } ` } >
214228 < span className = { `codicon codicon-${ icon } text-sm flex-shrink-0` } />
215229 < span className = "flex-1 truncate" > { t ( labelKey ) } </ span >
@@ -225,6 +239,7 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
225239 < button
226240 aria-label = { t ( "chat:autoApprove.selectAll" ) }
227241 onClick = { handleSelectAll }
242+ disabled = { ! effectiveAutoApprovalEnabled }
228243 className = { cn (
229244 "relative inline-flex items-center justify-center gap-1" ,
230245 "bg-transparent border-none px-2 py-1" ,
@@ -235,13 +250,15 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
235250 "focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder" ,
236251 "active:bg-[rgba(255,255,255,0.1)]" ,
237252 "cursor-pointer" ,
253+ ! effectiveAutoApprovalEnabled && "opacity-50 hover:opacity-50 cursor-not-allowed" ,
238254 ) } >
239255 < ListChecks className = "w-3.5 h-3.5" />
240256 < span > { t ( "chat:autoApprove.all" ) } </ span >
241257 </ button >
242258 < button
243259 aria-label = { t ( "chat:autoApprove.selectNone" ) }
244260 onClick = { handleSelectNone }
261+ disabled = { ! effectiveAutoApprovalEnabled }
245262 className = { cn (
246263 "relative inline-flex items-center justify-center gap-1" ,
247264 "bg-transparent border-none px-2 py-1" ,
@@ -252,11 +269,30 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
252269 "focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder" ,
253270 "active:bg-[rgba(255,255,255,0.1)]" ,
254271 "cursor-pointer" ,
272+ ! effectiveAutoApprovalEnabled && "opacity-50 hover:opacity-50 cursor-not-allowed" ,
255273 ) } >
256274 < LayoutList className = "w-3.5 h-3.5" />
257275 < span > { t ( "chat:autoApprove.none" ) } </ span >
258276 </ button >
259277 </ div >
278+
279+ < label
280+ className = "flex items-center gap-2 pr-2 cursor-pointer"
281+ onClick = { ( e ) => {
282+ // Prevent label click when clicking on the toggle switch itself
283+ if ( ( e . target as HTMLElement ) . closest ( '[role="switch"]' ) ) {
284+ e . preventDefault ( )
285+ return
286+ }
287+ handleAutoApprovalToggle ( )
288+ } } >
289+ < ToggleSwitch
290+ checked = { effectiveAutoApprovalEnabled }
291+ aria-label = "Toggle auto-approval"
292+ onChange = { handleAutoApprovalToggle }
293+ />
294+ < span className = { cn ( "text-sm font-bold select-none" ) } > Enabled</ span >
295+ </ label >
260296 </ div >
261297 </ div >
262298 </ PopoverContent >
0 commit comments