2018-01-09 17:12:55 +00:00
|
|
|
import { ListView as OldList } from 'realm/react-native';
|
|
|
|
import React from 'react';
|
|
|
|
import cloneReferencedElement from 'react-clone-referenced-element';
|
2018-02-08 14:08:50 +00:00
|
|
|
import { ScrollView, ListView as OldList2, LayoutAnimation } from 'react-native';
|
2018-01-16 20:27:57 +00:00
|
|
|
import moment from 'moment';
|
|
|
|
import { connect } from 'react-redux';
|
2018-01-30 19:48:26 +00:00
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
|
2018-01-16 20:27:57 +00:00
|
|
|
import DateSeparator from './DateSeparator';
|
|
|
|
import UnreadSeparator from './UnreadSeparator';
|
2018-01-30 19:48:26 +00:00
|
|
|
import styles from './styles';
|
|
|
|
import debounce from '../../utils/debounce';
|
|
|
|
import Typing from '../../containers/Typing';
|
|
|
|
import database from '../../lib/realm';
|
2018-02-08 14:08:50 +00:00
|
|
|
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
2018-01-09 17:12:55 +00:00
|
|
|
|
2018-01-30 19:48:26 +00:00
|
|
|
const DEFAULT_SCROLL_CALLBACK_THROTTLE = 100;
|
2018-01-09 17:12:55 +00:00
|
|
|
|
|
|
|
export class DataSource extends OldList.DataSource {
|
|
|
|
getRowData(sectionIndex: number, rowIndex: number): any {
|
|
|
|
const sectionID = this.sectionIdentities[sectionIndex];
|
|
|
|
const rowID = this.rowIdentities[sectionIndex][rowIndex];
|
|
|
|
return this._getRowData(this._dataBlob, sectionID, rowID);
|
|
|
|
}
|
|
|
|
_calculateDirtyArrays() { // eslint-disable-line
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2018-01-16 20:27:57 +00:00
|
|
|
|
2018-03-02 15:11:34 +00:00
|
|
|
const ds = new DataSource({ rowHasChanged: (r1, r2) => r1._id !== r2._id || r1._updatedAt.toISOString() !== r2._updatedAt.toISOString() });
|
2018-01-30 19:48:26 +00:00
|
|
|
|
|
|
|
export class List extends React.Component {
|
|
|
|
static propTypes = {
|
|
|
|
onEndReached: PropTypes.func,
|
|
|
|
renderFooter: PropTypes.func,
|
|
|
|
renderRow: PropTypes.func,
|
|
|
|
room: PropTypes.string,
|
|
|
|
end: PropTypes.bool
|
|
|
|
};
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.data = database
|
|
|
|
.objects('messages')
|
|
|
|
.filtered('rid = $0', props.room)
|
|
|
|
.sorted('ts', true);
|
|
|
|
this.dataSource = ds.cloneWithRows(this.data);
|
|
|
|
}
|
|
|
|
componentDidMount() {
|
|
|
|
this.data.addListener(this.updateState);
|
|
|
|
}
|
|
|
|
shouldComponentUpdate(nextProps) {
|
|
|
|
return this.props.end !== nextProps.end;
|
|
|
|
}
|
2018-02-08 14:08:50 +00:00
|
|
|
componentWillUpdate() {
|
|
|
|
LayoutAnimation.easeInEaseOut();
|
|
|
|
}
|
2018-01-30 19:48:26 +00:00
|
|
|
updateState = debounce(() => {
|
|
|
|
// this.setState({
|
|
|
|
this.dataSource = this.dataSource.cloneWithRows(this.data);
|
|
|
|
this.forceUpdate();
|
|
|
|
// });
|
|
|
|
}, 100);
|
|
|
|
|
|
|
|
render() {
|
|
|
|
return (<ListView
|
|
|
|
enableEmptySections
|
|
|
|
style={styles.list}
|
2018-03-02 21:31:44 +00:00
|
|
|
data={this.data}
|
2018-01-30 19:48:26 +00:00
|
|
|
onEndReachedThreshold={0.5}
|
|
|
|
renderFooter={this.props.renderFooter}
|
|
|
|
renderHeader={() => <Typing />}
|
|
|
|
onEndReached={() => this.props.onEndReached(this.data)}
|
|
|
|
dataSource={this.dataSource}
|
|
|
|
renderRow={item => this.props.renderRow(item)}
|
|
|
|
initialListSize={10}
|
2018-02-08 14:08:50 +00:00
|
|
|
{...scrollPersistTaps}
|
2018-01-30 19:48:26 +00:00
|
|
|
/>);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-08 14:08:50 +00:00
|
|
|
@connect(state => ({
|
|
|
|
lastOpen: state.room.lastOpen
|
|
|
|
}))
|
2018-01-09 17:12:55 +00:00
|
|
|
export class ListView extends OldList2 {
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
2018-03-02 21:31:44 +00:00
|
|
|
curRenderedRowsCount: 20,
|
2018-01-09 17:12:55 +00:00
|
|
|
highlightedRow: ({}: Object)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
getInnerViewNode() {
|
|
|
|
return this.refs.listView.getInnerViewNode();
|
|
|
|
}
|
|
|
|
|
|
|
|
scrollTo(...args) {
|
|
|
|
this.refs.listView.scrollTo(...args);
|
|
|
|
}
|
|
|
|
|
|
|
|
setNativeProps(props) {
|
|
|
|
this.refs.listView.setNativeProps(props);
|
|
|
|
}
|
|
|
|
static DataSource = DataSource;
|
|
|
|
render() {
|
|
|
|
const bodyComponents = [];
|
|
|
|
|
|
|
|
// const stickySectionHeaderIndices = [];
|
|
|
|
|
|
|
|
// const { renderSectionHeader } = this.props;
|
|
|
|
|
|
|
|
const header = this.props.renderHeader && this.props.renderHeader();
|
|
|
|
const footer = this.props.renderFooter && this.props.renderFooter();
|
|
|
|
// let totalIndex = header ? 1 : 0;
|
|
|
|
|
2018-03-02 21:31:44 +00:00
|
|
|
const { data } = this.props;
|
|
|
|
let count = 0;
|
|
|
|
|
|
|
|
for (let i = 0; i < this.state.curRenderedRowsCount && i < data.length; i += 1, count += 1) {
|
|
|
|
const room = data[i];
|
|
|
|
bodyComponents.push(this.props.renderRow(room));
|
|
|
|
|
|
|
|
const nextData = data[i + 1];
|
|
|
|
|
|
|
|
if (!nextData) {
|
2018-01-09 17:12:55 +00:00
|
|
|
continue; // eslint-disable-line
|
|
|
|
}
|
|
|
|
|
2018-03-02 21:31:44 +00:00
|
|
|
if (!moment(room.ts).isSame(nextData.ts, 'day')) {
|
|
|
|
bodyComponents.push(<DateSeparator key={room.ts.toISOString()} ts={room.ts} />);
|
2018-01-09 17:12:55 +00:00
|
|
|
}
|
2018-03-02 21:31:44 +00:00
|
|
|
if (this.props.lastOpen &&
|
|
|
|
moment(room.ts).isAfter(this.props.lastOpen) &&
|
|
|
|
moment(nextData.ts).isBefore(this.props.lastOpen)
|
|
|
|
) {
|
|
|
|
bodyComponents.push(<UnreadSeparator key='unread-separator' />);
|
2018-01-09 17:12:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const { ...props } = this.props;
|
|
|
|
if (!props.scrollEventThrottle) {
|
|
|
|
props.scrollEventThrottle = DEFAULT_SCROLL_CALLBACK_THROTTLE;
|
|
|
|
}
|
|
|
|
if (props.removeClippedSubviews === undefined) {
|
|
|
|
props.removeClippedSubviews = true;
|
|
|
|
}
|
|
|
|
/* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This comment
|
|
|
|
* suppresses an error found when Flow v0.54 was deployed. To see the error
|
|
|
|
* delete this comment and run Flow. */
|
|
|
|
Object.assign(props, {
|
|
|
|
onScroll: this._onScroll,
|
|
|
|
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
|
|
|
|
* comment suppresses an error when upgrading Flow's support for React.
|
|
|
|
* To see the error delete this comment and run Flow. */
|
|
|
|
// stickyHeaderIndices: this.props.stickyHeaderIndices.concat(stickySectionHeaderIndices,),
|
|
|
|
|
|
|
|
// Do not pass these events downstream to ScrollView since they will be
|
|
|
|
// registered in ListView's own ScrollResponder.Mixin
|
|
|
|
onKeyboardWillShow: undefined,
|
|
|
|
onKeyboardWillHide: undefined,
|
|
|
|
onKeyboardDidShow: undefined,
|
|
|
|
onKeyboardDidHide: undefined
|
|
|
|
});
|
|
|
|
|
|
|
|
return cloneReferencedElement(
|
|
|
|
<ScrollView {...props} />,
|
|
|
|
{
|
|
|
|
ref: this._setScrollComponentRef,
|
|
|
|
onContentSizeChange: this._onContentSizeChange,
|
|
|
|
onLayout: this._onLayout
|
|
|
|
},
|
|
|
|
header,
|
|
|
|
bodyComponents,
|
|
|
|
footer,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ListView.DataSource = DataSource;
|