Refactor the whole receiver part

- remove unused dependencies
- move to typescript
- add an automatic way to resize the tty-receiver
pull/14/merge
Vasile Popescu 5 years ago
parent bc832b8357
commit 71ebda8e8f

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
{
"name": "static",
"name": "tty-share",
"version": "1.0.0",
"description": "",
"main": "",
@ -7,25 +7,16 @@
"watch": "TTY_SHARE_ENV=development webpack --watch",
"build": "TTY_SHARE_ENV=production webpack"
},
"author": "",
"license": "",
"author": "elisescu",
"license": "elisescu",
"dependencies": {
"babel-core": "6.26.0",
"babel-loader": "7.1.2",
"babel-preset-env": "1.6.0",
"babel-preset-react": "6.24.1",
"css-loader": "0.28.7",
"ignore-loader": "0.1.2",
"material-ui": "0.19.4",
"react": "16.2.0",
"react-bootstrap": "0.31.3",
"react-dom": "16.2.0",
"source-map-loader": "0.2.2",
"style-loader": "0.19.0",
"webpack": "3.7.1",
"copy-webpack-plugin": "4.5.1",
"css-loader": "^3.0.0",
"style-loader": "^0.23.1",
"ts-loader": "^6.0.2",
"typescript": "^3.5.2",
"webpack": "^4.34.0",
"webpack-cli": "^3.3.4",
"xterm": "3.14.4"
},
"devDependencies": {
"copy-webpack-plugin": "4.5.1"
}
}

@ -0,0 +1,10 @@
{
"compilerOptions": {
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es5",
"jsx": "react",
"allowJs": true
}
}

@ -1,15 +0,0 @@
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import MuiThemePro from 'material-ui/styles/MuiThemeProvider';
import RaisedButton from 'material-ui/RaisedButton';
import TextField from 'material-ui/TextField';
class App extends Component {
constructor(props) {
super(props);
}
render() {
return (<div> </div>);
}
}
export default App;

@ -0,0 +1,12 @@
html, body {
width: 100%;
height: 100%;
margin: 0;
}
#terminal {
position: fixed;
top: 0;
width: 100%;
height: 100%;
}

@ -1,71 +0,0 @@
import 'xterm/dist/xterm.css';
import { Terminal } from 'xterm';
import pbkdf2 from 'pbkdf2';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './app';
import base64 from './base64'
ReactDOM.render(
<App />,
document.querySelector('#settings')
);
var term = new Terminal({
cursorBlink: true,
macOptionIsMeta: true,
});
var derivedKey = pbkdf2.pbkdf2Sync('password', 'salt', 4096, 32, 'sha256');
console.log(derivedKey);
let wsAddress = "";
if (window.location.protocol === "https:") {
wsAddress = 'wss://';
} else {
wsAddress = "ws://";
}
wsAddress += window.location.host + window.ttyInitialData.wsPath;
let connection = new WebSocket(wsAddress);
term.open(document.getElementById('terminal'), true);
term.write("$");
connection.onclose = function(evt) {
console.log("Got the WS closed: ", evt);
window.location.reload();
}
connection.onmessage = function(evt) {
let message = JSON.parse(evt.data)
let msgData = base64.decode(message.Data)
if (message.Type === "Write") {
let writeMsg = JSON.parse(msgData)
term.write(base64.decode(writeMsg.Data))
}
if (message.Type == "WinSize") {
let winSizeMsg = JSON.parse(msgData)
term.resize(winSizeMsg.Cols, winSizeMsg.Rows)
}
}
term.on('data', function (data) {
//console.log('TERM->WS:', data);
let writeMessage = {
Type: "Write",
Data: base64.encode(JSON.stringify({ Size: data.length, Data: base64.encode(data)})),
}
let dataToSend = JSON.stringify(writeMessage)
//console.log("Sending : ", dataToSend)
connection.send(dataToSend);
})

@ -0,0 +1,28 @@
import 'xterm/dist/xterm.css';
import './main.css';
import { Terminal } from 'xterm';
import * as pbkdf2 from 'pbkdf2';
import { TTYReceiver } from './tty-receiver';
const term = new Terminal({
cursorBlink: true,
macOptionIsMeta: true,
});
const derivedKey = pbkdf2.pbkdf2Sync('password', 'salt', 4096, 32, 'sha256');
console.log(derivedKey);
let wsAddress = "";
if (window.location.protocol === "https:") {
wsAddress = 'wss://';
} else {
wsAddress = "ws://";
}
let ttyWindow = window as any;
wsAddress += ttyWindow.location.host + ttyWindow.ttyInitialData.wsPath;
const ttyReceiver = new TTYReceiver(wsAddress, document.getElementById('terminal') as HTMLDivElement);

@ -0,0 +1,110 @@
import { Terminal, IEvent, IDisposable } from "xterm";
import base64 from './base64';
interface IRectSize {
width: number;
height: number;
}
class TTYReceiver {
private xterminal: Terminal;
private containerElement: HTMLElement;
constructor(wsAddress: string, container: HTMLDivElement) {
const connection = new WebSocket(wsAddress);
this.xterminal = new Terminal({
cursorBlink: true,
macOptionIsMeta: true,
scrollback: 0,
fontSize: 12,
letterSpacing: 0,
});
this.containerElement = container;
this.xterminal.open(container);
connection.onclose = (evt: CloseEvent) => {
// TODO: notify the user that the session was closed.
}
this.xterminal.focus();
const containerPixSize = this.getElementPixelsSize(container);
const newFontSize = this.guessNewFontSize(this.xterminal.cols, this.xterminal.rows, containerPixSize.width, containerPixSize.height);
this.xterminal.setOption('fontSize', newFontSize);
connection.onmessage = (ev: MessageEvent) => {
let message = JSON.parse(ev.data)
let msgData = base64.decode(message.Data)
if (message.Type === "Write") {
let writeMsg = JSON.parse(msgData)
this.xterminal.write(base64.decode(writeMsg.Data))
}
if (message.Type == "WinSize") {
let winSizeMsg = JSON.parse(msgData)
const containerPixSize = this.getElementPixelsSize(container);
const newFontSize = this.guessNewFontSize(winSizeMsg.Cols, winSizeMsg.Rows, containerPixSize.width, containerPixSize.height);
this.xterminal.setOption('fontSize', newFontSize);
// Now set the new size.
this.xterminal.resize(winSizeMsg.Cols, winSizeMsg.Rows)
}
}
// TODO: .on() is deprecated. Should be replaced.
this.xterminal.on('data', function (data) {
let writeMessage = {
Type: "Write",
Data: base64.encode(JSON.stringify({ Size: data.length, Data: base64.encode(data)})),
}
let dataToSend = JSON.stringify(writeMessage)
connection.send(dataToSend);
});
}
// Get the pixels size of the element, after all CSS was applied. This will be used in an ugly
// hack to guess what fontSize to set on the xterm object. Horrible hack, but I feel less bad
// about it seeing that VSV does it too:
// https://github.com/microsoft/vscode/blob/d14ee7613fcead91c5c3c2bddbf288c0462be876/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts#L363
private getElementPixelsSize(element: HTMLElement): IRectSize {
const defView = this.containerElement.ownerDocument.defaultView;
let width = parseInt(defView.getComputedStyle(element).getPropertyValue('width').replace('px', ''), 10);
let height = parseInt(defView.getComputedStyle(element).getPropertyValue('height').replace('px', ''), 10);
return {
width,
height,
}
}
// Tries to guess the new font size, for the new terminal size, so that the rendered terminal
// will have the newWidth and newHeight dimensions
private guessNewFontSize(newCols: number, newRows: number, targetWidth: number, targetHeight: number): number {
const cols = this.xterminal.cols;
const rows = this.xterminal.rows;
const fontSize = this.xterminal.getOption('fontSize');
const xtermPixelsSize = this.getElementPixelsSize(this.containerElement.querySelector(".xterm-screen"));
const newHFontSizeMultiplier = (cols / newCols) * (targetWidth / xtermPixelsSize.width);
const newVFontSizeMultiplier = (rows / newRows) * (targetHeight / xtermPixelsSize.height);
let newFontSize;
if (newHFontSizeMultiplier > newVFontSizeMultiplier) {
newFontSize = Math.floor(fontSize * newVFontSizeMultiplier);
} else {
newFontSize = Math.floor(fontSize * newHFontSizeMultiplier);
}
return newFontSize;
}
}
export {
TTYReceiver
}

@ -5,7 +5,7 @@ const develBuild = process.env.TTY_SHARE_ENV === 'development';
let mainConfig = {
entry: {
'tty-receiver': './tty-receiver/main.js',
'tty-receiver': './tty-receiver/main.ts',
},
output: {
path: __dirname + '/public/',
@ -14,45 +14,23 @@ let mainConfig = {
module: {
rules: [
{
test:/\.(js|jsx)$/,
use: [{
loader: 'babel-loader',
options: {
babelrc: false,
presets: ['env', 'react'],
},
}],
},
{
test: /\.(tsx|ts)?$/,
use: ['awesome-typescript-loader']
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /node_modules.+xterm.+\.map$/,
use: ['ignore-loader']
},
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.woff($|\?)|\.woff2($|\?)|\.ttf($|\?)|\.eot($|\?)/,
use: ['url-loader']
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: ['url-loader', 'image-webpack-loader']
},
{
test: /\.js\.map$/,
use: ['source-map-loader']
}
]
},
resolve: {
extensions: [".ts", ".tsx", ".js"],
},
plugins: [
new copyWebpackPlugin([
'static',

Loading…
Cancel
Save