frontend-tutorial-framework/src/app/services/terminado.service.ts

99 lines
3.0 KiB
TypeScript

import { Injectable } from '@angular/core';
import { Terminal } from 'xterm';
import * as fit from 'xterm/lib/addons/fit/fit';
import * as terminado from 'xterm/lib/addons/terminado/terminado';
@Injectable()
export class TerminadoService {
xterm: Terminal;
ws: WebSocket;
attached = false;
private dataListener: any;
private resizeListener: any;
constructor() {
Terminal.applyAddon(fit);
this.xterm = this.createTerminal();
}
createTerminal() {
return new Terminal({
theme: {
foreground: '#ffffff',
background: '#0C0C0C', // $tao-gray-800
cursor: '#ffffff',
selection: 'rgba(255, 255, 255, 0.3)',
black: '#000000',
red: '#FF5252', // $tao-red-500
brightRed: '#FF7171', // $tao-red-400
green: '#2fd19f', // $tao-bright-green-500
brightGreen: '#2fd19f', // $tao-bright-green-500
brightYellow: '#FFD283', // $tao-warm-yellow-300
yellow: '#FFB83B', // $tao-warm-yellow-500
magenta: '#FF8FC6', // $tao-pink-200
brightMagenta: '#FF8FC6', // $tao-pink-200
cyan: '#277EEC', // $tao-blue-500
blue: '#277EEC', // $tao-blue-500
brightCyan: '#42B7DF', // $tao-sky-400
brightBlue: '#19A7D8', // $tao-sky-500
white: '#FAFAFA', // $tao-gray-50
brightBlack: '#808080',
brightWhite: '#ffffff'
},
fontSize: 14
});
}
attach(element: HTMLElement) {
if (this.attached) {
return;
}
const wsproto = (location.protocol === 'https:') ? 'wss://' : 'ws://';
this.ws = new WebSocket(wsproto + window.location.host + '/terminal');
this.ws.onopen = () => {
this.attached = true;
this.xterm = this.createTerminal();
this.xterm.open(element);
this.fit();
// In order to reset the terminal state after a broken socket, we need to register the listeners manually.
(<any>this.xterm)._core.register(this.dataListener = this.xterm.onData(data => {
this.ws.send(JSON.stringify(['stdin', data]));
}));
(<any>this.xterm)._core.register(this.resizeListener = this.xterm.onResize((size: { rows: number, cols: number }) => {
this.ws.send(JSON.stringify(['set_size', size.rows, size.cols]));
}));
};
this.ws.onclose = () => {
this.detach();
this.xterm.destroy();
this.attach(element);
};
this.ws.onmessage = msg => {
const data = JSON.parse(msg.data);
if (data[0] === 'stdout') {
this.xterm.write(data[1]);
}
};
}
detach() {
if (!this.attached) {
return;
}
this.attached = false;
this.dataListener.dispose();
this.resizeListener.dispose();
}
fit() {
if (this.attached) {
(<any>this.xterm).fit();
}
}
}