@@ -9,7 +9,7 @@ class BridgeAdapter {
99 this . channels = [ ] ;
1010 this . users = [ ] ;
1111 this . currentChannel = { name : "/" , path : "/" } ;
12- this . asyncMessages = [ ] ;
12+ this . asyncMessages = [ ] ;
1313
1414 // Credentials from HTML config
1515 this . username = window . _ttUsername || "WebClient" ;
@@ -117,7 +117,7 @@ this.asyncMessages = [];
117117 username : this . username
118118 } ) ) ;
119119
120- // TeamTalk login request (now with nickname)
120+ // TeamTalk login request
121121 this . ws . send ( JSON . stringify ( {
122122 type : "tt-connect" ,
123123 host : window . _ttHost || "localhost" ,
@@ -198,7 +198,6 @@ this.asyncMessages = [];
198198 if ( ! data || ! data . type ) return ;
199199
200200 switch ( data . type ) {
201-
202201 case "presence-join" :
203202 if ( this . joinTone ) this . joinTone . play ( ) ;
204203 this . vibrate ( [ 40 , 40 , 40 ] ) ;
@@ -224,17 +223,17 @@ this.asyncMessages = [];
224223 this . handleTTStatus ( data ) ;
225224 break ;
226225
227- case "tt-channel-list" :
228- case "tt-channel-list-full" : // keep legacy support
229- this . channels = data . channels || [ ] ;
230- this . emit ( "channel-added" ) ;
231- break ;
226+ case "tt-channel-list" :
227+ case "tt-channel-list-full" :
228+ this . channels = data . channels || [ ] ;
229+ this . emit ( "channel-added" ) ;
230+ break ;
232231
233- case "tt-user-list" :
234- case "tt-user-list-full" : // keep legacy support
235- this . users = data . users || [ ] ;
236- this . emit ( "user-connected" ) ;
237- break ;
232+ case "tt-user-list" :
233+ case "tt-user-list-full" :
234+ this . users = data . users || [ ] ;
235+ this . emit ( "user-connected" ) ;
236+ break ;
238237
239238 case "tt-current-channel" :
240239 this . currentChannel = {
@@ -244,54 +243,63 @@ case "tt-user-list-full": // keep legacy support
244243 this . emit ( "channel-changed" ) ;
245244 break ;
246245
247- case "cw-async" :
248- // Store async message (optional but recommended)
249- if ( ! this . asyncMessages ) this . asyncMessages = [ ] ;
250- this . asyncMessages . push ( data ) ;
246+ case "cw-async" :
247+ if ( ! this . asyncMessages ) this . asyncMessages = [ ] ;
248+ this . asyncMessages . push ( data ) ;
249+ this . emit ( "async-message" , data ) ;
250+ break ;
251+
252+ case "tt-chat" :
253+ this . emit ( "chat-message" , {
254+ type : "live_text" ,
255+ text : data . text || "" ,
256+ user : data . user || data . nickname || "Someone" ,
257+ timestamp : data . timestamp || Date . now ( )
258+ } ) ;
259+ break ;
251260
252- // Notify UI
253- this . emit ( "async-message" , data ) ;
254- break ;
255-
256261 default :
257262 this . emit ( "message" , data ) ;
258263 break ;
259264 }
260265 }
261266
262- handleTTStatus ( data ) {
263- switch ( data . phase ) {
264-
265- case "received " :
266- case "login-sent " :
267- case "server-message " :
268- case "connecting " :
269- case "authenticating" :
270- break ;
271-
272- case "connected" :
273- this . ttStatus . textContent = "TeamTalk: 🟢 Connected" ;
274- if ( this . ttConnectTone ) this . ttConnectTone . play ( ) ;
275- this . vibrate ( [ 80 , 40 , 80 ] ) ;
276- updateReadyStatus ( true ) ;
277- this . emit ( "tt-connected" ) ;
278- break ;
279-
280- case "failed" :
281- this . ttStatus . textContent = "TeamTalk: 🔴 Failed" ;
282- this . showError ( "TeamTalk connection failed." ) ;
283- updateReadyStatus ( false ) ;
284- break ;
285-
286- case "disconnected" :
287- this . ttStatus . textContent = "TeamTalk: 🔴 Disconnected" ;
288- if ( this . ttDisconnectTone ) this . ttDisconnectTone . play ( ) ;
289- this . vibrate ( [ 120 ] ) ;
290- updateReadyStatus ( false ) ;
291- break ;
267+ handleTTStatus ( data ) {
268+ switch ( data . phase ) {
269+ case "received" :
270+ case "login-sent " :
271+ case "server-message " :
272+ case "connecting " :
273+ case "authenticating " :
274+ break ;
275+
276+ case "connected" :
277+ this . ttStatus . textContent = "TeamTalk: 🟢 Connected" ;
278+ if ( this . ttConnectTone ) this . ttConnectTone . play ( ) ;
279+ this . vibrate ( [ 80 , 40 , 80 ] ) ;
280+ updateReadyStatus ( true ) ;
281+ this . emit ( "tt-connected" ) ;
282+ break ;
283+
284+ case "failed" :
285+ this . ttStatus . textContent = "TeamTalk: 🔴 Failed" ;
286+ this . showError ( "TeamTalk connection failed." ) ;
287+ updateReadyStatus ( false ) ;
288+ break ;
289+
290+ case "disconnected" :
291+ this . ttStatus . textContent = "TeamTalk: 🔴 Disconnected" ;
292+ if ( this . ttDisconnectTone ) this . ttDisconnectTone . play ( ) ;
293+ this . vibrate ( [ 120 ] ) ;
294+ updateReadyStatus ( false ) ;
295+ break ;
296+ }
292297 }
293- }
294- async getChannels ( ) {
298+
299+ /* -------------------------------------------------------
300+ TeamTalk + async primitives
301+ ------------------------------------------------------- */
302+ async getChannels ( ) {
295303 return this . channels ;
296304 }
297305
@@ -303,9 +311,10 @@ async getChannels() {
303311 return this . currentChannel ;
304312 }
305313
306- async getAsyncMessages ( ) {
307- return this . asyncMessages ;
308- }
314+ async getAsyncMessages ( ) {
315+ return this . asyncMessages ;
316+ }
317+
309318 joinChannel ( id ) {
310319 const ch = this . channels . find ( c => c . id === id ) ;
311320 const path = ch ? ch . path : "/" ;
@@ -323,22 +332,83 @@ async getAsyncMessages() {
323332 } ) ) ;
324333 }
325334
326- sendAsync ( text ) {
327- this . ws . send ( JSON . stringify ( {
328- type : "cw-async" ,
329- text,
330- timestamp : Date . now ( )
331- } ) ) ;
332- }
335+ sendAsync ( text ) {
336+ this . ws . send ( JSON . stringify ( {
337+ type : "cw-async" ,
338+ text,
339+ timestamp : Date . now ( )
340+ } ) ) ;
341+ }
333342
334- sendMessage ( text , mode = "live" ) {
335- if ( mode === "async" ) {
336- this . sendAsync ( text ) ;
337- } else {
338- this . sendChat ( text ) ;
343+ // Explicit override: caller chooses async vs live
344+ sendMessage ( text , mode = "live" ) {
345+ if ( mode === "async" ) {
346+ this . sendAsync ( text ) ;
347+ } else {
348+ this . sendChat ( text ) ;
349+ }
339350 }
340- }
341- /* -------------------------------------------------------
351+
352+ /* -------------------------------------------------------
353+ Automation: system decides async vs live
354+ ------------------------------------------------------- */
355+ isLiveContext ( ) {
356+ const ttConnected =
357+ this . ttStatus && this . ttStatus . textContent . includes ( "🟢" ) ;
358+ const othersPresent = ( this . users || [ ] ) . length > 0 ;
359+ return ttConnected && othersPresent ;
360+ }
361+
362+ autoSend ( text ) {
363+ const mode = this . isLiveContext ( ) ? "live" : "async" ;
364+ this . sendMessage ( text , mode ) ;
365+ return mode ;
366+ }
367+
368+ /* -------------------------------------------------------
369+ AAC: symbols + dwell (AAC‑side only)
370+ ------------------------------------------------------- */
371+ sendSymbolTap ( symbolId , label , source = "tap" ) {
372+ const event = {
373+ type : "symbol_tap" ,
374+ symbolId,
375+ label,
376+ source,
377+ timestamp : Date . now ( )
378+ } ;
379+ this . emit ( "symbol-tap" , event ) ;
380+
381+ const text = label || symbolId ;
382+ const mode = this . autoSend ( text ) ;
383+ this . emit ( "symbol-tap-sent" , { ...event , mode } ) ;
384+ }
385+
386+ sendDwellSymbol ( symbolId , label ) {
387+ this . sendSymbolTap ( symbolId , label , "dwell" ) ;
388+ }
389+
390+ /* -------------------------------------------------------
391+ Live audio → TeamTalk
392+ ------------------------------------------------------- */
393+ startLiveAudioSession ( ) {
394+ if ( ! this . ws || this . ws . readyState !== WebSocket . OPEN ) return ;
395+ this . ws . send ( JSON . stringify ( { type : "cw-live-audio-start" } ) ) ;
396+ }
397+
398+ stopLiveAudioSession ( ) {
399+ if ( ! this . ws || this . ws . readyState !== WebSocket . OPEN ) return ;
400+ this . ws . send ( JSON . stringify ( { type : "cw-live-audio-stop" } ) ) ;
401+ }
402+
403+ sendLiveAudioChunk ( base64Data ) {
404+ if ( ! this . ws || this . ws . readyState !== WebSocket . OPEN ) return ;
405+ this . ws . send ( JSON . stringify ( {
406+ type : "cw-live-audio-chunk" ,
407+ data : base64Data
408+ } ) ) ;
409+ }
410+
411+ /* -------------------------------------------------------
342412 AAC UI wrappers
343413 ------------------------------------------------------- */
344414 async connectEverything ( ) {
@@ -358,7 +428,4 @@ sendMessage(text, mode = "live") {
358428 }
359429}
360430
361- /* ---------------------------------------------------------
362- Export instance
363- --------------------------------------------------------- */
364431const bridge = new BridgeAdapter ( ) ;
0 commit comments