react-native-gifted-chat
Advanced tools
Comparing version 0.0.3 to 0.0.4
{ | ||
"name": "react-native-gifted-chat", | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"description": "The most complete chat UI for React Native", | ||
@@ -49,4 +49,5 @@ "main": "index.js", | ||
"react-native-invertible-scroll-view": "^1.0.0", | ||
"react-native-parsed-text": "0.0.15" | ||
"react-native-parsed-text": "0.0.15", | ||
"shallowequal": "^0.2.2" | ||
} | ||
} |
@@ -12,7 +12,9 @@ # Gifted Chat | ||
## Android installation | ||
Add `windowSoftInputMode` in your Android Manifest `android/app/src/main/AndroidManifest.xml` | ||
``` | ||
Add `android:windowSoftInputMode="adjustResize"` to your Android Manifest `android/app/src/main/AndroidManifest.xml` | ||
```xml | ||
<!-- ... --> | ||
<activity | ||
android:name=".MainActivity" | ||
android:label="@string/app_name" | ||
android:windowSoftInputMode="adjustResize" // <!-- add this --> | ||
android:windowSoftInputMode="adjustResize" | ||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"> | ||
@@ -85,7 +87,6 @@ <!-- ... --> | ||
image: 'https://facebook.github.io/react/img/logo_og.png', | ||
// custom params | ||
// additional custom parameters | ||
} | ||
``` | ||
## Props | ||
@@ -119,4 +120,3 @@ | ||
## Features | ||
- Custom styles | ||
- Custom actions | ||
- Custom components | ||
- Multiline TextInput | ||
@@ -123,0 +123,0 @@ - Load earlier messages |
@@ -121,2 +121,4 @@ import React, { Component, PropTypes } from 'react'; | ||
marginRight: 60, | ||
minHeight: 20, | ||
justifyContent: 'flex-end', | ||
}, | ||
@@ -139,2 +141,4 @@ containerToNext: { | ||
marginLeft: 60, | ||
minHeight: 20, | ||
justifyContent: 'flex-end', | ||
}, | ||
@@ -141,0 +145,0 @@ containerToNext: { |
@@ -1,2 +0,2 @@ | ||
import React, { Component, PropTypes } from 'react'; | ||
import React, {Component, PropTypes} from 'react'; | ||
import { | ||
@@ -13,3 +13,2 @@ Animated, | ||
import moment from 'moment/min/moment-with-locales.min'; | ||
import md5 from 'md5'; | ||
@@ -52,3 +51,2 @@ import Actions from './Actions'; | ||
this._messages = []; | ||
this._messagesHash = null; | ||
@@ -69,2 +67,14 @@ this.state = { | ||
this.getLocale = this.getLocale.bind(this); | ||
this.invertibleScrollViewProps = { | ||
inverted: true, | ||
keyboardShouldPersistTaps: true, | ||
onTouchStart: this.onTouchStart, | ||
onTouchMove: this.onTouchMove, | ||
onTouchEnd: this.onTouchEnd, | ||
onKeyboardWillShow: this.onKeyboardWillShow, | ||
onKeyboardWillHide: this.onKeyboardWillHide, | ||
onKeyboardDidShow: this.onKeyboardDidShow, | ||
onKeyboardDidHide: this.onKeyboardDidHide, | ||
}; | ||
} | ||
@@ -103,3 +113,3 @@ | ||
componentWillReceiveProps(nextProps) { | ||
componentWillReceiveProps(nextProps = {}) { | ||
this.initMessages(nextProps.messages); | ||
@@ -130,3 +140,2 @@ } | ||
this._messages = messages; | ||
this.setMessagesHash(md5(JSON.stringify(messages))); | ||
} | ||
@@ -138,10 +147,2 @@ | ||
setMessagesHash(messagesHash) { | ||
this._messagesHash = messagesHash; | ||
} | ||
getMessagesHash() { | ||
return this._messagesHash; | ||
} | ||
setMaxHeight(height) { | ||
@@ -277,20 +278,9 @@ this._maxHeight = height; | ||
invertibleScrollViewProps={{ | ||
inverted: true, | ||
keyboardShouldPersistTaps: true, | ||
onTouchStart: this.onTouchStart, | ||
onTouchMove: this.onTouchMove, | ||
onTouchEnd: this.onTouchEnd, | ||
onKeyboardWillShow: this.onKeyboardWillShow, | ||
onKeyboardWillHide: this.onKeyboardWillHide, | ||
onKeyboardDidShow: this.onKeyboardDidShow, | ||
onKeyboardDidHide: this.onKeyboardDidHide, | ||
}} | ||
invertibleScrollViewProps={this.invertibleScrollViewProps} | ||
messages={this.getMessages()} | ||
messagesHash={this.getMessagesHash()} | ||
ref={component => this._messageContainerRef = component} | ||
/> | ||
{this.renderFooter()} | ||
{this.renderChatFooter()} | ||
</AnimatedView> | ||
@@ -380,8 +370,8 @@ ); | ||
renderFooter() { | ||
if (this.props.renderFooter) { | ||
renderChatFooter() { | ||
if (this.props.renderChatFooter) { | ||
const footerProps = { | ||
...this.props, | ||
}; | ||
return this.props.renderFooter(footerProps); | ||
return this.props.renderChatFooter(footerProps); | ||
} | ||
@@ -444,5 +434,7 @@ return null; | ||
messages: [], | ||
onSend: () => {}, | ||
onSend: () => { | ||
}, | ||
loadEarlier: false, | ||
onLoadEarlier: () => {}, | ||
onLoadEarlier: () => { | ||
}, | ||
locale: null, | ||
@@ -458,2 +450,3 @@ isAnimated: Platform.select({ | ||
renderFooter: null, | ||
renderChatFooter: null, | ||
renderMessageText: null, | ||
@@ -460,0 +453,0 @@ renderMessageImage: null, |
@@ -14,15 +14,2 @@ import React, { Component, PropTypes } from 'react'; | ||
export default class Message extends Component { | ||
shouldComponentUpdate(nextProps, nextState) { | ||
// not implemented yet | ||
// if (this.props.currentMessage.status !== nextProps.currentMessage.status) { | ||
// return true; | ||
// } | ||
if (this.props.nextMessage._id !== nextProps.nextMessage._id) { | ||
return true; | ||
} | ||
if (this.props.previousMessage._id !== nextProps.previousMessage._id) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
@@ -91,3 +78,3 @@ isSameDay(currentMessage = {}, diffMessage = {}) { | ||
render() { | ||
// if (!this.props.currentMessage.text && !this.props.currentMessage.customView && !this.props.currentMessage.image) { | ||
// if (!this.props.currentMessage.text && !this.props.currentMessage.image && !this.props.renderCustomView) { | ||
// return null; | ||
@@ -94,0 +81,0 @@ // } |
@@ -1,3 +0,9 @@ | ||
import React, { Component, PropTypes } from 'react'; | ||
import React, {Component, PropTypes} from 'react'; | ||
import ReactNative, { | ||
View, | ||
ListView | ||
} from 'react-native'; | ||
import shallowequal from 'shallowequal'; | ||
import InvertibleScrollView from 'react-native-invertible-scroll-view'; | ||
@@ -8,14 +14,74 @@ | ||
import md5 from 'md5'; | ||
export default class MessageContainer extends Component { | ||
constructor(props) { | ||
super(props); | ||
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.state = { | ||
dataSource: dataSource.cloneWithRows(messagesData.blob, messagesData.keys) | ||
}; | ||
} | ||
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; | ||
}, {}) | ||
}; | ||
} | ||
shouldComponentUpdate(nextProps, nextState) { | ||
if (this.props.messagesHash === nextProps.messagesHash && this.props.loadEarlier === nextProps.loadEarlier) { | ||
return false; | ||
if (!shallowequal(this.props, nextProps)) { | ||
return true; | ||
} | ||
return true; | ||
if (!shallowequal(this.state, nextState)) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
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) | ||
}); | ||
} | ||
renderFooter() { | ||
if (this.props.renderFooter) { | ||
const footerProps = { | ||
...this.props, | ||
}; | ||
return this.props.renderFooter(footerProps); | ||
} | ||
return null; | ||
} | ||
renderLoadEarlier() { | ||
@@ -40,33 +106,55 @@ if (this.props.loadEarlier === true) { | ||
render() { | ||
renderRow(message, sectionId, rowId) { | ||
if (!message._id) { | ||
console.warn('GiftedChat: `_id` is missing for message', JSON.stringify(message)); | ||
} | ||
if (!message.user) { | ||
console.warn('GiftedChat: `user` is missing for message', JSON.stringify(message)); | ||
message.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', | ||
}; | ||
if (this.props.renderMessage) { | ||
return this.props.renderMessage(messageProps); | ||
} | ||
return <Message {...messageProps}/>; | ||
} | ||
renderScrollComponent(props) { | ||
const invertibleScrollViewProps = this.props.invertibleScrollViewProps; | ||
return ( | ||
<InvertibleScrollView | ||
{...this.props.invertibleScrollViewProps} | ||
{...props} | ||
{...invertibleScrollViewProps} | ||
ref={component => this._invertibleScrollViewRef = component} | ||
> | ||
{this.props.messages.map((message, index) => { | ||
if (!message._id) { | ||
console.warn('GiftedChat: `_id` is missing for message', JSON.stringify(message)); | ||
} | ||
if (!message.user) { | ||
console.warn('GiftedChat: `user` is missing for message', JSON.stringify(message)); | ||
message.user = {}; | ||
} | ||
/> | ||
); | ||
} | ||
const messageProps = { | ||
...this.props, | ||
key: message._id, | ||
currentMessage: message, | ||
previousMessage: this.props.messages[index + 1] || {}, | ||
nextMessage: this.props.messages[index - 1] || {}, | ||
position: message.user._id === this.props.user._id ? 'right' : 'left', | ||
}; | ||
render() { | ||
return ( | ||
<View ref='container' style={{flex:1}}> | ||
<ListView | ||
enableEmptySections={true} | ||
keyboardShouldPersistTaps={true} | ||
automaticallyAdjustContentInsets={false} | ||
initialListSize={20} | ||
pageSize={20} | ||
if (this.props.renderMessage) { | ||
return this.props.renderMessage(messageProps); | ||
} | ||
return <Message {...messageProps}/>; | ||
})} | ||
{this.renderLoadEarlier()} | ||
</InvertibleScrollView> | ||
dataSource={this.state.dataSource} | ||
renderRow={this.renderRow} | ||
renderHeader={this.renderFooter} | ||
renderFooter={this.renderLoadEarlier} | ||
renderScrollComponent={this.renderScrollComponent} | ||
/> | ||
</View> | ||
); | ||
@@ -79,4 +167,6 @@ } | ||
user: {}, | ||
renderFooter: null, | ||
renderMessage: null, | ||
onLoadEarlier: () => {}, | ||
onLoadEarlier: () => { | ||
}, | ||
}; |
@@ -35,5 +35,4 @@ import React, { Component } from 'react'; | ||
container: { | ||
paddingLeft: 10, | ||
paddingRight: 10, | ||
marginBottom: 12, | ||
height: 44, | ||
justifyContent: 'flex-end', | ||
}, | ||
@@ -45,2 +44,5 @@ text: { | ||
backgroundColor: 'transparent', | ||
marginBottom: 12, | ||
marginLeft: 10, | ||
marginRight: 10, | ||
}, | ||
@@ -47,0 +49,0 @@ }); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
49181
1623
8
+ Addedshallowequal@^0.2.2
+ Addedlodash._getnative@3.9.1(transitive)
+ Addedlodash.isarguments@3.1.0(transitive)
+ Addedlodash.isarray@3.0.4(transitive)
+ Addedlodash.keys@3.1.2(transitive)
+ Addedshallowequal@0.2.2(transitive)