Fix and simplify resize handling using ResizeObserver (#3411)

This commit is contained in:
Igor Sadikov 2019-01-21 14:34:23 -05:00 committed by CHaBou
parent 9d4a41ebaa
commit ea3e109fbb
3 changed files with 42 additions and 49 deletions

View file

@ -13,7 +13,6 @@ class TermGroup_ extends React.PureComponent {
super(props, context); super(props, context);
this.bound = new WeakMap(); this.bound = new WeakMap();
this.termRefs = {}; this.termRefs = {};
this.sizeChanged = false;
this.onTermRef = this.onTermRef.bind(this); this.onTermRef = this.onTermRef.bind(this);
} }
@ -103,16 +102,6 @@ class TermGroup_ extends React.PureComponent {
return <Term ref_={this.onTermRef} key={uid} {...props} />; return <Term ref_={this.onTermRef} key={uid} {...props} />;
} }
componentWillReceiveProps(nextProps) {
if (this.props.termGroup.sizes != nextProps.termGroup.sizes || nextProps.sizeChanged) {
this.term && this.term.fitResize();
// Indicate to children that their size has changed even if their ratio hasn't
this.sizeChanged = true;
} else {
this.sizeChanged = false;
}
}
render() { render() {
const {childGroups, termGroup} = this.props; const {childGroups, termGroup} = this.props;
if (termGroup.sessionUid) { if (termGroup.sessionUid) {
@ -123,10 +112,7 @@ class TermGroup_ extends React.PureComponent {
const props = getTermGroupProps( const props = getTermGroupProps(
child.uid, child.uid,
this.props.parentProps, this.props.parentProps,
Object.assign({}, this.props, { Object.assign({}, this.props, {termGroup: child})
termGroup: child,
sizeChanged: this.sizeChanged
})
); );
return <DecoratedTermGroup key={child.uid} {...props} />; return <DecoratedTermGroup key={child.uid} {...props} />;

View file

@ -1,4 +1,4 @@
/* global Blob,URL,requestAnimationFrame */ /* global Blob,URL,requestAnimationFrame,ResizeObserver */
import React from 'react'; import React from 'react';
import {Terminal} from 'xterm'; import {Terminal} from 'xterm';
import * as fit from 'xterm/lib/addons/fit/fit'; import * as fit from 'xterm/lib/addons/fit/fit';
@ -78,8 +78,6 @@ export default class Term extends React.PureComponent {
props.ref_(props.uid, this); props.ref_(props.uid, this);
this.termWrapperRef = null; this.termWrapperRef = null;
this.termRect = null; this.termRect = null;
this.onOpen = this.onOpen.bind(this);
this.onWindowResize = this.onWindowResize.bind(this);
this.onWindowPaste = this.onWindowPaste.bind(this); this.onWindowPaste = this.onWindowPaste.bind(this);
this.onTermWrapperRef = this.onTermWrapperRef.bind(this); this.onTermWrapperRef = this.onTermWrapperRef.bind(this);
this.onMouseUp = this.onMouseUp.bind(this); this.onMouseUp = this.onMouseUp.bind(this);
@ -111,8 +109,6 @@ export default class Term extends React.PureComponent {
this.term.focus(); this.term.focus();
} }
this.onOpen(this.termOptions);
if (props.onTitle) { if (props.onTitle) {
this.disposableListeners.push(this.term.addDisposableListener('title', props.onTitle)); this.disposableListeners.push(this.term.addDisposableListener('title', props.onTitle));
} }
@ -149,10 +145,6 @@ export default class Term extends React.PureComponent {
); );
} }
window.addEventListener('resize', this.onWindowResize, {
passive: true
});
window.addEventListener('paste', this.onWindowPaste, { window.addEventListener('paste', this.onWindowPaste, {
capture: true capture: true
}); });
@ -160,15 +152,6 @@ export default class Term extends React.PureComponent {
terms[this.props.uid] = this; terms[this.props.uid] = this;
} }
onOpen() {
// we need to delay one frame so that styles
// get applied and we can make an accurate measurement
// of the container width and height
requestAnimationFrame(() => {
this.fitResize();
});
}
getTermDocument() { getTermDocument() {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.warn( console.warn(
@ -181,10 +164,6 @@ export default class Term extends React.PureComponent {
return document; return document;
} }
onWindowResize() {
this.fitResize();
}
// intercepting paste event for any necessary processing of // intercepting paste event for any necessary processing of
// clipboard data, if result is falsy, paste event continues // clipboard data, if result is falsy, paste event continues
onWindowPaste(e) { onWindowPaste(e) {
@ -281,12 +260,6 @@ export default class Term extends React.PureComponent {
this.termOptions = nextTermOptions; this.termOptions = nextTermOptions;
if (!this.props.isTermActive && nextProps.isTermActive) {
requestAnimationFrame(() => {
this.fitResize();
});
}
if ( if (
this.props.fontSize !== nextProps.fontSize || this.props.fontSize !== nextProps.fontSize ||
this.props.fontFamily !== nextProps.fontFamily || this.props.fontFamily !== nextProps.fontFamily ||
@ -304,6 +277,21 @@ export default class Term extends React.PureComponent {
onTermWrapperRef(component) { onTermWrapperRef(component) {
this.termWrapperRef = component; this.termWrapperRef = component;
if (component) {
this.resizeObserver = new ResizeObserver(() => {
if (this.resizeTimeout) {
return;
}
this.resizeTimeout = setTimeout(() => {
delete this.resizeTimeout;
this.fitResize();
}, 0);
});
this.resizeObserver.observe(component);
} else {
this.resizeObserver.disconnect();
}
} }
componentWillUnmount() { componentWillUnmount() {
@ -318,10 +306,6 @@ export default class Term extends React.PureComponent {
this.disposableListeners.forEach(handler => handler.dispose()); this.disposableListeners.forEach(handler => handler.dispose());
this.disposableListeners = []; this.disposableListeners = [];
window.removeEventListener('resize', this.onWindowResize, {
passive: true
});
window.removeEventListener('paste', this.onWindowPaste, { window.removeEventListener('paste', this.onWindowPaste, {
capture: true capture: true
}); });

View file

@ -85,7 +85,7 @@ export default class Terms extends React.Component {
render() { render() {
const shift = !isMac && this.props.termGroups.length > 1; const shift = !isMac && this.props.termGroups.length > 1;
return ( return (
<div className={`terms_terms ${shift ? 'terms_termsShifted' : ''}`}> <div className={`terms_terms ${shift ? 'terms_termsShifted' : 'terms_termsNotShifted'}`}>
{this.props.customChildrenBefore} {this.props.customChildrenBefore}
{this.props.termGroups.map(termGroup => { {this.props.termGroups.map(termGroup => {
const {uid} = termGroup; const {uid} = termGroup;
@ -152,11 +152,34 @@ export default class Terms extends React.Component {
left: 0; left: 0;
bottom: 0; bottom: 0;
color: #fff; color: #fff;
transition: ${isMac ? 'none' : 'margin-top 0.3s ease'};
} }
.terms_termsShifted { .terms_termsShifted {
margin-top: 68px; margin-top: 68px;
animation: shift-down 0.2s ease-out;
}
.terms_termsNotShifted {
margin-top: 34px;
animation: shift-up 0.3s ease;
}
@keyframes shift-down {
0% {
transform: translateY(-34px);
}
100% {
transform: translateY(0px);
}
}
@keyframes shift-up {
0% {
transform: translateY(34px);
}
100% {
transform: translateY(0px);
}
} }
.terms_termGroup { .terms_termGroup {