mirror of https://github.com/elisescu/tty-share
Refactor the whole receiver part
- remove unused dependencies - move to typescript - add an automatic way to resize the tty-receiverpull/14/merge
parent
bc832b8357
commit
71ebda8e8f
File diff suppressed because it is too large
Load Diff
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue