mirror of
https://github.com/Such-Software/adaptive-multi-protocol-gateway.git
synced 2026-10-17 07:31:32 +02:00
Improve mobile topology maps
This commit is contained in:
+163
-14
@@ -14,6 +14,19 @@
|
||||
const topologies = {
|
||||
vps: {
|
||||
caption: "A VPS shape starts with one source tree, renders transport outputs, then hands them to service-specific daemons on the host.",
|
||||
mobile: {
|
||||
source: [0.12, 0.46],
|
||||
build: [0.31, 0.46],
|
||||
outputs: [0.38, 0.25],
|
||||
state: [0.38, 0.68],
|
||||
vps: [0.55, 0.46],
|
||||
web: [0.72, 0.22],
|
||||
tor: [0.74, 0.4],
|
||||
i2p: [0.72, 0.6],
|
||||
gemini: [0.56, 0.8],
|
||||
reticulum: [0.84, 0.78],
|
||||
visitor: [0.9, 0.5]
|
||||
},
|
||||
nodes: [
|
||||
["source", "source\nsite", 0.11, 0.48, "amber"],
|
||||
["build", "AMPG\nbuild", 0.27, 0.48, "teal"],
|
||||
@@ -47,6 +60,17 @@
|
||||
},
|
||||
router: {
|
||||
caption: "Behind a router, clearnet depends on DNS and a chosen inbound path; onion, I2P, and Reticulum routes can publish without exposing normal web ports.",
|
||||
mobile: {
|
||||
visitor: [0.1, 0.44],
|
||||
dns: [0.26, 0.24],
|
||||
router: [0.42, 0.43],
|
||||
host: [0.58, 0.43],
|
||||
ampg: [0.72, 0.43],
|
||||
clearnet: [0.56, 0.23],
|
||||
onion: [0.55, 0.67],
|
||||
i2p: [0.77, 0.67],
|
||||
rns: [0.86, 0.28]
|
||||
},
|
||||
nodes: [
|
||||
["visitor", "visitor", 0.1, 0.42, "green"],
|
||||
["dns", "DNS /\nDDNS", 0.25, 0.24, "amber"],
|
||||
@@ -75,6 +99,17 @@
|
||||
},
|
||||
phone: {
|
||||
caption: "A spare Android phone can run Termux packages, local AMPG state, and user-space daemons for small always-on sites.",
|
||||
mobile: {
|
||||
phone: [0.13, 0.47],
|
||||
termux: [0.31, 0.26],
|
||||
state: [0.31, 0.67],
|
||||
ampg: [0.48, 0.47],
|
||||
daemons: [0.64, 0.47],
|
||||
network: [0.8, 0.27],
|
||||
routes: [0.82, 0.62],
|
||||
power: [0.5, 0.82],
|
||||
visitor: [0.92, 0.45]
|
||||
},
|
||||
nodes: [
|
||||
["phone", "Android\nphone", 0.14, 0.46, "green"],
|
||||
["termux", "Termux\npackages", 0.31, 0.28, "amber"],
|
||||
@@ -102,6 +137,17 @@
|
||||
},
|
||||
browser: {
|
||||
caption: "Browser validation consumes AMPG fixture manifests, chooses an adapter, then verifies each route through the intended transport profile.",
|
||||
mobile: {
|
||||
manifest: [0.12, 0.48],
|
||||
ampb: [0.3, 0.48],
|
||||
policy: [0.45, 0.25],
|
||||
adapters: [0.48, 0.57],
|
||||
existing: [0.66, 0.34],
|
||||
managed: [0.66, 0.7],
|
||||
context: [0.81, 0.5],
|
||||
result: [0.92, 0.5],
|
||||
visitor: [0.91, 0.74]
|
||||
},
|
||||
nodes: [
|
||||
["manifest", "fixture\nmanifest", 0.12, 0.43, "amber"],
|
||||
["ampb", "AMPB", 0.29, 0.43, "teal"],
|
||||
@@ -134,6 +180,17 @@
|
||||
clearnet: {
|
||||
motif: "clearnet",
|
||||
caption: "Clearnet splits into a DNS discovery path and an HTTPS request path before the web server reads AMPG output.",
|
||||
mobile: {
|
||||
client: [0.13, 0.54],
|
||||
resolver: [0.28, 0.34],
|
||||
auth: [0.47, 0.25],
|
||||
ip: [0.49, 0.46],
|
||||
tls: [0.32, 0.74],
|
||||
ingress: [0.55, 0.7],
|
||||
proxy: [0.7, 0.52],
|
||||
output: [0.84, 0.65],
|
||||
health: [0.82, 0.32]
|
||||
},
|
||||
nodes: [
|
||||
["client", "visitor\nbrowser", 0.11, 0.48, "green"],
|
||||
["resolver", "recursive\nDNS", 0.29, 0.25, "amber"],
|
||||
@@ -161,6 +218,19 @@
|
||||
tor: {
|
||||
motif: "onion",
|
||||
caption: "Tor onion traffic builds client and service circuits through relays; the rendezvous point joins them without revealing the origin.",
|
||||
mobile: {
|
||||
browser: [0.1, 0.52],
|
||||
hsdir: [0.28, 0.24],
|
||||
descriptor: [0.47, 0.21],
|
||||
guard: [0.28, 0.5],
|
||||
middle: [0.45, 0.66],
|
||||
rendezvous: [0.61, 0.5],
|
||||
intro: [0.68, 0.28],
|
||||
service: [0.78, 0.52],
|
||||
local: [0.88, 0.36],
|
||||
output: [0.88, 0.7],
|
||||
health: [0.62, 0.78]
|
||||
},
|
||||
nodes: [
|
||||
["browser", "Tor\nBrowser", 0.09, 0.5, "green"],
|
||||
["hsdir", "HSDir\nrelays", 0.28, 0.2, "amber"],
|
||||
@@ -193,6 +263,19 @@
|
||||
i2p: {
|
||||
motif: "garlic",
|
||||
caption: "I2P uses netDb LeaseSets and one-way tunnels; client outbound tunnels meet server inbound tunnels inside the I2P network.",
|
||||
mobile: {
|
||||
browser: [0.1, 0.52],
|
||||
address: [0.25, 0.25],
|
||||
floodfill: [0.46, 0.23],
|
||||
leaseset: [0.64, 0.25],
|
||||
outbound: [0.28, 0.62],
|
||||
routers: [0.5, 0.7],
|
||||
inbound: [0.7, 0.62],
|
||||
server: [0.84, 0.42],
|
||||
garlic: [0.5, 0.45],
|
||||
output: [0.88, 0.7],
|
||||
health: [0.72, 0.82]
|
||||
},
|
||||
nodes: [
|
||||
["browser", "I2P\nbrowser", 0.09, 0.52, "green"],
|
||||
["address", "b32 /\naddressbook", 0.25, 0.26, "amber"],
|
||||
@@ -225,6 +308,17 @@
|
||||
gemini: {
|
||||
motif: "gemini",
|
||||
caption: "Gemini is intentionally simple: resolve the capsule, open TLS on 1965, and serve text-first AMPG Gemtext.",
|
||||
mobile: {
|
||||
client: [0.12, 0.54],
|
||||
name: [0.28, 0.3],
|
||||
cert: [0.5, 0.24],
|
||||
tcp: [0.42, 0.52],
|
||||
daemon: [0.62, 0.52],
|
||||
gemtext: [0.78, 0.31],
|
||||
output: [0.86, 0.58],
|
||||
links: [0.62, 0.76],
|
||||
health: [0.84, 0.8]
|
||||
},
|
||||
nodes: [
|
||||
["client", "Gemini\nclient", 0.12, 0.5, "green"],
|
||||
["name", "capsule\nname", 0.28, 0.24, "amber"],
|
||||
@@ -253,6 +347,17 @@
|
||||
reticulum: {
|
||||
motif: "reticulum",
|
||||
caption: "Reticulum routes to destination identities across known paths and peers; it is transport-flexible, not automatically anonymous.",
|
||||
mobile: {
|
||||
client: [0.11, 0.52],
|
||||
cache: [0.28, 0.27],
|
||||
request: [0.28, 0.66],
|
||||
mesh: [0.49, 0.46],
|
||||
transport: [0.62, 0.24],
|
||||
identity: [0.72, 0.46],
|
||||
nomad: [0.84, 0.34],
|
||||
output: [0.88, 0.64],
|
||||
health: [0.72, 0.8]
|
||||
},
|
||||
nodes: [
|
||||
["client", "RNS\nclient", 0.1, 0.5, "green"],
|
||||
["cache", "path\ncache", 0.28, 0.24, "amber"],
|
||||
@@ -282,6 +387,18 @@
|
||||
ipfs: {
|
||||
motif: "ipfs",
|
||||
caption: "IPFS-style publishing addresses AMPG output by content hash, then discovers providers and fetches blocks from peers or gateways.",
|
||||
mobile: {
|
||||
browser: [0.1, 0.54],
|
||||
name: [0.28, 0.27],
|
||||
dnslink: [0.27, 0.68],
|
||||
dht: [0.49, 0.46],
|
||||
routing: [0.63, 0.25],
|
||||
bitswap: [0.66, 0.62],
|
||||
peers: [0.8, 0.43],
|
||||
blocks: [0.89, 0.25],
|
||||
output: [0.9, 0.66],
|
||||
health: [0.72, 0.8]
|
||||
},
|
||||
nodes: [
|
||||
["browser", "browser\nor gateway", 0.1, 0.5, "green"],
|
||||
["name", "CID /\nIPNS", 0.28, 0.24, "amber"],
|
||||
@@ -495,7 +612,7 @@
|
||||
: ay + (by - ay) * progress;
|
||||
ctx.fillStyle = index % 2 === 0 ? palette.teal : palette.amber;
|
||||
ctx.beginPath();
|
||||
ctx.arc(px, py, options.packetRadius || 3.5, 0, Math.PI * 2);
|
||||
ctx.arc(px, py, responsivePacketRadius(options.packetRadius || 3.5), 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
}
|
||||
@@ -507,13 +624,14 @@
|
||||
const y = position.y;
|
||||
const lines = String(label).split("\n");
|
||||
const boxWidth = responsiveNodeWidth(options.nodeWidth || 116);
|
||||
const lineHeight = options.lineHeight || 15;
|
||||
const boxHeight = Math.max(options.nodeHeight || 46, lines.length * lineHeight + 22);
|
||||
const fontSize = responsiveFontSize(options.fontSize || 13);
|
||||
const lineHeight = responsiveLineHeight(options.lineHeight || 15);
|
||||
const boxHeight = Math.max(responsiveNodeHeight(options.nodeHeight || 46), lines.length * lineHeight + 18);
|
||||
const pulse = Math.sin(tick * 2.2 + index) * 2;
|
||||
const color = palette[colorKey] || palette.teal;
|
||||
ctx.save();
|
||||
ctx.shadowColor = color;
|
||||
ctx.shadowBlur = options.shadowBlur || 20;
|
||||
ctx.shadowBlur = responsiveShadowBlur(options.shadowBlur || 20);
|
||||
ctx.fillStyle = "rgba(16, 16, 15, 0.86)";
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineWidth = 2;
|
||||
@@ -523,7 +641,7 @@
|
||||
ctx.stroke();
|
||||
ctx.shadowBlur = 0;
|
||||
ctx.fillStyle = palette.text;
|
||||
ctx.font = `${options.fontWeight || 700} ${options.fontSize || 13}px system-ui, sans-serif`;
|
||||
ctx.font = `${options.fontWeight || 700} ${fontSize}px system-ui, sans-serif`;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
const firstLineY = y - ((lines.length - 1) * lineHeight) / 2;
|
||||
@@ -534,24 +652,55 @@
|
||||
}
|
||||
|
||||
function responsiveNodeWidth(baseWidth) {
|
||||
if (width < 520) return Math.max(104, Math.min(baseWidth, width * 0.38));
|
||||
if (width < 720) return Math.max(104, Math.min(baseWidth, width * 0.28));
|
||||
if (width < 520) return Math.max(70, Math.min(baseWidth, width * 0.215));
|
||||
if (width < 720) return Math.max(92, Math.min(baseWidth, width * 0.18));
|
||||
if (width < 980) return Math.max(112, Math.min(baseWidth, width * 0.18));
|
||||
return baseWidth;
|
||||
}
|
||||
|
||||
function responsiveNodeHeight(baseHeight) {
|
||||
if (width < 520) return Math.min(baseHeight, 42);
|
||||
if (width < 720) return Math.min(baseHeight, 48);
|
||||
return baseHeight;
|
||||
}
|
||||
|
||||
function responsiveFontSize(baseSize) {
|
||||
if (width < 520) return Math.min(baseSize, 11.5);
|
||||
if (width < 720) return Math.min(baseSize, 12.5);
|
||||
return baseSize;
|
||||
}
|
||||
|
||||
function responsiveLineHeight(baseLineHeight) {
|
||||
if (width < 520) return Math.min(baseLineHeight, 12);
|
||||
if (width < 720) return Math.min(baseLineHeight, 13);
|
||||
return baseLineHeight;
|
||||
}
|
||||
|
||||
function responsiveShadowBlur(baseBlur) {
|
||||
if (width < 520) return Math.min(baseBlur, 14);
|
||||
if (width < 720) return Math.min(baseBlur, 18);
|
||||
return baseBlur;
|
||||
}
|
||||
|
||||
function responsivePacketRadius(baseRadius) {
|
||||
if (width < 520) return Math.min(baseRadius, 3.2);
|
||||
if (width < 720) return Math.min(baseRadius, 3.8);
|
||||
return baseRadius;
|
||||
}
|
||||
|
||||
function nodePosition(node) {
|
||||
if (!options.wrapNodes || width >= 760) {
|
||||
return { x: node[2] * width, y: node[3] * height };
|
||||
}
|
||||
const topology = graphSet[active];
|
||||
const index = topology.nodes.findIndex((candidate) => candidate[0] === node[0]);
|
||||
const columns = width < 520 ? 2 : 3;
|
||||
const rows = Math.max(1, Math.ceil(topology.nodes.length / columns));
|
||||
const col = index % columns;
|
||||
const row = Math.floor(index / columns);
|
||||
const x = (col + 0.5) / columns;
|
||||
const y = rows === 1 ? 0.34 : 0.15 + (row / (rows - 1)) * 0.48;
|
||||
const mobilePosition = topology.mobile && topology.mobile[node[0]];
|
||||
if (mobilePosition) {
|
||||
const x = Math.min(0.88, Math.max(0.12, mobilePosition[0]));
|
||||
const y = Math.min(0.84, Math.max(0.26, mobilePosition[1]));
|
||||
return { x: x * width, y: y * height };
|
||||
}
|
||||
const x = 0.12 + node[2] * 0.76;
|
||||
const y = 0.1 + node[3] * 0.68;
|
||||
return { x: x * width, y: y * height };
|
||||
}
|
||||
|
||||
|
||||
@@ -596,6 +596,18 @@ h3 {
|
||||
padding: 14px 18px;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 48px 0;
|
||||
}
|
||||
|
||||
.section-heading {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.map-stage {
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: clamp(2.75rem, 14vw, 3.45rem);
|
||||
}
|
||||
@@ -616,23 +628,45 @@ h3 {
|
||||
}
|
||||
|
||||
.map-theater {
|
||||
min-height: 820px;
|
||||
min-height: 0;
|
||||
padding-top: 420px;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
#cleanTopologyCanvas,
|
||||
#protocolTopologyCanvas,
|
||||
.map-canvas {
|
||||
bottom: auto;
|
||||
height: 420px;
|
||||
}
|
||||
|
||||
.map-theater::after {
|
||||
bottom: auto;
|
||||
height: 420px;
|
||||
}
|
||||
|
||||
.map-tabs {
|
||||
left: 12px;
|
||||
right: 12px;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.map-theater-controls {
|
||||
left: 12px;
|
||||
right: 12px;
|
||||
bottom: 12px;
|
||||
position: relative;
|
||||
left: auto;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
margin: 12px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.map-control-panel .segmented,
|
||||
.protocol-segmented {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.map-control-panel .topology-caption {
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.flow-list li {
|
||||
|
||||
Reference in New Issue
Block a user