Skip to main content
Glama
popup.js9.29 kB
// ../shared/src/popup/index.ts var statusEl = document.getElementById("status"); var connectedTabEl = document.getElementById("connected-tab"); var serverStatusEl = document.getElementById("server-status"); var serverStatusTextEl = document.getElementById("server-status-text"); var serverSpinnerEl = document.getElementById("server-spinner"); var tabInfoContainer = document.getElementById("tab-info"); var nameEl = document.getElementById("tab-name"); var urlEl = document.getElementById("tab-url"); var goToTabButton = document.getElementById("go-to-tab"); var iconEl = document.getElementById("header-icon"); var connectButton = document.getElementById("connect"); var disconnectButton = document.getElementById("disconnect"); var portModeSelect = document.getElementById("port-mode"); var reconnectButton = document.getElementById("reconnect"); var manualPortGroup = document.getElementById("port-manual-group"); var portSelect = document.getElementById("port-select"); var applyPortButton = document.getElementById("apply-port"); var applyTextEl = document.getElementById("apply-text"); var applySpinnerEl = document.getElementById("apply-spinner"); console.log("YetiBrowser popup loaded - NEW VERSION WITH PORT SELECT", { portSelect, applyTextEl, applySpinnerEl }); var lastError = null; connectButton.addEventListener("click", async () => { lastError = null; try { const activeTab = await getActiveTab(); if (!activeTab || activeTab.id === void 0) { throw new Error("Unable to determine active tab"); } if (!isUrlAllowed(activeTab.url ?? "")) { throw new Error("This page cannot be controlled. Switch to an http(s) tab and try again."); } await chrome.runtime.sendMessage({ type: "yetibrowser/connect", tabId: activeTab.id }); } catch (error) { lastError = error instanceof Error ? error.message : String(error); } finally { await refresh(); } }); disconnectButton.addEventListener("click", async () => { lastError = null; try { await chrome.runtime.sendMessage({ type: "yetibrowser/disconnect" }); } catch (error) { lastError = error instanceof Error ? error.message : String(error); } finally { await refresh(); } }); portModeSelect.addEventListener("change", async () => { const mode = portModeSelect.value === "manual" ? "manual" : "auto"; if (mode === "auto") { manualPortGroup.hidden = true; portSelect.disabled = true; applyPortButton.disabled = true; await applyPortConfiguration(mode); } else { manualPortGroup.hidden = false; portSelect.disabled = false; applyPortButton.disabled = false; portSelect.focus(); } }); applyPortButton.addEventListener("click", async () => { const portValue = Number.parseInt(portSelect.value, 10); if (!Number.isInteger(portValue) || portValue <= 0 || portValue > 65535) { lastError = "Invalid port selected"; await refresh(); return; } await applyPortConfiguration("manual", portValue); }); reconnectButton.addEventListener("click", async () => { lastError = null; reconnectButton.disabled = true; try { const response = await chrome.runtime.sendMessage({ type: "yetibrowser/reconnect" }); if (!response?.ok) { throw new Error(response?.error ?? "Failed to reconnect"); } await waitForSocketConnection(); } catch (error) { lastError = error instanceof Error ? error.message : String(error); } finally { await refresh(); reconnectButton.disabled = false; } }); void refresh(); async function refresh() { const state = await chrome.runtime.sendMessage({ type: "yetibrowser/getState" }); const activeTab = await getActiveTab(); const connectedTab = state?.tabId ? await chrome.tabs.get(state.tabId).catch(() => void 0) : void 0; updateUi(state, activeTab, connectedTab); } function updateUi(state, activeTab, connectedTab) { const { tabId, socketConnected, wsPort, portMode, socketStatus = "disconnected" } = state; const activeTabId = activeTab?.id ?? null; const isConnectedToActive = tabId !== null && tabId === activeTabId; connectButton.disabled = !activeTabId || isConnectedToActive || !isUrlAllowed(activeTab?.url ?? ""); disconnectButton.disabled = tabId === null; goToTabButton.disabled = tabId === null; portModeSelect.value = portMode; manualPortGroup.hidden = portMode !== "manual"; portSelect.disabled = portMode !== "manual"; applyPortButton.disabled = portMode !== "manual"; portSelect.value = String(wsPort); if (tabId && connectedTab) { const suffix = isConnectedToActive ? " (current)" : ""; connectedTabEl.textContent = `#${tabId}${suffix}`; connectedTabEl.classList.remove("error"); } else { connectedTabEl.textContent = "None"; connectedTabEl.classList.add("error"); } const modeLabel = portMode === "auto" ? "auto" : "manual"; if (socketStatus === "connecting") { serverStatusTextEl.textContent = `ws://localhost:${wsPort} (${modeLabel}) \u2014 connecting\u2026`; serverStatusEl.classList.add("error"); serverSpinnerEl.hidden = false; } else if (socketConnected) { serverStatusTextEl.textContent = `ws://localhost:${wsPort} (${modeLabel})`; serverStatusEl.classList.remove("error"); serverSpinnerEl.hidden = true; } else { serverStatusTextEl.textContent = `ws://localhost:${wsPort} (${modeLabel}) \u2014 not connected`; serverStatusEl.classList.add("error"); serverSpinnerEl.hidden = true; } statusEl.classList.remove("error"); if (lastError) { statusEl.textContent = lastError; statusEl.classList.add("error"); } else if (socketStatus === "connecting") { statusEl.textContent = "Scanning for an MCP server\u2026"; } else if (tabId && !isConnectedToActive) { statusEl.textContent = "We\u2019ll interact with this tab even if another is focused."; } else { statusEl.textContent = tabId ? "Connected" : "Not connected"; if (!tabId) { statusEl.classList.add("error"); } } if (connectedTab) { tabInfoContainer.hidden = false; nameEl.textContent = truncate(connectedTab.title ?? "Untitled"); const href = connectedTab.url ?? ""; if (href) { urlEl.textContent = truncate(href, 60); urlEl.href = href; urlEl.hidden = false; } else { urlEl.textContent = ""; urlEl.removeAttribute("href"); urlEl.hidden = true; } } else { tabInfoContainer.hidden = true; nameEl.textContent = ""; urlEl.textContent = ""; urlEl.removeAttribute("href"); urlEl.hidden = true; } iconEl.hidden = false; } async function getActiveTab() { const tabs = await chrome.tabs.query({ active: true, currentWindow: true }); return tabs[0]; } async function applyPortConfiguration(mode, port) { lastError = null; showSpinner(true); try { const response = await chrome.runtime.sendMessage({ type: "yetibrowser/setPortConfig", mode, port }); if (!response?.ok) { throw new Error(response?.error ?? "Failed to update port configuration"); } await waitForSocketConnection(); } catch (error) { lastError = error instanceof Error ? error.message : String(error); } finally { showSpinner(false); await refresh(); } } async function waitForSocketConnection(maxWaitMs = 5e3) { const start = Date.now(); let checkCount = 0; while (Date.now() - start < maxWaitMs) { const state = await chrome.runtime.sendMessage({ type: "yetibrowser/getState" }); const activeTab = await getActiveTab(); const connectedTab = state?.tabId ? await chrome.tabs.get(state.tabId).catch(() => void 0) : void 0; if (state) { updateUi(state, activeTab, connectedTab); } if (state?.socketConnected && state?.socketStatus === "open") { return; } const delayMs = checkCount < 10 ? 50 : checkCount < 20 ? 100 : 200; checkCount++; await delay(delayMs); } } goToTabButton.addEventListener("click", async () => { const state = await chrome.runtime.sendMessage({ type: "yetibrowser/getState" }); if (!state?.tabId) { return; } try { await chrome.tabs.update(state.tabId, { active: true }); const tab = await chrome.tabs.get(state.tabId); if (tab.windowId !== void 0) { await chrome.windows.update(tab.windowId, { focused: true }); } } catch (error) { lastError = error instanceof Error ? error.message : String(error); await refresh(); } }); function isUrlAllowed(url) { if (!url) { return false; } if (url.startsWith("chrome://") || url.startsWith("chrome-extension://")) { return false; } if (url.startsWith("edge://") || url.startsWith("about:")) { return false; } return true; } function truncate(value, max = 40) { if (value.length <= max) { return value; } return `${value.slice(0, max - 1)}\u2026`; } function delay(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } function showSpinner(show) { if (show) { applyTextEl.hidden = true; applySpinnerEl.hidden = false; applyPortButton.disabled = true; reconnectButton.disabled = true; } else { applyTextEl.hidden = false; applySpinnerEl.hidden = true; applyPortButton.disabled = false; reconnectButton.disabled = false; } } //# sourceMappingURL=popup.js.map

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yetidevworks/yetibrowser-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server