@@ -2,17 +2,20 @@ import {
22 AfterViewInit ,
33 Component ,
44 ElementRef ,
5+ inject ,
56 OnDestroy ,
67 ViewChild ,
78} from '@angular/core' ;
89import { FitAddon } from '@xterm/addon-fit' ;
910import { IDisposable , Terminal } from '@xterm/xterm' ;
11+ import { Subscription } from 'rxjs' ;
12+
13+ import { MudService } from '../../services/mud.service' ;
1014
1115/**
12- * Lightweight xterm wrapper that is decoupled from the backend and is optimized
13- * for screen-reader experiments. It renders a static intro text and mirrors any
14- * user input back to the terminal, including a delayed echo so assistive tech can
15- * be tested without talking to the backend.
16+ * Lightweight xterm wrapper that streams directly to/from the backend for
17+ * screen-reader experiments. It forwards raw server output 1:1 to xterm and
18+ * ships user input to the server on CR, echoing the submitted line locally.
1619 */
1720@Component ( {
1821 selector : 'app-mud-screenreader-client' ,
@@ -23,6 +26,8 @@ import { IDisposable, Terminal } from '@xterm/xterm';
2326export class MudScreenreaderClientComponent
2427 implements AfterViewInit , OnDestroy
2528{
29+ private readonly mudService = inject ( MudService ) ;
30+
2631 private readonly terminal = new Terminal ( {
2732 fontFamily : 'JetBrainsMono, monospace' ,
2833 theme : { background : '#000' , foreground : '#ccc' } ,
@@ -33,9 +38,9 @@ export class MudScreenreaderClientComponent
3338 private readonly fitAddon = new FitAddon ( ) ;
3439 private readonly terminalDisposables : IDisposable [ ] = [ ] ;
3540 private readonly resizeObs = new ResizeObserver ( ( ) => this . handleResize ( ) ) ;
41+ private mudOutputSubscription ?: Subscription ;
3642
3743 private currentInput = '' ;
38- private readonly pendingEchoTimeouts : number [ ] = [ ] ;
3944
4045 @ViewChild ( 'hostRef' , { static : true } )
4146 private readonly terminalRef ! : ElementRef < HTMLDivElement > ;
@@ -46,25 +51,37 @@ export class MudScreenreaderClientComponent
4651 this . fitAddon . fit ( ) ;
4752 this . resizeObs . observe ( this . terminalRef . nativeElement ) ;
4853
49- this . renderStaticIntro ( ) ;
54+ this . mudOutputSubscription = this . mudService . mudOutput$ . subscribe (
55+ ( { data } ) => this . terminal . write ( data ) ,
56+ ) ;
57+
5058 this . terminal . focus ( ) ;
5159
5260 this . terminalDisposables . push (
5361 this . terminal . onData ( ( data ) => this . handleInput ( data ) ) ,
5462 ) ;
63+
64+ this . connectToBackend ( ) ;
5565 }
5666
5767 ngOnDestroy ( ) : void {
5868 this . resizeObs . disconnect ( ) ;
59- this . pendingEchoTimeouts . forEach ( ( timeoutId ) => clearTimeout ( timeoutId ) ) ;
60- this . pendingEchoTimeouts . length = 0 ;
6169
70+ this . mudOutputSubscription ?. unsubscribe ( ) ;
6271 this . terminalDisposables . forEach ( ( disposable ) => disposable . dispose ( ) ) ;
72+ this . mudService . disconnect ( ) ;
6373 this . terminal . dispose ( ) ;
6474 }
6575
6676 private handleResize ( ) : void {
6777 this . fitAddon . fit ( ) ;
78+
79+ const columns = this . terminal . cols ;
80+ const rows = this . terminal . rows ;
81+
82+ if ( Number . isFinite ( columns ) && Number . isFinite ( rows ) ) {
83+ this . mudService . updateViewportSize ( columns , rows ) ;
84+ }
6885 }
6986
7087 private handleInput ( data : string ) : void {
@@ -104,38 +121,25 @@ export class MudScreenreaderClientComponent
104121 }
105122
106123 private commitInput ( ) : void {
107- this . terminal . write ( '\r\n' ) ;
124+ // this.terminal.write('\r\n');
108125 const inputSnapshot = this . currentInput ;
109- this . terminal . writeln ( `Eingabe: ${ inputSnapshot } ` ) ;
110- this . scheduleEcho ( inputSnapshot ) ;
126+ // this.terminal.writeln(`Eingabe: ${inputSnapshot}`);
127+ if ( inputSnapshot . length > 0 ) {
128+ this . mudService . sendMessage ( inputSnapshot ) ;
129+ }
111130 this . currentInput = '' ;
112131 this . terminal . writeln ( '' ) ;
113132 }
114133
115- private renderStaticIntro ( ) : void {
116- this . terminal . writeln ( 'Willkommen zum barrierefreien Testlauf.' ) ;
117- this . terminal . writeln ( 'Die Verbindung zum Server ist deaktiviert.' ) ;
118- this . terminal . writeln ( '' ) ;
119- this . terminal . writeln (
120- 'Tippen Sie Ihre Eingabe und bestaetigen Sie mit Enter.' ,
121- ) ;
122- this . terminal . writeln ( '' ) ;
123- }
124-
125134 private isPrintable ( char : string ) : boolean {
126135 const code = char . charCodeAt ( 0 ) ;
127136 return code >= 0x20 && code !== 0x7f ;
128137 }
129138
130- private scheduleEcho ( message : string ) : void {
131- const timeoutId = window . setTimeout ( ( ) => {
132- this . terminal . writeln ( `Echo: ${ message } ` ) ;
133- const idx = this . pendingEchoTimeouts . indexOf ( timeoutId ) ;
134- if ( idx >= 0 ) {
135- this . pendingEchoTimeouts . splice ( idx , 1 ) ;
136- }
137- } , 5000 ) ;
139+ private connectToBackend ( ) : void {
140+ const columns = this . terminal . cols ;
141+ const rows = this . terminal . rows ;
138142
139- this . pendingEchoTimeouts . push ( timeoutId ) ;
143+ this . mudService . connect ( { columns , rows } ) ;
140144 }
141145}
0 commit comments