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);
this.bound = new WeakMap();
this.termRefs = {};
this.sizeChanged = false;
this.onTermRef = this.onTermRef.bind(this);
}
@ -103,16 +102,6 @@ class TermGroup_ extends React.PureComponent {
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() {
const {childGroups, termGroup} = this.props;
if (termGroup.sessionUid) {
@ -123,10 +112,7 @@ class TermGroup_ extends React.PureComponent {
const props = getTermGroupProps(
child.uid,
this.props.parentProps,
Object.assign({}, this.props, {
termGroup: child,
sizeChanged: this.sizeChanged
})
Object.assign({}, this.props, {termGroup: child})
);
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 {Terminal} from 'xterm';
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);
this.termWrapperRef = null;
this.termRect = null;
this.onOpen = this.onOpen.bind(this);
this.onWindowResize = this.onWindowResize.bind(this);
this.onWindowPaste = this.onWindowPaste.bind(this);
this.onTermWrapperRef = this.onTermWrapperRef.bind(this);
this.onMouseUp = this.onMouseUp.bind(this);
@ -111,8 +109,6 @@ export default class Term extends React.PureComponent {
this.term.focus();
}
this.onOpen(this.termOptions);
if (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, {
capture: true
});
@ -160,15 +152,6 @@ export default class Term extends React.PureComponent {
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() {
// eslint-disable-next-line no-console
console.warn(
@ -181,10 +164,6 @@ export default class Term extends React.PureComponent {
return document;
}
onWindowResize() {
this.fitResize();
}
// intercepting paste event for any necessary processing of
// clipboard data, if result is falsy, paste event continues
onWindowPaste(e) {
@ -281,12 +260,6 @@ export default class Term extends React.PureComponent {
this.termOptions = nextTermOptions;
if (!this.props.isTermActive && nextProps.isTermActive) {
requestAnimationFrame(() => {
this.fitResize();
});
}
if (
this.props.fontSize !== nextProps.fontSize ||
this.props.fontFamily !== nextProps.fontFamily ||
@ -304,6 +277,21 @@ export default class Term extends React.PureComponent {
onTermWrapperRef(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() {
@ -318,10 +306,6 @@ export default class Term extends React.PureComponent {
this.disposableListeners.forEach(handler => handler.dispose());
this.disposableListeners = [];
window.removeEventListener('resize', this.onWindowResize, {
passive: true
});
window.removeEventListener('paste', this.onWindowPaste, {
capture: true
});

View file

@ -85,7 +85,7 @@ export default class Terms extends React.Component {
render() {
const shift = !isMac && this.props.termGroups.length > 1;
return (
<div className={`terms_terms ${shift ? 'terms_termsShifted' : ''}`}>
<div className={`terms_terms ${shift ? 'terms_termsShifted' : 'terms_termsNotShifted'}`}>
{this.props.customChildrenBefore}
{this.props.termGroups.map(termGroup => {
const {uid} = termGroup;
@ -152,11 +152,34 @@ export default class Terms extends React.Component {
left: 0;
bottom: 0;
color: #fff;
transition: ${isMac ? 'none' : 'margin-top 0.3s ease'};
}
.terms_termsShifted {
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 {