Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
10b8e6a
Modified for FlatList
Nov 6, 2017
33dc31f
Removed invertible-scroll-view from the dependencies
gavin-gmlab Nov 21, 2017
1ea1775
chore(lint): merge some new lint
xcarpentier Jan 15, 2018
8ff8f3a
chore(test): update jest snapshot
xcarpentier Jan 15, 2018
6786177
feat(purecomponent): remove state and weird styles
xcarpentier Jan 23, 2018
e1cc214
fix(test): update snapshot
xcarpentier Jan 23, 2018
c41b64d
fix(state): remove state at all
xcarpentier Jan 23, 2018
43b57fa
fix(hash): try without
xcarpentier Jan 23, 2018
d7e8718
fix(hash): re-add hash for local test
xcarpentier Jan 24, 2018
761126d
fix(ref): undefined on scroll
xcarpentier Jan 24, 2018
a490305
chore(appr): get mine
xcarpentier Jan 24, 2018
0fea254
feat(expo): change splash screen
xcarpentier Jan 24, 2018
3903cd9
chore(sentry): add sentry to debug crash
xcarpentier Jan 24, 2018
ffb9c8a
fix(lint): ignore example-expo
xcarpentier Jan 24, 2018
5dc7f1a
fix(ref): try with deprecated string ref
xcarpentier Jan 24, 2018
8abb5a3
fix(scroll): try by removing scroll
xcarpentier Jan 24, 2018
4f07992
chore(e2e): init detox
xcarpentier Jan 24, 2018
a85b9fb
chore(travis): add timeout cache
xcarpentier Jan 24, 2018
75ded90
fix(cache): remove cache
xcarpentier Jan 24, 2018
b2e74d5
clean(comment): remove old comments
xcarpentier Jan 24, 2018
5b35d29
chore(e2e): finish detox
xcarpentier Jan 24, 2018
05281c3
Merge branch 'master' of https://github.com/FaridSafi/react-native-gi…
xcarpentier Jan 24, 2018
a7bfd07
fix(data): add image
xcarpentier Jan 24, 2018
32a268d
fix(test): add snapshot, id for detox
xcarpentier Jan 25, 2018
505d749
fix(FlatList): try to find the best props
xcarpentier Jan 25, 2018
8ccbcd0
feat(chat): maxToRenderPerBatch
xcarpentier Jan 25, 2018
abbbdbe
fix(flatlist): Not Remove subview clipped
xcarpentier Jan 28, 2018
a27677d
fix(scroll blocking): multiply by 2 windowSize
xcarpentier Jan 28, 2018
ad12782
Update Constant.js
xcarpentier Jan 28, 2018
903dabf
fix(test): update snapshot
xcarpentier Jan 29, 2018
b8deab5
fix(test): update snapshot again
xcarpentier Jan 29, 2018
321afe4
upgrade 25 wip
xcarpentier Feb 16, 2018
7cd6d79
chore(yarn): lock
xcarpentier Mar 8, 2018
58b59d7
merge from v0.4.1
xcarpentier Mar 8, 2018
75c7442
fix(expo): ugrade to expo 25
xcarpentier Mar 8, 2018
2412107
chore(travis): log to debug
xcarpentier Mar 8, 2018
7f12e12
fix(coverage): add dummy test to be happy
xcarpentier Mar 9, 2018
5ef003e
chore(travis): appr only on local pr
xcarpentier Mar 9, 2018
e93d2d8
Merge branch 'master' into modified-for-flatlist
brunocascio Mar 13, 2018
e67f3cc
chore(merge): master and fix conflict
xcarpentier Mar 16, 2018
bebe79f
chore(merge): fix conflict on MessageContainer
xcarpentier Mar 16, 2018
30d02be
fix(initialNumToRender): remove settings
xcarpentier Mar 16, 2018
680e4cd
chore(exp): upgrade example
xcarpentier Mar 16, 2018
f60bd71
fix(setPRVersion): save app instead of pkg
xcarpentier Mar 16, 2018
d5f454e
fix(test): regenerate snapshot
xcarpentier Mar 16, 2018
041ffb9
fix(example): version
xcarpentier Mar 16, 2018
5845c41
fix(FlatList): perf by PureComponent and removeClippedSubviews on and…
xcarpentier Mar 21, 2018
a2deae8
refactor(isSame props): remove isSame props like said in next major r…
xcarpentier Mar 21, 2018
ca6f0f5
fix(FlatList): purify Avatar, Bubble, ...
xcarpentier Mar 21, 2018
3eb2ff0
chore(package): remove hash-sum
xcarpentier Mar 21, 2018
f60f1f2
fix(perf): try to use shouldComponentUpdate on MessageText
xcarpentier Mar 21, 2018
b55d841
Merge branch 'master' into modified-for-flatlist
xcarpentier May 29, 2018
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
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"scripts": {
"lint": "eslint . --ext .js,.jsx",
"precommit": "yarn lint",
"test": "jest",
"test": "jest --no-watchman",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage"
},
Expand Down Expand Up @@ -57,7 +57,6 @@
"moment": "^2.19.0",
"prop-types": "15.6.0",
"react-native-communications": "2.2.1",
"react-native-invertible-scroll-view": "^1.1.0",
"react-native-lightbox": "^0.7.0",
"react-native-parsed-text": "^0.0.20",
"shallowequal": "1.0.2",
Expand Down
158 changes: 72 additions & 86 deletions src/MessageContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@
no-param-reassign: 0,
no-use-before-define: ["error", { "variables": false }],
no-return-assign: 0,
react/no-string-refs: 0
react/no-string-refs: 0,
react/sort-comp: 0
*/

import PropTypes from 'prop-types';
import React from 'react';

import { ListView, View, StyleSheet } from 'react-native';
import { FlatList, View, StyleSheet } from 'react-native';

import shallowequal from 'shallowequal';
import InvertibleScrollView from 'react-native-invertible-scroll-view';
import md5 from 'md5';
import LoadEarlier from './LoadEarlier';
import Message from './Message';

Expand All @@ -25,30 +24,13 @@ export default class MessageContainer extends React.Component {
this.renderRow = this.renderRow.bind(this);
this.renderFooter = this.renderFooter.bind(this);
this.renderLoadEarlier = this.renderLoadEarlier.bind(this);
this.renderScrollComponent = this.renderScrollComponent.bind(this);

const dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => {
return r1.hash !== r2.hash;
},
});

const messagesData = this.prepareMessages(props.messages);
this.renderHeaderWrapper = this.renderHeaderWrapper.bind(this);
this.keyExtractor = this.keyExtractor.bind(this);
this.state = {
dataSource: dataSource.cloneWithRows(messagesData.blob, messagesData.keys),
messagesData: this.prepareMessages(props.messages),
};
}

componentWillReceiveProps(nextProps) {
if (this.props.messages === nextProps.messages) {
return;
}
const messagesData = this.prepareMessages(nextProps.messages);
this.setState({
dataSource: this.state.dataSource.cloneWithRows(messagesData.blob, messagesData.keys),
});
}

shouldComponentUpdate(nextProps, nextState) {
if (!shallowequal(this.props, nextProps)) {
return true;
Expand All @@ -60,26 +42,35 @@ export default class MessageContainer extends React.Component {
}

prepareMessages(messages) {
return {
keys: messages.map((m) => m._id),
blob: messages.reduce((o, m, i) => {
const previousMessage = messages[i + 1] || {};
const nextMessage = messages[i - 1] || {};
// add next and previous messages to hash to ensure updates
const toHash = JSON.stringify(m) + previousMessage._id + nextMessage._id;
o[m._id] = {
...m,
previousMessage,
nextMessage,
hash: md5(toHash),
};
return o;
}, {}),
};
return messages.reduce((o, m, i) => {
const previousMessage = messages[i + 1] || {};
const nextMessage = messages[i - 1] || {};
o.push({
...m,
previousMessage,
nextMessage,
});
return o;
}, []);
}

scrollTo(options) {
this._invertibleScrollViewRef.scrollTo(options);
componentWillReceiveProps(nextProps) {
if (this.props.messages === nextProps.messages) {
return;
}
this.setState({
messagesData: this.prepareMessages(nextProps.messages),
});
}

renderFooter() {
if (this.props.renderFooter) {
const footerProps = {
...this.props,
};
return this.props.renderFooter(footerProps);
}
return null;
}

renderLoadEarlier() {
Expand All @@ -95,72 +86,66 @@ export default class MessageContainer extends React.Component {
return null;
}

renderFooter() {
if (this.props.renderFooter) {
const footerProps = {
...this.props,
};
return this.props.renderFooter(footerProps);
}
return null;
scrollTo(options) {
this.refs.flatListRef.scrollToOffset(options);
}

renderRow(message) {
if (!message._id && message._id !== 0) {
console.warn('GiftedChat: `_id` is missing for message', JSON.stringify(message));
renderRow({ item }) {
if (!item._id && item._id !== 0) {
console.warn('GiftedChat: `_id` is missing for message', JSON.stringify(item));
}
if (!message.user) {
if (!message.system) {
console.warn('GiftedChat: `user` is missing for message', JSON.stringify(message));
if (!item.user) {
if (!item.system) {
console.warn('GiftedChat: `user` is missing for message', JSON.stringify(item));
}
message.user = {};
item.user = {};
}

const messageProps = {
...this.props,
key: message._id,
currentMessage: message,
previousMessage: message.previousMessage,
nextMessage: message.nextMessage,
position: message.user._id === this.props.user._id ? 'right' : 'left',
key: item._id,
currentMessage: item,
previousMessage: item.previousMessage,
nextMessage: item.nextMessage,
position: item.user._id === this.props.user._id ? 'right' : 'left',
};

if (this.props.renderMessage) {
return this.props.renderMessage(messageProps);
}
return <Message {...messageProps} />;
}

renderScrollComponent(props) {
const { invertibleScrollViewProps } = this.props;
return (
<InvertibleScrollView
{...props}
{...invertibleScrollViewProps}
ref={(component) => (this._invertibleScrollViewRef = component)}
/>
<View style={{ transform: [{ scaleY: -1 }, { perspective: 1280 }] }}>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this?

<Message {...messageProps} />
</View>
);
}

render() {
const contentContainerStyle = this.props.inverted
? {}
: styles.notInvertedContentContainerStyle;
renderHeaderWrapper() {
return <View style={styles.headerWrapper}>{this.renderLoadEarlier()}</View>;
}

keyExtractor(item, index) {
return `${item._id} ${index}`;
}

render() {
return (
<View ref="container" style={styles.container}>
<ListView
<FlatList
Copy link

@cshen4 cshen4 May 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this section in line 92-94 for? In our implementation, we have a case where there's no messages but we are currently loading earlier messages. In this case we would like to render the component we pass in through renderLoadEarlier.

enableEmptySections
automaticallyAdjustContentInsets={false}
initialListSize={20}
pageSize={20}
ref="flatListRef"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String ref was deprecated a year ago, you should use callback refs only.

ref={flatListRef =>
  if (flatListRef) {
    this.flatListRef = flatListRef
  }
}

keyExtractor={this.keyExtractor}
{...this.props.listViewProps}
dataSource={this.state.dataSource}
contentContainerStyle={contentContainerStyle}
renderRow={this.renderRow}
renderHeader={this.props.inverted ? this.renderFooter : this.renderLoadEarlier}
renderFooter={this.props.inverted ? this.renderLoadEarlier : this.renderFooter}
renderScrollComponent={this.renderScrollComponent}
data={this.state.messagesData}
renderItem={this.renderRow}
renderHeader={this.renderFooter}
renderFooter={this.renderLoadEarlier()}
style={{ transform: [{ scaleY: -1 }, { perspective: 1280 }] }}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this?

{...this.props.invertibleScrollViewProps}
ListFooterComponent={this.renderHeaderWrapper}
/>
</View>
);
Expand All @@ -172,8 +157,9 @@ const styles = StyleSheet.create({
container: {
flex: 1,
},
notInvertedContentContainerStyle: {
justifyContent: 'flex-end',
headerWrapper: {
flex: 1,
transform: [{ scaleY: -1 }, { perspective: 1280 }],

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this?

},
});

Expand All @@ -182,7 +168,7 @@ MessageContainer.defaultProps = {
user: {},
renderFooter: null,
renderMessage: null,
onLoadEarlier: () => { },
onLoadEarlier: () => {},
inverted: true,
loadEarlier: false,
listViewProps: {},
Expand Down
67 changes: 58 additions & 9 deletions src/__tests__/__snapshots__/MessageContainer.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,70 @@ exports[`should render <MessageContainer /> and compare with snapshot 1`] = `
}
>
<RCTScrollView
ListFooterComponent={[Function]}
automaticallyAdjustContentInsets={false}
contentContainerStyle={Object {}}
dataSource={
ListViewDataSource {
"items": 0,
}
}
data={Array []}
disableVirtualization={false}
enableEmptySections={true}
getItem={[Function]}
getItemCount={[Function]}
horizontal={false}
initialListSize={20}
initialNumToRender={10}
keyExtractor={[Function]}
maxToRenderPerBatch={10}
numColumns={1}
onContentSizeChange={[Function]}
onEndReachedThreshold={2}
onLayout={[Function]}
onMomentumScrollEnd={[Function]}
onScroll={[Function]}
onScrollBeginDrag={[Function]}
onScrollEndDrag={[Function]}
pageSize={20}
renderFooter={[Function]}
renderFooter={null}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this?

renderHeader={[Function]}
renderRow={[Function]}
renderItem={[Function]}
scrollEventThrottle={50}
stickyHeaderIndices={Array []}
style={
Object {
"transform": Array [
Object {
"scaleY": -1,
},
Object {
"perspective": 1280,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this?

},
],
}
}
updateCellsBatchingPeriod={50}
viewabilityConfigCallbackPairs={Array []}
windowSize={21}
>
<View />
<View>
<View
onLayout={[Function]}
style={null}
>
<View
style={
Object {
"flex": 1,
"transform": Array [
Object {
"scaleY": -1,
},
Object {
"perspective": 1280,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this?

},
],
}
}
/>
</View>
</View>
</RCTScrollView>
</View>
`;
Loading