({
availableIDEs,
unavailableIDEs,
currentIDE,
dynamicMcpConfig,
onChangeDynamicMcpConfig,
onDone
}: IDECommandFlowProps)
| 516 | }) => void; |
| 517 | }; |
| 518 | function IDECommandFlow({ |
| 519 | availableIDEs, |
| 520 | unavailableIDEs, |
| 521 | currentIDE, |
| 522 | dynamicMcpConfig, |
| 523 | onChangeDynamicMcpConfig, |
| 524 | onDone |
| 525 | }: IDECommandFlowProps): React.ReactNode { |
| 526 | const [connectingIDE, setConnectingIDE] = useState<DetectedIDEInfo | null>(null); |
| 527 | const ideClient = useAppState(s => s.mcp.clients.find(c => c.name === 'ide')); |
| 528 | const setAppState = useSetAppState(); |
| 529 | const isFirstCheckRef = useRef(true); |
| 530 | |
| 531 | // Watch for connection result |
| 532 | useEffect(() => { |
| 533 | if (!connectingIDE) return; |
| 534 | // Skip the first check — it reflects stale state from before the |
| 535 | // config change was dispatched |
| 536 | if (isFirstCheckRef.current) { |
| 537 | isFirstCheckRef.current = false; |
| 538 | return; |
| 539 | } |
| 540 | if (!ideClient || ideClient.type === 'pending') return; |
| 541 | if (ideClient.type === 'connected') { |
| 542 | onDone(`Connected to ${connectingIDE.name}.`); |
| 543 | } else if (ideClient.type === 'failed') { |
| 544 | onDone(`Failed to connect to ${connectingIDE.name}.`); |
| 545 | } |
| 546 | }, [ideClient, connectingIDE, onDone]); |
| 547 | |
| 548 | // Timeout fallback |
| 549 | useEffect(() => { |
| 550 | if (!connectingIDE) return; |
| 551 | const timer = setTimeout(onDone, IDE_CONNECTION_TIMEOUT_MS, `Connection to ${connectingIDE.name} timed out.`); |
| 552 | return () => clearTimeout(timer); |
| 553 | }, [connectingIDE, onDone]); |
| 554 | const handleSelectIDE = useCallback((selectedIDE?: DetectedIDEInfo) => { |
| 555 | if (!onChangeDynamicMcpConfig) { |
| 556 | onDone('Error connecting to IDE.'); |
| 557 | return; |
| 558 | } |
| 559 | const newConfig = { |
| 560 | ...(dynamicMcpConfig || {}) |
| 561 | }; |
| 562 | if (currentIDE) { |
| 563 | delete newConfig.ide; |
| 564 | } |
| 565 | if (!selectedIDE) { |
| 566 | // Close the MCP transport and remove the client from state |
| 567 | if (ideClient && ideClient.type === 'connected' && currentIDE) { |
| 568 | // Null out onclose to prevent auto-reconnection |
| 569 | ideClient.client.onclose = () => {}; |
| 570 | void clearServerCache('ide', ideClient.config); |
| 571 | setAppState(prev => ({ |
| 572 | ...prev, |
| 573 | mcp: { |
| 574 | ...prev.mcp, |
| 575 | clients: prev.mcp.clients.filter(c_0 => c_0.name !== 'ide'), |
nothing calls this directly
no test coverage detected