mirror of
https://github.com/quine-global/hyper.git
synced 2026-01-14 20:58:41 -09:00
Fix and simplify resize handling using ResizeObserver (#3411)
This commit is contained in:
parent
9d4a41ebaa
commit
ea3e109fbb
3 changed files with 42 additions and 49 deletions
|
|
@ -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} />;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue