diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e302183..1337e8f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -28,7 +28,7 @@ jobs: run: bun install --frozen-lockfile - name: Run server tests - run: bun test + run: bun test ./src client-tests: strategy: diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..bbd4fc9 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "testing.exclude": { + "**/Overlord-Server/dist/**": true + } +} diff --git a/Dockerfile b/Dockerfile index 6662a1a..d8f250f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,6 +5,9 @@ WORKDIR /app # Install Go for agent building and other tools RUN apt-get update \ && apt-get install -y --no-install-recommends \ + build-essential \ + gcc-mingw-w64-x86-64 \ + gcc-mingw-w64-i686 \ openssl \ curl \ ca-certificates \ diff --git a/Overlord-Client/cmd/agent/handlers/screenshot.go b/Overlord-Client/cmd/agent/handlers/screenshot.go index f9264a4..40d735d 100644 --- a/Overlord-Client/cmd/agent/handlers/screenshot.go +++ b/Overlord-Client/cmd/agent/handlers/screenshot.go @@ -18,9 +18,9 @@ import ( ) var ( - monitorCountFn = capture.MonitorCount - displayBoundsFn = capture.DisplayBounds - captureDisplayRGBABitBltFn = capture.CaptureDisplayRGBABitBlt + monitorCountFn = capture.MonitorCount + displayBoundsFn = capture.DisplayBounds + captureDisplayRGBABitBltFn = capture.CaptureDisplayRGBABitBlt ) func HandleScreenshot(ctx context.Context, env *rt.Env, cmdID string, allDisplays bool) error { diff --git a/Overlord-Server/public/assets/build.js b/Overlord-Server/public/assets/build.js index 87ea073..07db1bd 100644 --- a/Overlord-Server/public/assets/build.js +++ b/Overlord-Server/public/assets/build.js @@ -235,9 +235,15 @@ async function startBuild(config) { "info", ); - await streamBuildOutput(buildId); + await streamBuildOutput(buildId, config); } catch (err) { addBuildOutput(`\nERROR: ${err.message}\n`, "error"); + if (!config.disableCgo) { + addBuildOutput( + "Hint: This build used CGO. If it keeps failing, try enabling the 'Disable CGO' option and build again.\n", + "warn", + ); + } buildStatusText.textContent = "Build failed"; buildStatus.querySelector("div").className = "flex items-center gap-2 p-3 rounded-lg bg-red-900/40 border border-red-700/60"; @@ -250,7 +256,7 @@ async function startBuild(config) { } } -async function streamBuildOutput(buildId) { +async function streamBuildOutput(buildId, config = {}) { const res = await fetch(`/api/build/${buildId}/stream`, { credentials: "include", }); @@ -295,6 +301,13 @@ async function streamBuildOutput(buildId) { ? "fa-solid fa-circle-check" : "fa-solid fa-circle-xmark"; + if (!data.success && !config.disableCgo) { + addBuildOutput( + "Hint: This build used CGO. If it keeps failing, try enabling the 'Disable CGO' option and build again.\n", + "warn", + ); + } + if (data.success && data.files) { const buildData = { id: data.buildId, diff --git a/Overlord-Server/public/assets/main.js b/Overlord-Server/public/assets/main.js index 45bd402..539e2d9 100644 --- a/Overlord-Server/public/assets/main.js +++ b/Overlord-Server/public/assets/main.js @@ -443,6 +443,27 @@ bulkUninstallBtn?.addEventListener("click", async () => { window.toggleClientSelection = toggleClientSelection; window.isClientSelected = (clientId) => selectedClients.has(clientId); window.syncClientSelection = syncSelectionState; +window.removeClientFromDashboard = async (clientId) => { + if (!clientId) return false; + try { + const res = await fetch(`/api/clients/${clientId}`, { + method: "DELETE", + headers: { "Content-Type": "application/json" }, + }); + if (!res.ok) { + const data = await res.json().catch(() => ({})); + alert(data.error || "Failed to remove client from dashboard"); + return false; + } + selectedClients.delete(clientId); + return true; + } catch (err) { + console.error(err); + alert("Failed to remove client from dashboard"); + return false; + } +}; + window.banClient = async (clientId) => { if (!clientId) return; if (!confirm(`Ban IP for ${clientId} and block future connections?`)) return; @@ -578,6 +599,23 @@ menu.addEventListener("click", async (e) => { closeMenu(clearContext); return; } + } else if (action === "remove-dashboard") { + if ( + !confirm( + `Remove ${contextCard} from the dashboard list?\n\nUse this for stale clients that are already gone. If that client reconnects later, it will appear again.`, + ) + ) { + closeMenu(clearContext); + return; + } + + const removed = await window.removeClientFromDashboard(contextCard); + if (removed) { + updateBulkToolbar(); + setTimeout(() => loadWithOptions({ force: true }), 200); + } + closeMenu(clearContext); + return; } const ok = await sendCommand(contextCard, action); diff --git a/Overlord-Server/public/assets/ui.js b/Overlord-Server/public/assets/ui.js index 4321d47..14205a6 100644 --- a/Overlord-Server/public/assets/ui.js +++ b/Overlord-Server/public/assets/ui.js @@ -17,6 +17,7 @@ menu.innerHTML = ` +