From 7838760ca41149cba38d7e9c9df64a05870b39e3 Mon Sep 17 00:00:00 2001 From: dtoro Date: Sun, 5 Apr 2026 00:39:32 +0200 Subject: [PATCH] feat: add self to graph --- frontend/src/routes/BrowseView.tsx | 45 +++++++++++++++++++----------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/frontend/src/routes/BrowseView.tsx b/frontend/src/routes/BrowseView.tsx index 0e159b0..6ac288f 100644 --- a/frontend/src/routes/BrowseView.tsx +++ b/frontend/src/routes/BrowseView.tsx @@ -105,10 +105,13 @@ function buildGraphArrays( theme: ReturnType, ): BuiltGraph { const interfaces = rawNodes.filter(e => e.type === "interface").sort((a, b) => a.name.localeCompare(b.name)); + const selfNode = rawNodes.find(e => e.is_self && e.type !== "interface"); const peers = rawNodes.filter(e => !e.is_self && e.type !== "interface"); - // Only peers are points — interfaces are clusters, not nodes - const entries = peers; + // Peers + self node are points — interfaces are clusters, not nodes + // Self node goes first so it's easy to find by index + const entries = selfNode ? [selfNode, ...peers] : peers; + const selfIndex = selfNode ? 0 : -1; const n = entries.length; const nClusters = interfaces.length; const hashToIndex = new Map(); @@ -119,11 +122,13 @@ function buildGraphArrays( const clusterStrength = new Float32Array(n); // Cluster map: interface name → cluster index + // Self node gets its own cluster at the end const clusterMap = new Map(); interfaces.forEach((iface, i) => clusterMap.set(iface.name, i)); + const selfClusterIndex = interfaces.length; // Cluster names for labels - const clusterNames = interfaces.map(i => i.name); + const clusterNames = [...interfaces.map(i => i.name), ...(selfNode ? [selfNode.name] : [])]; // No explicit cluster positions — let cosmos use centermass const clusterPositions: (number | undefined)[] = []; @@ -141,8 +146,10 @@ function buildGraphArrays( positions[i * 2 + 1] = CENTER + (Math.random() - 0.5) * SPACE_SIZE * 0.5; } - // Colors — by status - const rgba = statusRGBA(entry, theme); + // Colors — self node uses bright white, others by status + const rgba = i === selfIndex + ? [1, 1, 1, 1] as [number, number, number, number] + : statusRGBA(entry, theme); colors[i * 4 + 0] = rgba[0]; colors[i * 4 + 1] = rgba[1]; colors[i * 4 + 2] = rgba[2]; @@ -150,11 +157,15 @@ function buildGraphArrays( sizes[i] = 3; - // Cluster assignment — map to parent interface - const pi = peers.indexOf(entry); - const parentHash = findParentIface(entry, interfaces, pi); - const parentName = parentHash ? interfaces.find(f => f.hash === parentHash)?.name : undefined; - clusterIndices.push(parentName !== undefined ? clusterMap.get(parentName) : undefined); + // Cluster assignment — self node gets its own cluster, peers map to parent interface + if (i === selfIndex) { + clusterIndices.push(selfClusterIndex); + } else { + const pi = peers.indexOf(entry); + const parentHash = findParentIface(entry, interfaces, pi); + const parentName = parentHash ? interfaces.find(f => f.hash === parentHash)?.name : undefined; + clusterIndices.push(parentName !== undefined ? clusterMap.get(parentName) : undefined); + } // Cluster strength clusterStrength[i] = nClusters > 1 ? (nClusters - (i % nClusters)) / nClusters : 1; @@ -263,14 +274,16 @@ export default function BrowseView() { div.style.pointerEvents = "none"; div.style.whiteSpace = "nowrap"; div.style.transform = "translate(-50%, -100%)"; - div.style.padding = "2px 8px"; - div.style.borderRadius = "4px"; - div.style.background = "var(--popover)"; - div.style.border = "1px solid var(--border)"; + div.style.padding = "0"; + div.style.background = "none"; + div.style.border = "none"; div.style.color = "var(--foreground)"; div.style.fontFamily = "JetBrains Mono, monospace"; - div.style.fontSize = "11px"; - div.style.boxShadow = "0 2px 8px rgba(0,0,0,0.3)"; + div.style.fontSize = "14px"; + div.style.fontWeight = "700"; + div.style.letterSpacing = "0.05em"; + div.style.textTransform = "uppercase"; + div.style.opacity = "0.85"; div.textContent = names[i] ?? ""; container.appendChild(div); labelDivsRef.current.push(div);