Avoid using getBoundingClientRect to calculate height (#4001)

pull/4102/merge
Nolan Lawson 2017-07-07 16:57:22 -07:00 committed by Eugen Rochko
parent 8fecd80108
commit 63b77f2320
4 changed files with 30 additions and 20 deletions

View File

@ -17,6 +17,7 @@ import { MediaGallery, VideoPlayer } from '../features/ui/util/async-components'
// We use the component (and not the container) since we do not want // We use the component (and not the container) since we do not want
// to use the progress bar to show download progress // to use the progress bar to show download progress
import Bundle from '../features/ui/components/bundle'; import Bundle from '../features/ui/components/bundle';
import getRectFromEntry from '../features/ui/util/get_rect_from_entry';
export default class Status extends ImmutablePureComponent { export default class Status extends ImmutablePureComponent {
@ -101,6 +102,11 @@ export default class Status extends ImmutablePureComponent {
} }
handleIntersection = (entry) => { handleIntersection = (entry) => {
if (this.node && this.node.children.length !== 0) {
// save the height of the fully-rendered element
this.height = getRectFromEntry(entry).height;
}
// Edge 15 doesn't support isIntersecting, but we can infer it // Edge 15 doesn't support isIntersecting, but we can infer it
// https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12156111/ // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12156111/
// https://github.com/WICG/IntersectionObserver/issues/211 // https://github.com/WICG/IntersectionObserver/issues/211
@ -129,15 +135,8 @@ export default class Status extends ImmutablePureComponent {
this.setState((prevState) => ({ isHidden: !prevState.isIntersecting })); this.setState((prevState) => ({ isHidden: !prevState.isIntersecting }));
} }
saveHeight = () => {
if (this.node && this.node.children.length !== 0) {
this.height = this.node.getBoundingClientRect().height;
}
}
handleRef = (node) => { handleRef = (node) => {
this.node = node; this.node = node;
this.saveHeight();
} }
handleClick = () => { handleClick = () => {
@ -213,13 +212,13 @@ export default class Status extends ImmutablePureComponent {
} else if (status.getIn(['media_attachments', 0, 'type']) === 'video') { } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') {
media = ( media = (
<Bundle fetchComponent={VideoPlayer} loading={this.renderLoadingVideoPlayer} onRender={this.saveHeight} > <Bundle fetchComponent={VideoPlayer} loading={this.renderLoadingVideoPlayer} >
{Component => <Component media={status.getIn(['media_attachments', 0])} sensitive={status.get('sensitive')} onOpenVideo={this.props.onOpenVideo} />} {Component => <Component media={status.getIn(['media_attachments', 0])} sensitive={status.get('sensitive')} onOpenVideo={this.props.onOpenVideo} />}
</Bundle> </Bundle>
); );
} else { } else {
media = ( media = (
<Bundle fetchComponent={MediaGallery} loading={this.renderLoadingMediaGallery} onRender={this.saveHeight} > <Bundle fetchComponent={MediaGallery} loading={this.renderLoadingMediaGallery} >
{Component => <Component media={status.get('media_attachments')} sensitive={status.get('sensitive')} height={110} onOpenMedia={this.props.onOpenMedia} autoPlayGif={this.props.autoPlayGif} />} {Component => <Component media={status.get('media_attachments')} sensitive={status.get('sensitive')} height={110} onOpenMedia={this.props.onOpenMedia} autoPlayGif={this.props.autoPlayGif} />}
</Bundle> </Bundle>
); );
@ -246,7 +245,7 @@ export default class Status extends ImmutablePureComponent {
</a> </a>
</div> </div>
<StatusContent status={status} onClick={this.handleClick} expanded={isExpanded} onExpandedToggle={this.handleExpandedToggle} onHeightUpdate={this.saveHeight} /> <StatusContent status={status} onClick={this.handleClick} expanded={isExpanded} onExpandedToggle={this.handleExpandedToggle} />
{media} {media}

View File

@ -17,7 +17,6 @@ export default class StatusContent extends React.PureComponent {
status: ImmutablePropTypes.map.isRequired, status: ImmutablePropTypes.map.isRequired,
expanded: PropTypes.bool, expanded: PropTypes.bool,
onExpandedToggle: PropTypes.func, onExpandedToggle: PropTypes.func,
onHeightUpdate: PropTypes.func,
onClick: PropTypes.func, onClick: PropTypes.func,
}; };
@ -56,9 +55,6 @@ export default class StatusContent extends React.PureComponent {
} }
componentDidUpdate () { componentDidUpdate () {
if (this.props.onHeightUpdate) {
this.props.onHeightUpdate();
}
this._updateStatusLinks(); this._updateStatusLinks();
} }

View File

@ -12,7 +12,6 @@ class Bundle extends React.Component {
error: PropTypes.func, error: PropTypes.func,
children: PropTypes.func.isRequired, children: PropTypes.func.isRequired,
renderDelay: PropTypes.number, renderDelay: PropTypes.number,
onRender: PropTypes.func,
onFetch: PropTypes.func, onFetch: PropTypes.func,
onFetchSuccess: PropTypes.func, onFetchSuccess: PropTypes.func,
onFetchFail: PropTypes.func, onFetchFail: PropTypes.func,
@ -22,7 +21,6 @@ class Bundle extends React.Component {
loading: emptyComponent, loading: emptyComponent,
error: emptyComponent, error: emptyComponent,
renderDelay: 0, renderDelay: 0,
onRender: noop,
onFetch: noop, onFetch: noop,
onFetchSuccess: noop, onFetchSuccess: noop,
onFetchFail: noop, onFetchFail: noop,
@ -43,10 +41,6 @@ class Bundle extends React.Component {
} }
} }
componentDidUpdate () {
this.props.onRender();
}
componentWillUnmount () { componentWillUnmount () {
if (this.timeout) { if (this.timeout) {
clearTimeout(this.timeout); clearTimeout(this.timeout);

View File

@ -0,0 +1,21 @@
// Get the bounding client rect from an IntersectionObserver entry.
// This is to work around a bug in Chrome: https://crbug.com/737228
let hasBoundingRectBug;
function getRectFromEntry(entry) {
if (typeof hasBoundingRectBug !== 'boolean') {
const boundingRect = entry.target.getBoundingClientRect();
const observerRect = entry.boundingClientRect;
hasBoundingRectBug = boundingRect.height !== observerRect.height ||
boundingRect.top !== observerRect.top ||
boundingRect.width !== observerRect.width ||
boundingRect.bottom !== observerRect.bottom ||
boundingRect.left !== observerRect.left ||
boundingRect.right !== observerRect.right;
}
return hasBoundingRectBug ? entry.target.getBoundingClientRect() : entry.boundingClientRect;
}
export default getRectFromEntry;