11let wasmReady = false ;
22let nodeRunning = false ;
3+ let ircConnected = false ;
34
45const statusEl = document . getElementById ( 'runtimeStatus' ) ;
56const responseEl = document . getElementById ( 'response' ) ;
67
8+ function randomIRCName ( prefix ) {
9+ const bytes = new Uint8Array ( 4 ) ;
10+ crypto . getRandomValues ( bytes ) ;
11+ const suffix = Array . from ( bytes , ( byte ) => byte . toString ( 16 ) . padStart ( 2 , '0' ) ) . join ( '' ) ;
12+ return `${ prefix } ${ suffix } ` ;
13+ }
14+
15+ function setRandomIRCIdentity ( ) {
16+ const nick = randomIRCName ( 'ygg' ) ;
17+ document . getElementById ( 'ircNick' ) . value = nick ;
18+ document . getElementById ( 'ircUsername' ) . value = randomIRCName ( 'web' ) ;
19+ }
20+
721function appendLog ( line ) {
822 const logs = document . getElementById ( 'logs' ) ;
923 if ( ! logs ) {
@@ -18,6 +32,28 @@ function appendLog(line) {
1832
1933window . yggDemoAppendLog = appendLog ;
2034
35+ function appendIRC ( kind , at , line ) {
36+ const chat = document . getElementById ( 'ircMessages' ) ;
37+ if ( ! chat ) {
38+ return ;
39+ }
40+ const atBottom = chat . scrollTop + chat . clientHeight >= chat . scrollHeight - 8 ;
41+ const row = document . createElement ( 'div' ) ;
42+ row . className = `irc-line irc-${ kind || 'in' } ` ;
43+ const time = document . createElement ( 'span' ) ;
44+ time . className = 'irc-time' ;
45+ time . textContent = at || '' ;
46+ const text = document . createElement ( 'span' ) ;
47+ text . textContent = line || '' ;
48+ row . append ( time , text ) ;
49+ chat . append ( row ) ;
50+ if ( atBottom ) {
51+ chat . scrollTop = chat . scrollHeight ;
52+ }
53+ }
54+
55+ window . yggDemoAppendIRC = appendIRC ;
56+
2157function setStatus ( kind , text ) {
2258 statusEl . className = `status ${ kind } ` ;
2359 statusEl . textContent = text ;
@@ -28,6 +64,9 @@ function syncButtons() {
2864 document . getElementById ( 'stopNode' ) . disabled = ! wasmReady || ! nodeRunning ;
2965 document . getElementById ( 'refreshState' ) . disabled = ! wasmReady || ! nodeRunning ;
3066 document . getElementById ( 'runRequest' ) . disabled = ! wasmReady || ! nodeRunning ;
67+ document . getElementById ( 'ircConnect' ) . disabled = ! wasmReady || ! nodeRunning ;
68+ document . getElementById ( 'ircDisconnect' ) . disabled = ! wasmReady || ! nodeRunning || ! ircConnected ;
69+ document . getElementById ( 'ircSend' ) . disabled = ! wasmReady || ! nodeRunning || ! ircConnected ;
3170}
3271
3372function startConfig ( ) {
@@ -48,6 +87,26 @@ function requestConfig() {
4887 } ;
4988}
5089
90+ function ircConnectConfig ( ) {
91+ return {
92+ server : document . getElementById ( 'ircServer' ) . value . trim ( ) ,
93+ nick : document . getElementById ( 'ircNick' ) . value . trim ( ) ,
94+ username : document . getElementById ( 'ircUsername' ) . value . trim ( ) ,
95+ realname : document . getElementById ( 'ircRealname' ) . value . trim ( ) ,
96+ channel : document . getElementById ( 'ircChannel' ) . value . trim ( ) ,
97+ nickServMode : document . getElementById ( 'nickServMode' ) . value ,
98+ nickServPassword : document . getElementById ( 'nickServPassword' ) . value ,
99+ nickServEmail : document . getElementById ( 'nickServEmail' ) . value . trim ( ) ,
100+ } ;
101+ }
102+
103+ function ircSendConfig ( ) {
104+ return {
105+ target : document . getElementById ( 'ircTarget' ) . value . trim ( ) ,
106+ text : document . getElementById ( 'ircText' ) . value ,
107+ } ;
108+ }
109+
51110function renderState ( state ) {
52111 document . getElementById ( 'address' ) . textContent = state . address || '-' ;
53112 document . getElementById ( 'subnet' ) . textContent = state . subnet || '-' ;
@@ -109,6 +168,7 @@ async function stopNode() {
109168 await yggDemoStop ( ) ;
110169 } finally {
111170 nodeRunning = false ;
171+ ircConnected = false ;
112172 renderState ( { peers : [ ] } ) ;
113173 document . getElementById ( 'address' ) . textContent = '-' ;
114174 document . getElementById ( 'subnet' ) . textContent = '-' ;
@@ -149,9 +209,66 @@ async function runRequest() {
149209 }
150210}
151211
212+ async function connectIRC ( ) {
213+ setStatus ( 'loading' , 'Connecting IRC' ) ;
214+ syncButtons ( ) ;
215+ try {
216+ await yggDemoIRCConnect ( JSON . stringify ( ircConnectConfig ( ) ) ) ;
217+ ircConnected = true ;
218+ setStatus ( 'success' , 'IRC connected' ) ;
219+ await refreshState ( ) ;
220+ } catch ( error ) {
221+ ircConnected = false ;
222+ appendIRC ( 'error' , new Date ( ) . toLocaleTimeString ( ) , `Error: ${ error . message || error } ` ) ;
223+ setStatus ( 'error' , `IRC failed: ${ error . message || error } ` ) ;
224+ }
225+ syncButtons ( ) ;
226+ }
227+
228+ async function disconnectIRC ( ) {
229+ try {
230+ await yggDemoIRCDisconnect ( ) ;
231+ } finally {
232+ ircConnected = false ;
233+ setStatus ( 'ready' , nodeRunning ? 'Node running' : 'Stopped' ) ;
234+ syncButtons ( ) ;
235+ }
236+ }
237+
238+ async function sendIRC ( ) {
239+ const text = document . getElementById ( 'ircText' ) ;
240+ try {
241+ await yggDemoIRCSend ( JSON . stringify ( ircSendConfig ( ) ) ) ;
242+ text . value = '' ;
243+ } catch ( error ) {
244+ appendIRC ( 'error' , new Date ( ) . toLocaleTimeString ( ) , `Error: ${ error . message || error } ` ) ;
245+ setStatus ( 'error' , `IRC send failed: ${ error . message || error } ` ) ;
246+ }
247+ }
248+
249+ function syncNickServFields ( ) {
250+ const mode = document . getElementById ( 'nickServMode' ) . value ;
251+ document . getElementById ( 'nickServPassword' ) . disabled = mode === 'none' ;
252+ document . getElementById ( 'nickServEmailLabel' ) . classList . toggle ( 'hidden' , mode !== 'register' ) ;
253+ }
254+
255+ setRandomIRCIdentity ( ) ;
256+ syncNickServFields ( ) ;
152257document . getElementById ( 'startNode' ) . addEventListener ( 'click' , startNode ) ;
153258document . getElementById ( 'stopNode' ) . addEventListener ( 'click' , stopNode ) ;
154259document . getElementById ( 'refreshState' ) . addEventListener ( 'click' , refreshState ) ;
155260document . getElementById ( 'runRequest' ) . addEventListener ( 'click' , runRequest ) ;
261+ document . getElementById ( 'ircConnect' ) . addEventListener ( 'click' , connectIRC ) ;
262+ document . getElementById ( 'ircDisconnect' ) . addEventListener ( 'click' , disconnectIRC ) ;
263+ document . getElementById ( 'ircSend' ) . addEventListener ( 'click' , sendIRC ) ;
264+ document . getElementById ( 'nickServMode' ) . addEventListener ( 'change' , syncNickServFields ) ;
265+ document . getElementById ( 'ircText' ) . addEventListener ( 'keydown' , ( event ) => {
266+ if ( event . key === 'Enter' && ! event . shiftKey ) {
267+ event . preventDefault ( ) ;
268+ if ( ! document . getElementById ( 'ircSend' ) . disabled ) {
269+ sendIRC ( ) ;
270+ }
271+ }
272+ } ) ;
156273syncButtons ( ) ;
157274loadWasm ( ) ;
0 commit comments