diff --git a/client/app/scripts/components/terminal.js b/client/app/scripts/components/terminal.js index 0f7f902ed..d32b37f32 100644 --- a/client/app/scripts/components/terminal.js +++ b/client/app/scripts/components/terminal.js @@ -5,6 +5,7 @@ import { connect } from 'react-redux'; import classNames from 'classnames'; import { debounce } from 'lodash'; import { Terminal as Term } from 'xterm'; +import * as fit from 'xterm/lib/addons/fit/fit'; import { closeTerminal } from '../actions/app-actions'; import { getNeutralColor } from '../utils/color-utils'; @@ -30,32 +31,6 @@ function ab2str(buf) { return decodedString; } -function terminalCellSize(wrapperNode) { - // Badly guess the width/height of the row. - let characterWidth = 20; - let characterHeight = 20; - - // Now try and measure the first row we find. - const subjectRow = wrapperNode.querySelector('.terminal .xterm-rows div'); - if (!subjectRow) { - log("ERROR: Couldn't find first row, resizing might not work very well."); - } else { - const rowDisplay = subjectRow.style.display; - const contentBuffer = subjectRow.innerHTML; - - subjectRow.innerHTML = 'W'; - subjectRow.style.display = 'inline'; - characterWidth = subjectRow.getBoundingClientRect().width; - subjectRow.style.display = rowDisplay; - characterHeight = parseInt(subjectRow.offsetHeight, 10); - subjectRow.innerHTML = contentBuffer; - } - - log('Calculated (charWidth, charHeight) sizes in px: ', characterWidth, characterHeight); - return {characterWidth, characterHeight}; -} - - function openNewWindow(url, bcr, minWidth = 200) { const screenLeft = window.screenX || window.screenLeft; const screenTop = window.screenY || window.screenTop; @@ -89,8 +64,6 @@ class Terminal extends React.Component { detached: false, rows: DEFAULT_ROWS, cols: DEFAULT_COLS, - characterWidth: 0, - characterHeight: 0 }; this.handleCloseClick = this.handleCloseClick.bind(this); @@ -171,9 +144,8 @@ class Terminal extends React.Component { } mountTerminal() { + Term.applyAddon(fit); this.term = new Term({ - cols: this.state.cols, - rows: this.state.rows, convertEol: !this.props.pipe.get('raw'), cursorBlink: true, scrollback: 10000, @@ -188,17 +160,19 @@ class Terminal extends React.Component { } }); - this.createWebsocket(this.term); + this.term.on('resize', ({ cols, rows }) => { + const resizeTtyControl = this.props.pipe.get('resizeTtyControl'); + if (resizeTtyControl) { + doResizeTty(this.getPipeId(), resizeTtyControl, cols, rows); + } + this.setState({ cols, rows }); + }); - const {characterWidth, characterHeight} = terminalCellSize(this.term.element); + this.createWebsocket(this.term); window.addEventListener('resize', this.handleResizeDebounced); this.resizeTimeout = setTimeout(() => { - this.setState({ - characterWidth, - characterHeight - }); this.handleResize(); }, 10); } @@ -231,14 +205,7 @@ class Terminal extends React.Component { } } - componentDidUpdate(prevProps, prevState) { - const sizeChanged = ( - prevState.cols !== this.state.cols || - prevState.rows !== this.state.rows - ); - if (sizeChanged) { - this.term.resize(this.state.cols, this.state.rows); - } + componentDidUpdate() { if (!this.isEmbedded()) { setDocumentTitle(this.getTitle()); } @@ -256,24 +223,11 @@ class Terminal extends React.Component { this.setState({detached: true}); const bcr = this.node.getBoundingClientRect(); - const minWidth = (this.state.characterWidth * 80) + (8 * 2); - openNewWindow(`${basePath(window.location.pathname)}/terminal.html#!/state/${paramString}`, bcr, minWidth); + openNewWindow(`${basePath(window.location.pathname)}/terminal.html#!/state/${paramString}`, bcr); } handleResize() { - // scrollbar === 16px - const width = this.innerFlex.clientWidth - (2 * 8) - 16; - const height = this.innerFlex.clientHeight - (2 * 8); - const cols = Math.floor(width / this.state.characterWidth); - const rows = Math.floor(height / this.state.characterHeight); - - const resizeTtyControl = this.props.pipe.get('resizeTtyControl'); - if (resizeTtyControl) { - doResizeTty(this.getPipeId(), resizeTtyControl, cols, rows) - .then(() => this.setState({cols, rows})); - } else if (!this.props.pipe.get('raw')) { - this.setState({cols, rows}); - } + this.term.fit(); } isEmbedded() { @@ -352,9 +306,6 @@ class Terminal extends React.Component { opacity: this.state.connected ? 1 : 0.8, overflow: 'hidden', }; - const innerStyle = { - width: (this.state.cols + 2) * this.state.characterWidth - }; const innerClassName = classNames('terminal-inner hideable', { 'terminal-inactive': !this.state.connected }); @@ -362,9 +313,7 @@ class Terminal extends React.Component { return (