Avoid two-step rendering of statuses as much as possible

Cache width shared by Video player, MediaGallery and Cards at the
ScrollableList level, pass it down through StatusList and Notifications.
This commit is contained in:
Thibaut Girka 2019-02-09 20:54:11 +01:00 committed by ThibG
parent 68f3d003d6
commit 049c9a3b97
6 changed files with 48 additions and 6 deletions

View File

@ -224,6 +224,8 @@ export default class MediaGallery extends React.PureComponent {
size: PropTypes.object, size: PropTypes.object,
onOpenMedia: PropTypes.func.isRequired, onOpenMedia: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
defaultWidth: PropTypes.number,
cacheWidth: PropTypes.func,
}; };
static defaultProps = { static defaultProps = {
@ -232,6 +234,7 @@ export default class MediaGallery extends React.PureComponent {
state = { state = {
visible: this.props.revealed === undefined ? (displayMedia !== 'hide_all' && !this.props.sensitive || displayMedia === 'show_all') : this.props.revealed, visible: this.props.revealed === undefined ? (displayMedia !== 'hide_all' && !this.props.sensitive || displayMedia === 'show_all') : this.props.revealed,
width: this.props.defaultWidth,
}; };
componentWillReceiveProps (nextProps) { componentWillReceiveProps (nextProps) {
@ -259,6 +262,7 @@ export default class MediaGallery extends React.PureComponent {
handleRef = (node) => { handleRef = (node) => {
this.node = node; this.node = node;
if (node && node.offsetWidth && node.offsetWidth != this.state.width) { if (node && node.offsetWidth && node.offsetWidth != this.state.width) {
if (this.props.cacheWidth) this.props.cacheWidth(node.offsetWidth);
this.setState({ this.setState({
width: node.offsetWidth, width: node.offsetWidth,
}); });
@ -271,10 +275,12 @@ export default class MediaGallery extends React.PureComponent {
} }
render () { render () {
const { media, intl, sensitive, letterbox, fullwidth } = this.props; const { media, intl, sensitive, letterbox, fullwidth, defaultWidth } = this.props;
const { width, visible } = this.state; const { visible } = this.state;
const size = media.take(4).size; const size = media.take(4).size;
const width = this.state.width || defaultWidth;
let children; let children;
const style = {}; const style = {};

View File

@ -40,6 +40,7 @@ export default class ScrollableList extends PureComponent {
state = { state = {
fullscreen: null, fullscreen: null,
cachedMediaWidth: 300,
}; };
intersectionObserverWrapper = new IntersectionObserverWrapper(); intersectionObserverWrapper = new IntersectionObserverWrapper();
@ -141,6 +142,10 @@ export default class ScrollableList extends PureComponent {
this.setScrollTop(newScrollTop); this.setScrollTop(newScrollTop);
} }
cacheMediaWidth = (width) => {
if (width && this.state.cachedMediaWidth != width) this.setState({ cachedMediaWidth: width });
}
getSnapshotBeforeUpdate (prevProps, prevState) { getSnapshotBeforeUpdate (prevProps, prevState) {
const someItemInserted = React.Children.count(prevProps.children) > 0 && const someItemInserted = React.Children.count(prevProps.children) > 0 &&
React.Children.count(prevProps.children) < React.Children.count(this.props.children) && React.Children.count(prevProps.children) < React.Children.count(this.props.children) &&
@ -252,7 +257,12 @@ export default class ScrollableList extends PureComponent {
intersectionObserverWrapper={this.intersectionObserverWrapper} intersectionObserverWrapper={this.intersectionObserverWrapper}
saveHeightKey={trackScroll ? `${this.context.router.route.location.key}:${scrollKey}` : null} saveHeightKey={trackScroll ? `${this.context.router.route.location.key}:${scrollKey}` : null}
> >
{React.cloneElement(child, {getScrollPosition: this.getScrollPosition, updateScrollBottom: this.updateScrollBottom})} {React.cloneElement(child, {
getScrollPosition: this.getScrollPosition,
updateScrollBottom: this.updateScrollBottom,
cachedMediaWidth: this.state.cachedMediaWidth,
cacheMediaWidth: this.cacheMediaWidth,
})}
</IntersectionObserverArticleContainer> </IntersectionObserverArticleContainer>
))} ))}

View File

@ -72,6 +72,8 @@ export default class Status extends ImmutablePureComponent {
updateScrollBottom: PropTypes.func, updateScrollBottom: PropTypes.func,
expanded: PropTypes.bool, expanded: PropTypes.bool,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
cacheMediaWidth: PropTypes.func,
cachedMediaWidth: PropTypes.number,
}; };
state = { state = {
@ -445,6 +447,8 @@ export default class Status extends ImmutablePureComponent {
fullwidth={settings.getIn(['media', 'fullwidth'])} fullwidth={settings.getIn(['media', 'fullwidth'])}
preventPlayback={isCollapsed || !isExpanded} preventPlayback={isCollapsed || !isExpanded}
onOpenVideo={this.handleOpenVideo} onOpenVideo={this.handleOpenVideo}
width={this.props.cachedMediaWidth}
cacheWidth={this.props.cacheMediaWidth}
/>)} />)}
</Bundle> </Bundle>
); );
@ -460,6 +464,8 @@ export default class Status extends ImmutablePureComponent {
fullwidth={settings.getIn(['media', 'fullwidth'])} fullwidth={settings.getIn(['media', 'fullwidth'])}
hidden={isCollapsed || !isExpanded} hidden={isCollapsed || !isExpanded}
onOpenMedia={this.props.onOpenMedia} onOpenMedia={this.props.onOpenMedia}
cacheWidth={this.props.cacheMediaWidth}
defaultWidth={this.props.cachedMediaWidth}
/> />
)} )}
</Bundle> </Bundle>
@ -476,6 +482,8 @@ export default class Status extends ImmutablePureComponent {
onOpenMedia={this.props.onOpenMedia} onOpenMedia={this.props.onOpenMedia}
card={status.get('card')} card={status.get('card')}
compact compact
cacheWidth={this.props.cacheMediaWidth}
defaultWidth={this.props.cachedMediaWidth}
/> />
); );
mediaIcon = 'link'; mediaIcon = 'link';

View File

@ -18,6 +18,9 @@ export default class Notification extends ImmutablePureComponent {
onMention: PropTypes.func.isRequired, onMention: PropTypes.func.isRequired,
getScrollPosition: PropTypes.func, getScrollPosition: PropTypes.func,
updateScrollBottom: PropTypes.func, updateScrollBottom: PropTypes.func,
cacheMediaWidth: PropTypes.func,
cachedMediaWidth: PropTypes.number,
onUnmount: PropTypes.func,
}; };
render () { render () {
@ -57,6 +60,9 @@ export default class Notification extends ImmutablePureComponent {
contextType='notifications' contextType='notifications'
getScrollPosition={getScrollPosition} getScrollPosition={getScrollPosition}
updateScrollBottom={updateScrollBottom} updateScrollBottom={updateScrollBottom}
cachedMediaWidth={this.props.cachedMediaWidth}
cacheMediaWidth={this.props.cacheMediaWidth}
onUnmount={this.props.onUnmount}
withDismiss withDismiss
/> />
); );
@ -75,6 +81,9 @@ export default class Notification extends ImmutablePureComponent {
onMention={onMention} onMention={onMention}
getScrollPosition={getScrollPosition} getScrollPosition={getScrollPosition}
updateScrollBottom={updateScrollBottom} updateScrollBottom={updateScrollBottom}
cachedMediaWidth={this.props.cachedMediaWidth}
cacheMediaWidth={this.props.cacheMediaWidth}
onUnmount={this.props.onUnmount}
withDismiss withDismiss
/> />
); );
@ -93,6 +102,9 @@ export default class Notification extends ImmutablePureComponent {
onMention={onMention} onMention={onMention}
getScrollPosition={getScrollPosition} getScrollPosition={getScrollPosition}
updateScrollBottom={updateScrollBottom} updateScrollBottom={updateScrollBottom}
cachedMediaWidth={this.props.cachedMediaWidth}
cacheMediaWidth={this.props.cacheMediaWidth}
onUnmount={this.props.onUnmount}
withDismiss withDismiss
/> />
); );

View File

@ -60,6 +60,8 @@ export default class Card extends React.PureComponent {
maxDescription: PropTypes.number, maxDescription: PropTypes.number,
onOpenMedia: PropTypes.func.isRequired, onOpenMedia: PropTypes.func.isRequired,
compact: PropTypes.bool, compact: PropTypes.bool,
defaultWidth: PropTypes.number,
cacheWidth: PropTypes.func,
}; };
static defaultProps = { static defaultProps = {
@ -68,7 +70,7 @@ export default class Card extends React.PureComponent {
}; };
state = { state = {
width: 280, width: this.props.defaultWidth || 280,
embedded: false, embedded: false,
}; };
@ -111,6 +113,7 @@ export default class Card extends React.PureComponent {
setRef = c => { setRef = c => {
if (c) { if (c) {
if (this.props.cacheWidth) this.props.cacheWidth(c.offsetWidth);
this.setState({ width: c.offsetWidth }); this.setState({ width: c.offsetWidth });
} }
} }
@ -133,7 +136,7 @@ export default class Card extends React.PureComponent {
} }
render () { render () {
const { card, maxDescription, compact } = this.props; const { card, maxDescription, compact, defaultWidth } = this.props;
const { width, embedded } = this.state; const { width, embedded } = this.state;
if (card === null) { if (card === null) {

View File

@ -103,6 +103,7 @@ export default class Video extends React.PureComponent {
inline: PropTypes.bool, inline: PropTypes.bool,
preventPlayback: PropTypes.bool, preventPlayback: PropTypes.bool,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
cacheWidth: PropTypes.func,
}; };
state = { state = {
@ -111,7 +112,7 @@ export default class Video extends React.PureComponent {
volume: 0.5, volume: 0.5,
paused: true, paused: true,
dragging: false, dragging: false,
containerWidth: false, containerWidth: this.props.width,
fullscreen: false, fullscreen: false,
hovered: false, hovered: false,
muted: false, muted: false,
@ -131,6 +132,7 @@ export default class Video extends React.PureComponent {
this.player = c; this.player = c;
if (c && c.offsetWidth && c.offsetWidth != this.state.containerWidth) { if (c && c.offsetWidth && c.offsetWidth != this.state.containerWidth) {
if (this.props.cacheWidth) this.props.cacheWidth(this.player.offsetWidth);
this.setState({ this.setState({
containerWidth: c.offsetWidth, containerWidth: c.offsetWidth,
}); });
@ -275,6 +277,7 @@ export default class Video extends React.PureComponent {
componentDidUpdate (prevProps) { componentDidUpdate (prevProps) {
if (this.player && this.player.offsetWidth && this.player.offsetWidth != this.state.containerWidth && !this.state.fullscreen) { if (this.player && this.player.offsetWidth && this.player.offsetWidth != this.state.containerWidth && !this.state.fullscreen) {
if (this.props.cacheWidth) this.props.cacheWidth(this.player.offsetWidth);
this.setState({ this.setState({
containerWidth: this.player.offsetWidth, containerWidth: this.player.offsetWidth,
}); });