import React, { useState, useRef, useCallback } from 'react'; import type { Agent } from '../hooks/useAgents'; import { useDismissablePopover } from '../hooks/useDismissablePopover'; import { getAgentSwitchSettings, saveAgentSwitchSettings, type AgentSwitchSettings } from '../utils/agentSwitch'; interface ApproveDropdownProps { onApprove: () => void; agents: Agent[]; disabled?: boolean; isLoading?: boolean; } function getSelectedLabel(setting: AgentSwitchSettings, agents: Agent[]): string | null { if (setting.switchTo === 'disabled') return null; if (setting.switchTo === 'custom' && setting.customName) { return setting.customName; } const match = agents.find(a => a.id.toLowerCase() === setting.switchTo.toLowerCase()); return match?.name ?? setting.switchTo; } function isSelected(agentId: string, setting: AgentSwitchSettings): boolean { if (setting.switchTo === 'custom') return false; if (setting.switchTo === 'disabled') return false; return agentId.toLowerCase() === setting.switchTo.toLowerCase(); } const Checkmark = () => ( ); export const ApproveDropdown: React.FC = ({ onApprove, agents, disabled = false, isLoading = false, }) => { const [setting, setSetting] = useState(() => getAgentSwitchSettings('plan')); const [isOpen, setIsOpen] = useState(false); const dropdownRef = useRef(null); // Shared dismissal (outside pointerdown + Escape), active only while open — // the old always-on listeners were no-ops when closed. The hook consumes the // dismissing Escape so it cannot double as a host-ladder Escape. const dismiss = useCallback(() => setIsOpen(false), []); useDismissablePopover({ enabled: isOpen, ref: dropdownRef, onDismiss: dismiss, }); const handleSelect = (newSetting: AgentSwitchSettings) => { setSetting(newSetting); saveAgentSwitchSettings(newSetting); setIsOpen(false); }; const agentLabel = getSelectedLabel(setting, agents); const isNoSwitch = setting.switchTo === 'disabled'; const isCustom = setting.switchTo === 'custom'; const notFound = agentLabel && !isNoSwitch && !isCustom && !agents.some(a => a.id.toLowerCase() === setting.switchTo.toLowerCase()); const baseClasses = disabled ? 'opacity-50 cursor-not-allowed bg-muted text-muted-foreground' : 'bg-success text-success-foreground hover:opacity-90'; const handleApproveClick = () => { setIsOpen(false); onApprove(); }; return (
{/* Mobile: simple button */} {/* Desktop: split button */}
{/* Dropdown */} {isOpen && (
Switch to agent
{agents.map((agent) => { const selected = isSelected(agent.id, setting); return ( ); })} {isCustom && setting.customName && ( )}
)}
); };