@@ -4,13 +4,20 @@ const totalUniqueEl = document.getElementById("total-unique");
44const canvas = document . getElementById ( "network" ) ;
55const ctx = canvas . getContext ( "2d" ) ;
66let particles = [ ] ;
7+ let particleColor = "#4ade80" ;
8+ let particleLinkColor = "#22d3ee" ;
79
810function getThemeColor ( varName ) {
911 return getComputedStyle ( document . documentElement )
1012 . getPropertyValue ( varName )
1113 . trim ( ) ;
1214}
1315
16+ const refreshThemeColors = ( ) => {
17+ particleColor = getThemeColor ( "--color-particle" ) ;
18+ particleLinkColor = getThemeColor ( "--color-particle-link" ) ;
19+ } ;
20+
1421function resize ( ) {
1522 canvas . width = window . innerWidth ;
1623 canvas . height = window . innerHeight ;
@@ -39,7 +46,7 @@ class Particle {
3946 draw ( ) {
4047 ctx . beginPath ( ) ;
4148 ctx . arc ( this . x , this . y , this . size , 0 , Math . PI * 2 ) ;
42- ctx . fillStyle = getThemeColor ( "--color-particle" ) ;
49+ ctx . fillStyle = particleColor ;
4350 ctx . fill ( ) ;
4451 }
4552}
@@ -62,15 +69,15 @@ const updateParticles = (count) => {
6269const animate = ( ) => {
6370 ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
6471
65- ctx . strokeStyle = getThemeColor ( "--color-particle-link" ) ;
72+ ctx . strokeStyle = particleLinkColor ;
6673 ctx . lineWidth = 1 ;
6774 for ( let i = 0 ; i < particles . length ; i ++ ) {
6875 for ( let j = i + 1 ; j < particles . length ; j ++ ) {
6976 const dx = particles [ i ] . x - particles [ j ] . x ;
7077 const dy = particles [ i ] . y - particles [ j ] . y ;
71- const distance = Math . sqrt ( dx * dx + dy * dy ) ;
78+ const distanceSquared = dx * dx + dy * dy ;
7279
73- if ( distance < 150 ) {
80+ if ( distanceSquared < 22500 ) {
7481 ctx . beginPath ( ) ;
7582 ctx . moveTo ( particles [ i ] . x , particles [ i ] . y ) ;
7683 ctx . lineTo ( particles [ j ] . x , particles [ j ] . y ) ;
@@ -473,6 +480,17 @@ const getColorFromId = (id) => {
473480const seenMessageIds = new Set ( ) ;
474481const messageIdHistory = [ ] ;
475482
483+ const appendSystemLines = ( lines ) => {
484+ const entries = Array . isArray ( lines ) ? lines : [ lines ] ;
485+ for ( const line of entries ) {
486+ const div = document . createElement ( "div" ) ;
487+ div . className = "system-message" ;
488+ div . innerText = `[SYSTEM] ${ line } ` ;
489+ terminalOutput . appendChild ( div ) ;
490+ }
491+ terminalOutput . scrollTop = terminalOutput . scrollHeight ;
492+ } ;
493+
476494const appendMessage = ( msg ) => {
477495 const div = document . createElement ( "div" ) ;
478496
@@ -631,6 +649,39 @@ terminalInput.addEventListener("keypress", async (e) => {
631649 }
632650 }
633651 return ;
652+ } else if ( content === "/who" ) {
653+ try {
654+ const res = await fetch ( "/api/peers" ) ;
655+ if ( ! res . ok ) {
656+ systemStatusBar . innerText = "[SYSTEM] Failed to fetch peer list" ;
657+ return ;
658+ }
659+
660+ const data = await res . json ( ) ;
661+ const peers = Array . isArray ( data . peers ) ? data . peers : [ ] ;
662+ const mappedPeers = peers . map ( ( peer ) => {
663+ if ( peer . id && peer . screenname ) {
664+ nameToId . set ( peer . screenname , peer . id ) ;
665+ }
666+ const shortId = peer . id ? peer . id . slice ( - 8 ) : "unknown" ;
667+ return `${ peer . screenname || "Unknown" } (...${ shortId } )` ;
668+ } ) ;
669+
670+ const visiblePeers = mappedPeers . slice ( 0 , 20 ) ;
671+ const outputLines = [
672+ `Active users: ${ mappedPeers . length } ` ,
673+ ...visiblePeers ,
674+ ] ;
675+ if ( mappedPeers . length > visiblePeers . length ) {
676+ outputLines . push ( `...and ${ mappedPeers . length - visiblePeers . length } more` ) ;
677+ }
678+
679+ appendSystemLines ( outputLines ) ;
680+ systemStatusBar . innerText = `[SYSTEM] Listed ${ mappedPeers . length } active users` ;
681+ } catch ( err ) {
682+ systemStatusBar . innerText = "[SYSTEM] Failed to fetch peer list" ;
683+ }
684+ return ;
634685 } else if ( content . startsWith ( "/whisper " ) ) {
635686 const parts = content . split ( " " ) ;
636687 if ( parts . length < 3 ) {
@@ -840,6 +891,7 @@ const initialCount = parseInt(countEl.dataset.initialCount) || 0;
840891countEl . innerText = initialCount ;
841892countEl . classList . add ( "loaded" ) ;
842893updateParticles ( initialCount ) ;
894+ refreshThemeColors ( ) ;
843895animate ( ) ;
844896
845897const bandwidthHistory = { timestamps : [ ] , bytesIn : [ ] , bytesOut : [ ] } ;
@@ -1040,6 +1092,7 @@ function cycleTheme() {
10401092 if ( oldLink ) oldLink . remove ( ) ;
10411093 newLink . id = "theme-css" ;
10421094 localStorage . setItem ( "hypermind-theme" , newTheme ) ;
1095+ refreshThemeColors ( ) ;
10431096 btn . disabled = false ;
10441097 btn . style . opacity = "" ;
10451098 showThemeNotification ( newTheme ) ;
0 commit comments