Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/asepindrak/react-native-easy-chat-ui-modif


https://github.com/asepindrak/react-native-easy-chat-ui-modif

Last synced: about 1 month ago
JSON representation

Awesome Lists containing this project

README

        

# react-native-easy-chat-ui

[中文文档](./cn/README.md)

[![npm](https://img.shields.io/npm/v/react-native-easy-chat-ui.svg)](https://www.npmjs.com/package/react-native-easy-chat-ui)
[![npm](https://img.shields.io/npm/dm/react-native-easy-chat-ui.svg)](https://www.npmjs.com/package/react-native-easy-chat-ui)
[![npm](https://img.shields.io/npm/dt/react-native-easy-chat-ui.svg)](https://www.npmjs.com/package/react-native-easy-chat-ui)
[![npm](https://img.shields.io/npm/l/react-native-easy-chat-ui.svg)](https://github.com/DaiYz/react-native-easy-chat-ui/blob/master/LICENSE)

## ScreenShots


react-native-easy-chat-ui
react-native-easy-chat-ui
react-native-easy-chat-ui
react-native-easy-chat-ui
react-native-easy-chat-ui
react-native-easy-chat-ui

## Installation
* yarn add @react-native-community/viewpager
* react-native link @react-native-community/viewpager
* [npm](https://www.npmjs.com/#getting-started): `npm install react-native-easy-chat-ui --save`
* [Yarn](https://yarnpkg.com/): `yarn add react-native-easy-chat-ui`

## Dependency
- Use version `0.2.x` for RN `>= 0.44.0`
- Use version `0.1.x` for RN `< 0.44.0`

## Example

```jsx
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
StatusBar,
PermissionsAndroid
} from 'react-native';
import { Header, NavigationActions } from 'react-navigation'
import {AudioRecorder, AudioUtils} from 'react-native-audio'
import RNFS from 'react-native-fs'
import Sound from 'react-native-sound'
import { ChatScreen } from 'react-native-easy-chat-ui'

class Example extends React.Component {
state = {
messages: [
{
id: `1`,
type: 'text',
content: 'hello world',
targetId: '12345678',
chatInfo: {
avatar: require('../../source/defaultAvatar.png'),
id: '12345678',
nickName: 'Test'
},
renderTime: true,
sendStatus: 0,
time: '1542006036549'
},
{
id: `2`,
type: 'text',
content: 'hi/{se}',
targetId: '12345678',
chatInfo: {
avatar: require('../../source/defaultAvatar.png'),
id: '12345678',
nickName: 'Test'
},
renderTime: true,
sendStatus: 0,
time: '1542106036549'
},
{
id: `3`,
type: 'image',
content: {
uri: 'https://upload-images.jianshu.io/upload_images/11942126-044bd33212dcbfb8.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/300/h/240',
width: 100,
height: 80,
} ,
targetId: '12345678',
chatInfo: {
avatar: require('../../source/defaultAvatar.png'),
id: '12345678',
nickName: 'Test'
},
renderTime: false,
sendStatus: 0,
time: '1542106037000'
},
{
id: `4`,
type: 'text',
content: '你好/{weixiao}',
targetId: '88886666',
chatInfo: {
avatar: require('../../source/avatar.png'),
id: '12345678'
},
renderTime: true,
sendStatus: -2,
time: '1542177036549'
},
{
id: `5`,
type: 'voice',
content: {
uri: 'http://m10.music.126.net/20190810141311/78bf2f6e1080052bc0259afa91cf030d/ymusic/d60e/d53a/a031/1578f4093912b3c1f41a0bfd6c10115d.mp3',
length: 10
},
targetId: '12345678',
chatInfo: {
avatar: require('../../source/defaultAvatar.png'),
id: '12345678',
nickName: 'Test'
},
renderTime: true,
sendStatus: 1,
time: '1542260667161'
},
{
id: `6`,
type: 'voice',
content: {
uri: 'http://m10.music.126.net/20190810141311/78bf2f6e1080052bc0259afa91cf030d/ymusic/d60e/d53a/a031/1578f4093912b3c1f41a0bfd6c10115d.mp3',
length: 30
},
targetId: '88886666',
chatInfo: {
avatar: require('../../source/avatar.png'),
id: '12345678'
},
renderTime: true,
sendStatus: 0,
time: '1542264667161'
},
],
// chatBg: require('../../source/bg.jpg'),
inverted: false, // require
voiceHandle: true,
currentTime: 0,
recording: false,
paused: false,
stoppedRecording: false,
finished: false,
audioPath: '',
voicePlaying: false,
voiceLoading: false
}

sendMessage = (type, content, isInverted) => {
console.log(type, content, isInverted, 'msg')
}

render() {
return (
this.chat = e}
messageList={this.state.messages}
sendMessage={this.sendMessage}
/>
)
}
}
```

## Advanced example (How to record voice)

```
cd Demo
yarn
react-native run-ios or react-native run-android
```

## About Message
```js
{
messages: [
{
id: `${new Date().getTime()}`,
type: 'text',
content: 'hello world',
targetId: '12345678',
chatInfo: {
avatar: require('./app/source/image/avatar.png'),
id: '12345678',
nickName: 'Test' // not require
},
renderTime: true,
sendStatus: 0,
time: new Date().getTime()
}
]
}
```
* id: message id
* about message type: 'text', 'image', 'voice', 'video', 'location', 'share', 'videoCall', 'voiceCall', 'redEnvelope', 'file', 'system'
* targetId: The id of the person who sent the message
* content: see example
* chatInfo: The profile of the person you're chatting with
* renderTime: Whether to render time above message
* sendStatus: 0 ---> sending, 1 ---> sendSuccess, -1 ---> You are deleted or on the blacklist, -2 ---> error
* time: moment,messageList sorted by time

## Props

* message

props | default | Info
----- | ------- | -----
messageList | [] | Messages to display
inverted | false | When messageList exceeds the screen height, set it to true otherwise false (You can change this value when componentWillUnmount or delete message)
isIPhoneX | false | Is it full screen
chatBackgroundImage | null | Custom BackgroundImage
onScroll | () => {} | ListView Props
onEndReachedThreshold | 0.1 | ListView Props
chatWindowStyle | undefined | Container style
sendMessage | (type, content, isInverted) => {} | Callback when sending a message
reSendMessage | (message) => {} | Callback when you want send again
delMessage | (indexs, isInverted) => {} | Callback when delete message
renderAvatar | (message) => {} | Custom avatar view
avatarStyle | undefined | Style of avatar
chatId | '123455678' | The id of the person you're chatting with
chatType | 'friend' | Your relationship with the person you're chatting with
onMessagePress | (type, index, content) => {} | Callback when press a message
onMessageLongPress | (type, index, content) => {} | Callback when longPress a message and usePopView is false
pressAvatar | (isSelf, targetId) => {} | Callback when press avatar
headerHeight | 66 | navigation bar height + statusBar height
userProfile | {id: '88888888', avatar: 'default.png'} | Your own profile
showUserName | false | Whether show userName
loadHistory | () => {} | Callback when loading earlier messages
renderMessageTime | (time) => {} | Custom time inside above message
renderChatBg | (bg) => {} | Custom chat background image
renderErrorMessage | (messageStatus) => {} | Custom a message when the friend relationship is abnormal
panelSource | [] | Custom panel source
renderPanelRow | () => {} | Custom a tab icon
allPanelHeight | 200 | emojiPanel and plusPanel height
messageErrorIcon | icon element | Custom a icon when message failed to be sent
leftMessageBackground | '#fffff' | Custom background color on left
rightMessageBackground | '#a0e75a' | Custom background color on right
leftMessageTextStyle | undefined | Custom text message style on left
rightMessageTextStyle | undefined | Custom text message style on right

* inputBarProps

props | default | Info
----- | ------- | -----
emojiIcon | icon element | Custom emoticons
placeholder | '请输入...' | Placeholder when `text` is empty
keyboardIcon | icon | Custom keyboard icon
plusIcon | icon element | Custom plus icon
sendIcon | icon element | Custom send icon

* popViewProps

props | default | Info
----- | ------ | -----
usePopView | true | Display a popView when longPress a message
popoverStyle | {backgroundColor: '#333'} | popView style
renderDelPanel | undefined | Custom any what you want, (isSelect)=> {}
changeHeaderLeft | () => {} | Custom headerLeft
setPopItems | (type, index, text) => {let items = [{title: '删除',onPress: () => {that.props.delMessage([index])}},{title: '多选',onPress: () => {that.multipleSelect(index)}}]if (type === 'text') {items = [{title: '复制',onPress: () => Clipboard.setString(text)},{title: '删除',onPress: () => {that.props.delMessage([index])}},{title: '多选', onPress: () => {that.multipleSelect(index)}}]}return items} | Custom PopView
messageDelIcon | icon element | Custom delete icon
messageSelectIcon | icon element | Custom selected icon
renderMessageCheck | undefined | Custom selected icon, (isSelect)=> {}

* voiceProps

props | default | Info
----- | ------- | -----
useVoice | true | send voice message
pressInText | '按住 说话' | Custom pressIn text
pressOutText | '松开 发送' | Custom pressOut text
voiceIcon | icon element | Custom voice icon
voiceLeftIcon | undefined | Custom icon of the message on the left
voiceRightIcon | undefined | Custom icon of the message on the right
voiceErrorIcon | icon element | Custom icon when record error
voiceErrorText | '说话时间太短' | Custom text when record error
voiceCancelIcon | icon element | Custom icon when cancel record
voiceCancelText | '松开手指取消发送' | Custom text when cancel record
voiceNoteText | '手指上划,取消发送' | Custom text when pressIn record button
voiceSpeakIcon | [] | Custom icon when pressIn record button
audioPath | '' | File path to store voice
audioOnProgress | () => {} | Callback when recording
audioOnFinish | () => {} | Callback when finish record
audioInitPath | () => {} | Callback when init file path
audioRecord | () => {} | Callback when start record
audioStopRecord | () => {} | Callback when stop record
audioPauseRecord | () => {} | Callback when pause record
audioResumeRecord | () => {} | Callback when resume record
audioCurrentTime | 0 | audio length
audioHandle | true | Whether to get a recording handle
setAudioHandle | (status) => {} | Callback when get handle or not
audioHasPermission | false | Whether has permission
requestAndroidPermission | () => {} | Callback when check permission on android
checkPermission | () => {} | Callback whether has permission
voiceLoading | false | Loading voice or not
voicePlaying | false | Playing voice or not
voiceLeftLoadingColor | '#cccccc' | Custom background color on left when load voice
voiceVolume | 0 | Volume (0~10)
voiceRightLoadingColor | '#628b42' | Custom background color on right when load voice

* bubbleProps

props | default | Info
----- | ------- | -----
renderTextMessage | undefined | Custom message text, (data) => {}
renderImageMessage | undefined | Custom message image, (data) => {}
renderVoiceMessage | undefined | Custom message voice, (data) => {}
renderVoiceView | undefined | Custom voice container, (data) => {}
renderVideoMessage | undefined | Custom message video, (data) => {}
renderLocationMessage | undefined | Custom message location, (data) => {}
renderShareMessage| undefined | Custom message share, (data) => {}
renderVideoCallMessage| undefined | Custom message video call, (data) => {}
renderVoiceCallMessage| undefined | Custom message voice call, (data) => {}
renderRedEnvelopeMessage| undefined | Custom message red-envelope, (data) => {}
renderFileMessage| undefined | Custom message file, (data) => {}
renderPatMessage| undefined | Custom message pat, (data) => {}
renderCustomMessage| undefined | Custom message custom, (data) => {}
renderSystemMessage| undefined | Custom message system, (data) => {}

## All Props
```js
propTypes = {
/* defaultProps */
messageList: PropTypes.array.isRequired,
inverted: PropTypes.bool,
isIPhoneX: PropTypes.bool.isRequired,
lastReadAt: PropTypes.object,
chatBackgroundImage: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
onScroll: PropTypes.func,
onEndReachedThreshold: PropTypes.number,
chatWindowStyle: ViewPropTypes.style,
sendMessage: PropTypes.func,
renderAvatar: PropTypes.func,
avatarStyle: ViewPropTypes.style,
allPanelAnimateDuration: PropTypes.number,
chatType: PropTypes.oneOf(['friend', 'group']),
onMessagePress: PropTypes.func,
onMessageLongPress: PropTypes.func,
renderMessageTime: PropTypes.func,
pressAvatar: PropTypes.func,
renderErrorMessage: PropTypes.func,
renderChatBg: PropTypes.func,
reSendMessage: PropTypes.func,
headerHeight: PropTypes.number.isRequired,
iphoneXBottomPadding: PropTypes.number,
showUserName: PropTypes.bool,
showIsRead: PropTypes.bool,
showInput: PropTypes.bool,
isReadStyle: PropTypes.object,
userProfile: PropTypes.shape({
id: PropTypes.string.isRequired,
avatar: PropTypes.isRequired,
nickName: PropTypes.string
}),
panelSource: PropTypes.array,
renderPanelRow: PropTypes.func,
panelContainerStyle: ViewPropTypes.style,
itemContainerStyle: ViewPropTypes.style,
allPanelHeight: PropTypes.number,
messageErrorIcon: PropTypes.element,
loadHistory: PropTypes.func,
leftMessageBackground: PropTypes.string,
rightMessageBackground: PropTypes.string,
leftMessageTextStyle: PropTypes.object,
rightMessageTextStyle: PropTypes.object,
renderLoadEarlier: PropTypes.func,
extraData: PropTypes.any,
containerBackgroundColor: PropTypes.string,
showsVerticalScrollIndicator: PropTypes.bool,
userNameStyle: PropTypes.object,
panelContainerBackgroundColor: PropTypes.string,
/* popProps */
usePopView: PropTypes.bool,
popoverStyle: ViewPropTypes.style,
renderDelPanel: PropTypes.func,
changeHeaderLeft: PropTypes.func,
setPopItems: PropTypes.func,
messageDelIcon: PropTypes.element,
messageSelectIcon: PropTypes.element,
delMessage: PropTypes.func,
renderMessageCheck: PropTypes.func,

/* inputBarProps */
emojiIcon: PropTypes.element,
placeholder: PropTypes.string,
keyboardIcon: PropTypes.element,
plusIcon: PropTypes.element,
sendIcon: PropTypes.element,
sendUnableIcon: PropTypes.element,
inputStyle: ViewPropTypes.style,
inputOutContainerStyle: ViewPropTypes.style,
inputContainerStyle: ViewPropTypes.style,
inputHeightFix: PropTypes.number,
useEmoji: PropTypes.bool,
usePlus: PropTypes.bool,
/* voiceProps */
useVoice: PropTypes.bool,
pressInText: PropTypes.string,
pressOutText: PropTypes.string,
voiceIcon: PropTypes.element,
voiceLeftIcon: PropTypes.element,
voiceRightIcon: PropTypes.element,
voiceErrorIcon: PropTypes.element,
voiceCancelIcon: PropTypes.element,
voiceSpeakIcon: PropTypes.array,
audioPath: PropTypes.string,
audioOnProgress: PropTypes.func,
audioOnFinish: PropTypes.func,
audioInitPath: PropTypes.func,
audioRecord: PropTypes.func,
audioStopRecord: PropTypes.func,
audioPauseRecord: PropTypes.func,
audioResumeRecord: PropTypes.func,
audioCurrentTime: PropTypes.number,
audioHandle: PropTypes.bool,
setAudioHandle: PropTypes.func,
audioHasPermission: PropTypes.bool,
checkPermission: PropTypes.func,
requestAndroidPermission: PropTypes.func,
voiceErrorText: PropTypes.string,
voiceCancelText: PropTypes.string,
voiceNoteText: PropTypes.string,
voiceLoading: PropTypes.bool,
voicePlaying: PropTypes.bool,
voiceLeftLoadingColor: PropTypes.string,
voiceVolume: PropTypes.number,
voiceRightLoadingColor: PropTypes.string,
/* bubbleProps */
renderTextMessage: PropTypes.func,
renderImageMessage: PropTypes.func,
renderVoiceMessage: PropTypes.func,
renderVoiceView: PropTypes.func,
renderVideoMessage: PropTypes.func,
renderLocationMessage: PropTypes.func,
renderShareMessage: PropTypes.func,
renderVideoCallMessage: PropTypes.func,
renderVoiceCallMessage: PropTypes.func,
renderRedEnvelopeMessage: PropTypes.func,
renderFileMessage: PropTypes.func,
renderSystemMessage: PropTypes.func,
renderCustomMessage: PropTypes.func,
renderPatMessage: PropTypes.func,
/* delPanelProps */
delPanelStyle: ViewPropTypes.style,
delPanelButtonStyle: ViewPropTypes.style,
flatListProps: PropTypes.object
}

````

## Notes for Android
* Make sure you have `android:windowSoftInputMode="adjustResize"` in your `AndroidManifest.xml`:
```xml
android:windowSoftInputMode="adjustResize"
```

## Donation
☕️☕️


react-native-easy-chat-ui
react-native-easy-chat-ui

## License
* [MIT](LICENSE)