Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the scrolling with ScrollView #57

Merged
merged 6 commits into from
Aug 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 8 additions & 13 deletions src/page/HomePage/Report/ReportHistoryItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,14 @@ const propTypes = {
displayAsGroup: PropTypes.bool.isRequired,
};

// TODO: Fix eslint error here
// eslint-disable-next-line react/prefer-stateless-function
class ReportHistoryItem extends React.Component {
render() {
return (
<View>
{!this.props.displayAsGroup && <ReportHistoryItemSingle historyItem={this.props.historyItem} />}
{this.props.displayAsGroup && <ReportHistoryItemGrouped historyItem={this.props.historyItem} />}
{this.props.historyItem.tempGuid && <ActivityIndicator type="small" color="#7d8b8f" />}
</View>
);
}
}
const ReportHistoryItem = ({displayAsGroup, historyItem}) => (
<View>
{!displayAsGroup && <ReportHistoryItemSingle historyItem={historyItem} />}
{displayAsGroup && <ReportHistoryItemGrouped historyItem={historyItem} />}
{historyItem.tempGuid && <ActivityIndicator type="small" color="#7d8b8f" />}
</View>
);
ReportHistoryItem.propTypes = propTypes;
ReportHistoryItem.displayName = 'ReportHistoryItem';

export default ReportHistoryItem;
63 changes: 38 additions & 25 deletions src/page/HomePage/Report/ReportHistoryView.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import {Text, VirtualizedList} from 'react-native';
import {Text, ScrollView} from 'react-native';
import PropTypes from 'prop-types';
import _ from 'underscore';
import lodashGet from 'lodash.get';
Expand All @@ -18,7 +18,20 @@ class ReportHistoryView extends React.Component {
constructor(props) {
super(props);

// Keeps track of the history length so that when length changes, the list is scrolled to the bottom
this.previousReportHistoryLength = 0;
this.itemsAreRendered = false;

this.recordlastReadActionID = _.debounce(this.recordlastReadActionID.bind(this), 1000, true);
this.scrollToBottomWhenListSizeChanges = this.scrollToBottomWhenListSizeChanges.bind(this);
}

componentDidUpdate(prevProps) {
// Reset the previous history length when the props change
if (this.props.reportID !== prevProps.reportID) {
this.previousReportHistoryLength = 0;
this.itemsAreRendered = false;
}
}

/**
Expand Down Expand Up @@ -100,6 +113,25 @@ class ReportHistoryView extends React.Component {
});
}

/**
* This function is triggered from the ref callback for the scrollview. That way it can be scrolled once all the
* items have been rendered. If the number of items in our history have changed since it was last rendered, then
* scroll the list to the end.
*
* @param {object} el
*/
scrollToBottomWhenListSizeChanges(el) {
if (el) {
const filteredHistory = this.getFilteredReportHistory();
if (this.previousReportHistoryLength < filteredHistory.length) {
el.scrollToEnd({animated: false});
this.recordMaxAction();
}

this.previousReportHistoryLength = filteredHistory.length;
}
}

render() {
const filteredHistory = this.getFilteredReportHistory();

Expand All @@ -108,34 +140,15 @@ class ReportHistoryView extends React.Component {
}

return (
<VirtualizedList
data={filteredHistory.reverse()}
getItemCount={() => filteredHistory.length}
getItem={(data, index) => filteredHistory[index]}
initialNumToRender="10"
inverted
renderItem={({index, item}) => (
<ScrollView ref={this.scrollToBottomWhenListSizeChanges}>
{_.map(filteredHistory, (item, index) => (
<ReportHistoryItem
key={item.sequenceNumber}
historyItem={item}
displayAsGroup={this.isConsecutiveHistoryItemMadeByPreviousActor(index)}
/>
)}
viewabilityConfig={{
itemVisiblePercentThreshold: 100,
}}
onViewableItemsChanged={({viewableItems}) => {
const maxVisibleSequenceNumber = _.chain(viewableItems)
.pluck('item')
.pluck('sequenceNumber')
.max()
.value();
this.recordlastReadActionID(maxVisibleSequenceNumber);
}}
onEndReached={() => this.recordMaxAction()}

// We have to return a string for the key or else FlatList throws an error
keyExtractor={reportHistoryItem => `${reportHistoryItem.sequenceNumber}`}
/>
))}
</ScrollView>
);
}
}
Expand Down
28 changes: 15 additions & 13 deletions src/page/HomePage/Report/ReportView.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
import React from 'react';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import {withRouter, Route} from '../../../lib/Router';
import styles from '../../../style/StyleSheet';
import ReportHistoryView from './ReportHistoryView';
import ReportHistoryCompose from './ReportHistoryCompose';
import {addHistoryItem} from '../../../store/actions/ReportActions';

const propTypes = {
// These are from withRouter
// eslint-disable-next-line react/forbid-prop-types
match: PropTypes.object.isRequired,
};

const ReportView = props => (
const ReportView = () => (
<View style={styles.flex1}>
<Route path="/:reportID" exact>
<ReportHistoryView reportID={props.match.params.reportID} />
<ReportHistoryCompose onSubmit={text => addHistoryItem(props.match.params.reportID, text)} />
</Route>
<Route
path="/:reportID"
exact
component={({match}) => (
<ReportHistoryView reportID={match.params.reportID} />
)}
/>
<Route
path="/:reportID"
exact
component={({match}) => (
<ReportHistoryCompose reportID={match.params.reportID} onSubmit={addHistoryItem} />
)}
/>
</View>
);

ReportView.propTypes = propTypes;
ReportView.displayName = 'ReportView';

export default withRouter(ReportView);