MM-23176 Fix crash due to scrollToIndex out of range (#4027)

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
This commit is contained in:
Mattermost Build 2020-03-11 22:23:02 +01:00 committed by GitHub
parent 1c0e0e888c
commit 4f36dbc4d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 20 deletions

View file

@ -41,6 +41,7 @@ exports[`PostList setting channel deep link 1`] = `
onEndReachedThreshold={2}
onLayout={[Function]}
onScroll={[Function]}
onScrollBeginDrag={[Function]}
onScrollToIndexFailed={[Function]}
refreshControl={
<RefreshControl
@ -108,6 +109,7 @@ exports[`PostList setting permalink deep link 1`] = `
onEndReachedThreshold={2}
onLayout={[Function]}
onScroll={[Function]}
onScrollBeginDrag={[Function]}
onScrollToIndexFailed={[Function]}
refreshControl={
<RefreshControl
@ -175,6 +177,7 @@ exports[`PostList should match snapshot 1`] = `
onEndReachedThreshold={2}
onLayout={[Function]}
onScroll={[Function]}
onScrollBeginDrag={[Function]}
onScrollToIndexFailed={[Function]}
refreshControl={
<RefreshControl

View file

@ -93,6 +93,7 @@ export default class PostList extends PureComponent {
this.hasDoneInitialScroll = false;
this.contentOffsetY = 0;
this.shouldScrollToBottom = false;
this.cancelScrollToIndex = false;
this.makeExtraData = makeExtraData();
this.flatListRef = React.createRef();
@ -149,13 +150,20 @@ export default class PostList extends PureComponent {
componentWillUnmount() {
EventEmitter.off('scroll-to-bottom', this.handleSetScrollToBottom);
if (this.animationFrameIndexFailed) {
cancelAnimationFrame(this.animationFrameIndexFailed);
}
this.resetPostList();
}
if (this.animationFrameInitialIndex) {
cancelAnimationFrame(this.animationFrameInitialIndex);
}
flatListScrollToIndex = (index) => {
this.animationFrameInitialIndex = requestAnimationFrame(() => {
if (!this.cancelScrollToIndex) {
this.flatListRef.current.scrollToIndex({
animated: false,
index,
viewOffset: 0,
viewPosition: 1, // 0 is at bottom
});
}
});
}
getItemCount = () => {
@ -278,6 +286,10 @@ export default class PostList extends PureComponent {
}
};
handleScrollBeginDrag = () => {
this.cancelScrollToIndex = true;
}
handleScrollToIndexFailed = () => {
this.animationFrameIndexFailed = requestAnimationFrame(() => {
if (this.props.initialIndex > 0 && this.state.contentHeight > 0) {
@ -297,7 +309,7 @@ export default class PostList extends PureComponent {
};
loadToFillContent = () => {
setTimeout(() => {
this.fillContentTimer = setTimeout(() => {
this.handleContentSizeChange(0, this.state.contentHeight);
});
};
@ -386,27 +398,38 @@ export default class PostList extends PureComponent {
};
scrollToBottom = () => {
setTimeout(() => {
this.scrollToBottomTimer = setTimeout(() => {
if (this.flatListRef.current) {
this.flatListRef.current.scrollToOffset({offset: 0, animated: true});
}
}, 250);
};
flatListScrollToIndex = (index) => {
this.animationFrameInitialIndex = requestAnimationFrame(() => {
this.flatListRef.current.scrollToIndex({
animated: false,
index,
viewOffset: 0,
viewPosition: 1, // 0 is at bottom
});
});
}
resetPostList = () => {
this.contentOffsetY = 0;
this.hasDoneInitialScroll = false;
this.cancelScrollToIndex = false;
if (this.animationFrameIndexFailed) {
cancelAnimationFrame(this.animationFrameIndexFailed);
}
if (this.animationFrameInitialIndex) {
cancelAnimationFrame(this.animationFrameInitialIndex);
}
if (this.fillContentTimer) {
clearTimeout(this.fillContentTimer);
}
if (this.scrollToBottomTimer) {
clearTimeout(this.scrollToBottomTimer);
}
if (this.scrollToInitialTimer) {
clearTimeout(this.scrollToInitialTimer);
}
if (this.state.contentHeight !== 0) {
this.setState({contentHeight: 0});
}
@ -426,7 +449,7 @@ export default class PostList extends PureComponent {
this.hasDoneInitialScroll = true;
this.scrollToIndex(index);
} else if (count < 3) {
setTimeout(() => {
this.scrollToInitialTimer = setTimeout(() => {
this.scrollToInitialIndexIfNeeded(index, count + 1);
}, 300);
}
@ -496,6 +519,7 @@ export default class PostList extends PureComponent {
onContentSizeChange={this.handleContentSizeChange}
onLayout={this.handleLayout}
onScroll={this.handleScroll}
onScrollBeginDrag={this.handleScrollBeginDrag}
onScrollToIndexFailed={this.handleScrollToIndexFailed}
removeClippedSubviews={true}
renderItem={this.renderItem}