From 9405824d7be820038490354f6639c2289fc0cb77 Mon Sep 17 00:00:00 2001 From: Amrit Subramanian Date: Sun, 5 Oct 2025 16:13:23 -0400 Subject: [PATCH] Add loading spinner to MCP add button during polling - Send mcp-polling-started event from main process before each poll - Show spinner on add button when polling starts - Restore + button when mcp-servers-updated event received - Spinner shows on initial load and every 60s refresh --- main.ts | 5 +++++ renderer.ts | 37 +++++++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/main.ts b/main.ts index 999d415..69980e2 100644 --- a/main.ts +++ b/main.ts @@ -158,6 +158,11 @@ function spawnMcpPoller(sessionId: string, projectDir: string) { console.log(`[MCP Poller ${sessionId}] Starting polling loop`); const pollMcp = () => { if (mcpPollerPtyProcesses.has(sessionId)) { + // Notify renderer that polling is starting + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.webContents.send("mcp-polling-started", sessionId); + } + const command = `claude mcp list`; console.log(`[MCP Poller ${sessionId}] Running command: ${command}`); ptyProcess.write(command + "\r"); diff --git a/renderer.ts b/renderer.ts index 1dab449..63bfb5b 100644 --- a/renderer.ts +++ b/renderer.ts @@ -225,6 +225,7 @@ const DEFAULT_SETTINGS: TerminalSettings = { const sessions = new Map(); let activeSessionId: string | null = null; let mcpServers: McpServer[] = []; +let mcpPollerActive = false; let terminalSettings: TerminalSettings = { ...DEFAULT_SETTINGS }; function createTerminalUI(sessionId: string) { @@ -962,25 +963,11 @@ async function loadMcpServers() { return; } - const addMcpServerBtn = document.getElementById("add-mcp-server"); - - // Show loading spinner - if (addMcpServerBtn) { - addMcpServerBtn.innerHTML = ''; - addMcpServerBtn.classList.add("pointer-events-none"); - } - try { await ipcRenderer.invoke("list-mcp-servers", activeSessionId); // Results will come via mcp-servers-updated event } catch (error) { console.error("Failed to load MCP servers:", error); - } finally { - // Restore button - if (addMcpServerBtn) { - addMcpServerBtn.innerHTML = '+'; - addMcpServerBtn.classList.remove("pointer-events-none"); - } } } @@ -1243,12 +1230,34 @@ removeMcpDetailsBtn?.addEventListener("click", async () => { } }); +// Listen for MCP polling started event +ipcRenderer.on("mcp-polling-started", (_event, sessionId: string) => { + console.log(`[MCP UI] Polling started for session ${sessionId}, active: ${activeSessionId}`); + if (sessionId === activeSessionId) { + const addMcpServerBtn = document.getElementById("add-mcp-server"); + if (addMcpServerBtn) { + console.log("[MCP UI] Setting add button to loading state"); + addMcpServerBtn.innerHTML = ''; + addMcpServerBtn.classList.add("pointer-events-none"); + } + } +}); + // Listen for MCP server updates from main process ipcRenderer.on("mcp-servers-updated", (_event, sessionId: string, servers: McpServer[]) => { + console.log(`[MCP UI] Received update for session ${sessionId}, active: ${activeSessionId}`); // Only update if this is for the active session if (sessionId === activeSessionId) { mcpServers = servers; renderMcpServers(); + + // Restore add button + console.log("[MCP UI] Restoring add button from loading state"); + const addMcpServerBtn = document.getElementById("add-mcp-server"); + if (addMcpServerBtn) { + addMcpServerBtn.innerHTML = '+'; + addMcpServerBtn.classList.remove("pointer-events-none"); + } } });