From 63b77f23202a6dece419e2eb7180395b2e276b09 Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Fri, 7 Jul 2017 16:57:22 -0700 Subject: [PATCH] Avoid using getBoundingClientRect to calculate height (#4001) --- app/javascript/mastodon/components/status.js | 19 ++++++++--------- .../mastodon/components/status_content.js | 4 ---- .../mastodon/features/ui/components/bundle.js | 6 ------ .../features/ui/util/get_rect_from_entry.js | 21 +++++++++++++++++++ 4 files changed, 30 insertions(+), 20 deletions(-) create mode 100644 app/javascript/mastodon/features/ui/util/get_rect_from_entry.js diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index 18ce0198eb2..df771f5a8f6 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -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 // to use the progress bar to show download progress import Bundle from '../features/ui/components/bundle'; +import getRectFromEntry from '../features/ui/util/get_rect_from_entry'; export default class Status extends ImmutablePureComponent { @@ -101,6 +102,11 @@ export default class Status extends ImmutablePureComponent { } 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 // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12156111/ // https://github.com/WICG/IntersectionObserver/issues/211 @@ -129,15 +135,8 @@ export default class Status extends ImmutablePureComponent { this.setState((prevState) => ({ isHidden: !prevState.isIntersecting })); } - saveHeight = () => { - if (this.node && this.node.children.length !== 0) { - this.height = this.node.getBoundingClientRect().height; - } - } - handleRef = (node) => { this.node = node; - this.saveHeight(); } handleClick = () => { @@ -213,13 +212,13 @@ export default class Status extends ImmutablePureComponent { } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') { media = ( - + {Component => } ); } else { media = ( - + {Component => } ); @@ -246,7 +245,7 @@ export default class Status extends ImmutablePureComponent { - + {media} diff --git a/app/javascript/mastodon/components/status_content.js b/app/javascript/mastodon/components/status_content.js index 78656571d11..02b4c84020c 100644 --- a/app/javascript/mastodon/components/status_content.js +++ b/app/javascript/mastodon/components/status_content.js @@ -17,7 +17,6 @@ export default class StatusContent extends React.PureComponent { status: ImmutablePropTypes.map.isRequired, expanded: PropTypes.bool, onExpandedToggle: PropTypes.func, - onHeightUpdate: PropTypes.func, onClick: PropTypes.func, }; @@ -56,9 +55,6 @@ export default class StatusContent extends React.PureComponent { } componentDidUpdate () { - if (this.props.onHeightUpdate) { - this.props.onHeightUpdate(); - } this._updateStatusLinks(); } diff --git a/app/javascript/mastodon/features/ui/components/bundle.js b/app/javascript/mastodon/features/ui/components/bundle.js index e69a32f474c..3eed446fec2 100644 --- a/app/javascript/mastodon/features/ui/components/bundle.js +++ b/app/javascript/mastodon/features/ui/components/bundle.js @@ -12,7 +12,6 @@ class Bundle extends React.Component { error: PropTypes.func, children: PropTypes.func.isRequired, renderDelay: PropTypes.number, - onRender: PropTypes.func, onFetch: PropTypes.func, onFetchSuccess: PropTypes.func, onFetchFail: PropTypes.func, @@ -22,7 +21,6 @@ class Bundle extends React.Component { loading: emptyComponent, error: emptyComponent, renderDelay: 0, - onRender: noop, onFetch: noop, onFetchSuccess: noop, onFetchFail: noop, @@ -43,10 +41,6 @@ class Bundle extends React.Component { } } - componentDidUpdate () { - this.props.onRender(); - } - componentWillUnmount () { if (this.timeout) { clearTimeout(this.timeout); diff --git a/app/javascript/mastodon/features/ui/util/get_rect_from_entry.js b/app/javascript/mastodon/features/ui/util/get_rect_from_entry.js new file mode 100644 index 00000000000..c266cd7dce7 --- /dev/null +++ b/app/javascript/mastodon/features/ui/util/get_rect_from_entry.js @@ -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;