@@ -10,7 +10,7 @@ import { AsyncPipe } from '@angular/common';
1010import { AttachAddon } from '@xterm/addon-attach' ;
1111import { FitAddon } from '@xterm/addon-fit' ;
1212import { IDisposable , Terminal } from '@xterm/xterm' ;
13- import { Subscription } from 'rxjs' ;
13+ import { of , Subscription } from 'rxjs' ;
1414
1515import { MudService } from '../../services/mud.service' ;
1616import { SecureString } from '@mudlet3/frontend/shared' ;
@@ -48,23 +48,14 @@ const DELETE_SEQUENCE = `${CTRL.ESC}[3~`;
4848} )
4949export class MudClientComponent implements AfterViewInit , OnDestroy {
5050 private readonly mudService = inject ( MudService ) ;
51+ private readonly isStaticTerminalMode = true ;
5152
5253 private readonly terminal : Terminal ;
53- private readonly inputController : MudInputController ;
54- private readonly promptManager : MudPromptManager ;
54+ private readonly inputController ? : MudInputController ;
55+ private readonly promptManager ? : MudPromptManager ;
5556 private readonly terminalFitAddon = new FitAddon ( ) ;
56- private readonly socketAdapter = new MudSocketAdapter (
57- this . mudService . mudOutput$ ,
58- {
59- transformMessage : ( data ) => this . transformMudOutput ( data ) ,
60- beforeMessage : ( data ) => this . beforeMudOutput ( data ) ,
61- afterMessage : ( data ) => this . afterMudOutput ( data ) ,
62- } ,
63- ) ;
64- private readonly terminalAttachAddon = new AttachAddon (
65- this . socketAdapter as unknown as WebSocket ,
66- { bidirectional : false } ,
67- ) ;
57+ private readonly socketAdapter ?: MudSocketAdapter ;
58+ private readonly terminalAttachAddon ?: AttachAddon ;
6859
6960 private readonly terminalDisposables : IDisposable [ ] = [ ] ;
7061 private readonly resizeObs = new ResizeObserver ( ( ) => {
@@ -84,8 +75,12 @@ export class MudClientComponent implements AfterViewInit, OnDestroy {
8475 @ViewChild ( 'hostRef' , { static : true } )
8576 private readonly terminalRef ! : ElementRef < HTMLDivElement > ;
8677
87- protected readonly isConnected$ = this . mudService . connectedToMud$ ;
88- protected readonly showEcho$ = this . mudService . showEcho$ ;
78+ protected readonly isConnected$ = this . isStaticTerminalMode
79+ ? of ( true )
80+ : this . mudService . connectedToMud$ ;
81+ protected readonly showEcho$ = this . isStaticTerminalMode
82+ ? of ( true )
83+ : this . mudService . showEcho$ ;
8984
9085 /**
9186 * Instantiates the terminal plus helper controllers. All services (input/prompt)
@@ -95,20 +90,32 @@ export class MudClientComponent implements AfterViewInit, OnDestroy {
9590 this . terminal = new Terminal ( {
9691 fontFamily : 'JetBrainsMono, monospace' ,
9792 theme : { background : '#000' , foreground : '#ccc' } ,
98- disableStdin : false ,
93+ disableStdin : this . isStaticTerminalMode ,
9994 screenReaderMode : true ,
10095 } ) ;
10196
102- this . inputController = new MudInputController (
103- this . terminal ,
104- ( { message, echoed } ) => this . handleCommittedInput ( message , echoed ) ,
105- ) ;
106- this . inputController . setLocalEcho ( this . state . localEchoEnabled ) ;
107-
108- this . promptManager = new MudPromptManager (
109- this . terminal ,
110- this . inputController ,
111- ) ;
97+ if ( ! this . isStaticTerminalMode ) {
98+ this . socketAdapter = new MudSocketAdapter ( this . mudService . mudOutput$ , {
99+ transformMessage : ( data ) => this . transformMudOutput ( data ) ,
100+ beforeMessage : ( data ) => this . beforeMudOutput ( data ) ,
101+ afterMessage : ( data ) => this . afterMudOutput ( data ) ,
102+ } ) ;
103+ this . terminalAttachAddon = new AttachAddon (
104+ this . socketAdapter as unknown as WebSocket ,
105+ { bidirectional : false } ,
106+ ) ;
107+
108+ this . inputController = new MudInputController (
109+ this . terminal ,
110+ ( { message, echoed } ) => this . handleCommittedInput ( message , echoed ) ,
111+ ) ;
112+ this . inputController . setLocalEcho ( this . state . localEchoEnabled ) ;
113+
114+ this . promptManager = new MudPromptManager (
115+ this . terminal ,
116+ this . inputController ,
117+ ) ;
118+ }
112119 }
113120
114121 /**
@@ -118,7 +125,16 @@ export class MudClientComponent implements AfterViewInit, OnDestroy {
118125 ngAfterViewInit ( ) {
119126 this . terminal . open ( this . terminalRef . nativeElement ) ;
120127 this . terminal . loadAddon ( this . terminalFitAddon ) ;
121- this . terminal . loadAddon ( this . terminalAttachAddon ) ;
128+ this . terminalFitAddon . fit ( ) ;
129+ this . resizeObs . observe ( this . terminalRef . nativeElement ) ;
130+ this . setState ( { terminalReady : true } ) ;
131+
132+ if ( this . isStaticTerminalMode ) {
133+ this . renderStaticDemoText ( ) ;
134+ return ;
135+ }
136+
137+ this . terminal . loadAddon ( this . terminalAttachAddon ! ) ;
122138 this . terminal . focus ( ) ;
123139
124140 this . terminalDisposables . push (
@@ -133,9 +149,6 @@ export class MudClientComponent implements AfterViewInit, OnDestroy {
133149 this . setLinemode ( state ) ,
134150 ) ;
135151
136- this . resizeObs . observe ( this . terminalRef . nativeElement ) ;
137- this . setState ( { terminalReady : true } ) ;
138-
139152 const columns = this . terminal . cols ;
140153 const rows = this . terminal . rows + 1 ;
141154
@@ -152,12 +165,16 @@ export class MudClientComponent implements AfterViewInit, OnDestroy {
152165 this . showEchoSubscription ?. unsubscribe ( ) ;
153166 this . linemodeSubscription ?. unsubscribe ( ) ;
154167
155- this . terminalAttachAddon . dispose ( ) ;
156- this . socketAdapter . dispose ( ) ;
168+ this . terminalAttachAddon ? .dispose ( ) ;
169+ this . socketAdapter ? .dispose ( ) ;
157170 this . terminal . dispose ( ) ;
158171 }
159172
160173 protected connect ( ) {
174+ if ( this . isStaticTerminalMode ) {
175+ return ;
176+ }
177+
161178 const columns = this . terminal . cols ;
162179 const rows = this . terminal . rows ;
163180
@@ -170,6 +187,9 @@ export class MudClientComponent implements AfterViewInit, OnDestroy {
170187 */
171188 private handleTerminalResize ( ) {
172189 this . terminalFitAddon . fit ( ) ;
190+ if ( this . isStaticTerminalMode ) {
191+ return ;
192+ }
173193
174194 const columns = this . terminal . cols ;
175195 const rows = this . terminal . rows ;
@@ -199,6 +219,10 @@ export class MudClientComponent implements AfterViewInit, OnDestroy {
199219 * Sends a committed line (or secure string) to the server.
200220 */
201221 private handleCommittedInput ( message : string , echoed : boolean ) {
222+ if ( this . isStaticTerminalMode ) {
223+ return ;
224+ }
225+
202226 const payload : string | SecureString = echoed
203227 ? message
204228 : { value : message } ;
@@ -211,6 +235,10 @@ export class MudClientComponent implements AfterViewInit, OnDestroy {
211235 * or through the {@link MudInputController}.
212236 */
213237 private handleInput ( data : string ) {
238+ if ( ! this . inputController ) {
239+ return ;
240+ }
241+
214242 if ( ! this . state . isEditMode ) {
215243 if ( data . length > 0 ) {
216244 const rewritten = this . rewriteBackspaceToDelete ( data ) ;
@@ -232,20 +260,20 @@ export class MudClientComponent implements AfterViewInit, OnDestroy {
232260
233261 if ( ! state . edit ) {
234262 if ( wasEditMode ) {
235- const pending = this . inputController . flush ( ) ;
263+ const pending = this . inputController ? .flush ( ) ;
236264
237265 if ( pending ) {
238266 this . handleCommittedInput ( pending . message , pending . echoed ) ;
239267 }
240268 }
241269
242- this . inputController . reset ( ) ;
270+ this . inputController ? .reset ( ) ;
243271 } else if ( ! wasEditMode ) {
244- this . inputController . reset ( ) ;
272+ this . inputController ? .reset ( ) ;
245273 }
246274
247275 this . setState ( { isEditMode : state . edit } ) ;
248- this . promptManager . reset ( ) ;
276+ this . promptManager ? .reset ( ) ;
249277 this . updateLocalEcho ( this . state . showEcho ) ;
250278 }
251279
@@ -257,28 +285,28 @@ export class MudClientComponent implements AfterViewInit, OnDestroy {
257285 const localEchoEnabled = this . state . isEditMode && showEcho ;
258286
259287 this . setState ( { showEcho, localEchoEnabled } ) ;
260- this . inputController . setLocalEcho ( localEchoEnabled ) ;
288+ this . inputController ? .setLocalEcho ( localEchoEnabled ) ;
261289 }
262290
263291 /**
264292 * Delegates to the prompt manager so it can temporarily hide the local prompt.
265293 */
266294 private beforeMudOutput ( _data : string ) {
267- this . promptManager . beforeServerOutput ( this . getPromptContext ( ) ) ;
295+ this . promptManager ? .beforeServerOutput ( this . getPromptContext ( ) ) ;
268296 }
269297
270298 /**
271299 * Restores prompt and user input after the server chunk has been rendered.
272300 */
273301 private afterMudOutput ( data : string ) {
274- this . promptManager . afterServerOutput ( data , this . getPromptContext ( ) ) ;
302+ this . promptManager ? .afterServerOutput ( data , this . getPromptContext ( ) ) ;
275303 }
276304
277305 /**
278306 * Lets the prompt manager strip redundant CR/LF characters.
279307 */
280308 private transformMudOutput ( data : string ) : string {
281- return this . promptManager . transformOutput ( data ) ;
309+ return this . promptManager ? .transformOutput ( data ) ?? data ;
282310 }
283311
284312 /**
@@ -312,4 +340,20 @@ export class MudClientComponent implements AfterViewInit, OnDestroy {
312340
313341 return data ;
314342 }
343+
344+ /**
345+ * Renders a short static sample without connecting to the backend.
346+ */
347+ private renderStaticDemoText ( ) : void {
348+ this . terminal . writeln ( '' ) ;
349+ this . terminal . writeln ( 'Willkommen zum barrierefreien Testlauf.' ) ;
350+ this . terminal . writeln ( 'Die Verbindung zum Server ist deaktiviert.' ) ;
351+ this . terminal . writeln (
352+ 'Das Terminal zeigt ausschließlich diesen statischen Text an.' ,
353+ ) ;
354+ this . terminal . writeln ( '' ) ;
355+ this . terminal . writeln (
356+ 'Drücken von Tasten hat in diesem Modus keine Wirkung.' ,
357+ ) ;
358+ }
315359}
0 commit comments