Skip to content

Instantly share code, notes, and snippets.

@poberwong
Created March 12, 2018 09:22
Show Gist options
  • Save poberwong/061c5ddb39f8fea4838ed17dfa1e16ca to your computer and use it in GitHub Desktop.
Save poberwong/061c5ddb39f8fea4838ed17dfa1e16ca to your computer and use it in GitHub Desktop.
/**
* Created by dowin on 2017/8/3.
*/
import React from 'react'
import PropTypes from 'prop-types'
import {
Clipboard,
StyleSheet,
Image,
View,
Dimensions,
NativeAppEventEmitter,
NativeModules,
Animated
} from 'react-native'
import {inject, observer} from 'mobx-react'
import LGNavigationBar from '../components/LGNavigationBar'
// import Toast from 'react-native-simple-toast'
import {NimFriend, NimSession} from 'react-native-netease-im'
import ImagePicker from 'react-native-image-crop-picker'
import {MessageList, ChatInput} from 'react-native-imui'
const ContainerHeightMax = 800
// const ContainerHeightMin = 800
const ChatInputHeightMax = 300
const ChatInputHeightMin = 56
const ChatInputHeightBg = '#ffffff'
const AuroraIMUIModule = NativeModules.AuroraIMUIModule
const AnimatedImplementation = require('react-native/Libraries/Animated/src/AnimatedImplementation')
const MessageListView = AnimatedImplementation.createAnimatedComponent(MessageList)
const InputView = AnimatedImplementation.createAnimatedComponent(ChatInput)
@inject('auth')@observer
export default class Chat extends React.Component {
static navigatorStyle = {
tabBarHidden: true,
navBarBackgroundColor: '#444',
navBarButtonColor: '#fff',
navBarTextColor: '#fff'
}
static propTypes = {
navigation: PropTypes.object,
auth: PropTypes.object
}
constructor (props) {
super(props)
this.state = {
isInitialized: false, // initialization will calculate maxHeight before rendering the chat
canLoadMoreContent: true,
currentMetering: 0,
messages: [],
lastMessage: undefined,
showMenuBar: false,
menuBarOrigin: {},
menuItems: [],
isPacketModalOpen: false,
packetData: {},
sendUser: {},
selectMessage: {},
menuContainerHeight: ContainerHeightMax,
chatInputStyle: {
backgroundColor: ChatInputHeightBg,
width: width
},
chatInputheight: new Animated.Value(48),
level: '',
time: '',
status: '',
isDismissMenuContainer: false,
initList: []
}
this._loadMoreContentAsync = this._loadMoreContentAsync.bind(this)
this.onSend = this.onSend.bind(this)
// if (props.session && props.session.sessionType === '1') {
// this.props.navigator.setButtons({
// rightButtons: [
// {
// id: 'setting_team',
// icon: require('../images/session_team.png')
// }
// ]
// })
// } else {
// this.props.navigator.setButtons({
// rightButtons: [
// {
// id: 'setting_user',
// icon: require('../images/session_user.png')
// }
// ]
// })
// }
// this.props.navigator.setOnNavigatorEvent(this._onNavigatorEvent.bind(this))
}
// _onNavigatorEvent (event) {
// const {session, navigator} = this.props
// let self = this
// if (event.type == 'NavBarButtonPress') { // this is the event type for button presses
// if (event.id == 'setting_team') { // this is the same id field from the static navigatorButtons definition
// navigator.push({
// screen: 'ImDemo.SessionTeamDetail',
// title: '聊天信息',
// backButtonTitle: '返回',
// passProps: {
// session: session,
// onResult: function() {
// AuroraIMUIModule.clearMessage()
// }
// }
// })
// }
// if (event.id === 'setting_user') {
// navigator.push({
// screen: 'ImDemo.SessionUserDetail',
// title: '聊天详情',
// passProps: {
// session: session,
// onResult: function () {
// AuroraIMUIModule.clearMessage()
// }
// }
// })
// }
// }
// }
componentDidMount () {
const {auth: { nimInfo, doctorInfo }} = this.props
NimSession.login(nimInfo.accid, nimInfo.token).then(res => {
this.loadSession(doctorInfo.accid)
})
}
loadSession = (friendId) => {
NimFriend.addFriendWithType(friendId, '1', '直接加好友') // 每次都默认强行加一次好友(其实可以先看看是不是好友)
NimSession.startSession(friendId, '0')
this.sessionListener = NativeAppEventEmitter.addListener('observeReceiveMessage', (data) => {
console.info('新消息通知', data)
if (data && data.length > 0) {
AuroraIMUIModule.appendMessages(data)
AuroraIMUIModule.scrollToBottom()
}
})
this.msgStatusListener = NativeAppEventEmitter.addListener('observeMsgStatus', (data) => {
console.info('消息', data)
if (data.length > 0) {
if (data[0].status === 'send_sending') {
AuroraIMUIModule.appendMessages(data)
} else {
for (var i in data) {
AuroraIMUIModule.updateMessage(data[i])
}
}
AuroraIMUIModule.scrollToBottom()
}
})
this.deleteMessageListener = NativeAppEventEmitter.addListener('observeDeleteMessage', (data) => {
if (data.length > 0) {
for (var i in data) {
AuroraIMUIModule.deleteMessage(data[i])
}
}
})
NimSession.queryMessageListEx('', 20).then((data) => {
console.info('首次加载', data)
if (data.length > 0) {
this._lastMessage = data[0]
this.setState({initList: data})
AuroraIMUIModule.scrollToBottom()
}
}, (err) => {
console.log(err)
})
}
componentWillUnmount () {
NimSession.stopSession()
this.sessionListener && this.sessionListener.remove()
this.msgStatusListener && this.msgStatusListener.remove()
this.deleteMessageListener && this.deleteMessageListener.remove()
}
sendLocationImage (longitude, latitude, address) {
NimSession.sendLocationMessage(longitude, latitude, address)
}
onSend (text, ids) {
if (!text || !text.trim()) {
console.log('请输入聊天内容')
return
}
text = text.trim()
NimSession.sendTextMessage(text, ids)
this.forceUpdate()
}
handleImagePicker () {
if (!this.state.action) {
return
}
ImagePicker.openPicker({mediaType: 'photo', loadingLabelText: '请稍候...'}).then(image => {
NimSession.sendImageMessages(image.path, 'myName')
})
}
handleCameraPicker () {
if (!this.state.action) {
return
}
ImagePicker.openCamera({mediaType: 'photo', loadingLabelText: '请稍候...'}).then(image => {
NimSession.sendImageMessages(image.path, 'myName')
})
}
onLocation (coordinate) {
this.sendLocationImage(coordinate.longitude, coordinate.latitude, coordinate.address)
}
handleLocationClick () {
// if (!this.state.action) {
// return
// }
// this.props.navigator.showModal({
// screen: 'ImDemo.LocationPicker',
// title: '位置信息',
// backButtonTitle: '返回',
// passProps: {
// onLocation: this.onLocation.bind(this)
// }
// })
}
handleTransferClick () {
// if (!this.state.action) {
// return
// }
// const {navigator, session} = this.props
console.log('向好友转账')
}
handlePacketClick () {
if (!this.state.action) {
return
}
console.log('发红包')
}
onOpenURL = (url) => {
console.log('打开链接')
}
onMessagePress = (message) => {
// const { navigator } = this.props
// if (message.msgType === 'location') {
// navigator.push({
// screen: 'ImDemo.LocationView',
// title: '查看位置',
// passProps: {
// region: message.extend
// }
// })
// }
if (message.msgType === 'redpacket' && message.extend) {
console.log('红包详情')
}
if (message.msgType === 'transfer' && message.extend) {
console.log('转账详情')
}
if (message.msgType === 'redpacketOpen' && message.extend) {
this.onPacketPress(message)
}
}
onTouchMsgList = () => {
Animated.timing(this.state.chatInputheight, {
toValue: 48,
duration: 200
}).start()
this.setState({
isDismissMenuContainer: true,
chatInputStyle: {
backgroundColor: ChatInputHeightBg,
width: width
}
})
}
onPacketPress (message) {
console.log('红包详情')
}
onAvatarPress = (v) => {
// if (v && v.fromUser) {
// NimFriend.getUserInfo(v.fromUser._id).then((data) => {
// this.props.navigator.push({
// screen: 'ImDemo.FriendDetail',
// title: '详细资料',
// backButtonTitle: '返回',
// passProps: {
// friendData: data
// }
// })
// })
// }
}
_loadMoreContentAsync = async () => {
if (!this._lastMessage) {
return
}
return NimSession.queryMessageListEx(this._lastMessage.msgId, 20)
.then((data) => {
if (data.length > 0) {
this._lastMessage = data[0]
AuroraIMUIModule.insertMessagesToTop(data)
}
}, () => {
this.setState({canLoadMoreContent: false})
})
}
onSendText = (text) => {
this.onSend(text, [])
}
onSendRecordMessage = (path, duration) => {
NimSession.sendAudioMessage(path, duration)
}
onFeatureView = (inputHeight, showType) => {
console.log('showType: ', showType)
if (showType > 0) {
Animated.timing(this.state.chatInputheight, {
toValue: 323,
duration: 200
}).start()
} else {
Animated.timing(this.state.chatInputheight, {
toValue: 48,
duration: 260
}).start()
}
this.setState({
action: showType === 2,
isDismissMenuContainer: false,
chatInputStyle: {
backgroundColor: ChatInputHeightBg,
width: width
// height: showType === 0 ? ChatInputHeightMin : ChatInputHeightMax
},
menuContainerHeight: ContainerHeightMax // showType === 0 ? ContainerHeightMin : ContainerHeightMax + showType,
})
setTimeout(() => {
AuroraIMUIModule.scrollToBottom()
}, 500)
}
onShowKeyboard = (inputHeight, showType) => {
console.info('onShowKeyboard', inputHeight, showType)
setTimeout(() => {
AuroraIMUIModule.scrollToBottom()
}, 200)
}
onEditTextChange = (text) => {
console.log('用于做@提醒:', text)
}
onStatusViewClick = (message, opt) => {
console.info('onStatusViewClick', message + '--' + opt)
if (opt === 'copy') {
Clipboard.setString(message.text)
} else if (opt === 'delete') {
NimSession.deleteMessage(message.msgId)
AuroraIMUIModule.deleteMessage([message])
} else if (opt === 'revoke') {
NimSession.revokeMessage(message.msgId).then((data) => {
AuroraIMUIModule.deleteMessage([message])
})
}
}
renderChatInput () {
return (
<InputView style={[this.state.chatInputStyle, {height: this.state.chatInputheight}]}
menuContainerHeight={this.state.menuContainerHeight}
isDismissMenuContainer={this.state.isDismissMenuContainer}
onSendText={this.onSendText}
onSendVoice={this.onSendRecordMessage}
onShowKeyboard={this.onShowKeyboard}
onFeatureView={this.onFeatureView}
onEditTextChange={this.onEditTextChange}>
<View style={styles.search}>
{/* {this.renderActionBar()} */}
</View>
</InputView>
)
}
renderMessages () {
return (
<MessageListView style={{flex: 1}}
onMsgClick={this.onMessagePress}
onLinkClick={this.onOpenURL}
onAvatarClick={this.onAvatarPress}
onStatusViewClick={this.onStatusViewClick}
onTouchMsgList={this.onTouchMsgList}
onClickChangeAutoScroll={this.onClickChangeAutoScroll}
onPullToRefresh={this._loadMoreContentAsync}
sendBubble={{imageName: 'send_msg', padding: 10}}
receiveBubbleTextColor={'#ffffff'}
sendBubbleTextSize={14}
receiveBubbleTextSize={14}
sendBubblePressedColor={'#dddddd'}
eventMsgTxtColor={'#ffffff'}
eventMsgTxtSize={12}
initList={this.state.initList} />
)
}
goBack = () => this.props.navigation.goBack()
render () {
return (
<View style={{ flex: 1, backgroundColor: '#f7f7f7' }}>
{this.renderMessages()}
{this.renderChatInput()}
</View>
)
}
}
const {width} = Dimensions.get('window')
const sWidth = width - 55 * 4
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF'
},
messageList: {
// backgroundColor: 'red',
flex: 1,
marginTop: 0,
width: window.width,
margin: 0
},
inputView: {
backgroundColor: 'green',
width: window.width,
height: 100
},
btnStyle: {
marginTop: 10,
borderWidth: 1,
borderColor: '#3e83d7',
borderRadius: 8,
backgroundColor: '#3e83d7'
},
iconRow: {
flexDirection: 'row',
paddingHorizontal: sWidth / 5 - 1,
flexWrap: 'wrap',
paddingVertical: 30,
flex: 1
},
actionCol: {
alignItems: 'center',
marginRight: sWidth / 5,
height: 95
},
iconTouch: {
justifyContent: 'center',
alignItems: 'center'
},
search: {
flex: 1,
flexDirection: 'column',
backgroundColor: '#fff'
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment