forked from treehouse/mastodon
Avoid using getBoundingClientRect to calculate height (#4001)
parent
8fecd80108
commit
63b77f2320
|
@ -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}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
Loading…
Reference in New Issue