반응형
google firebase 의 realtime database 와
react-native-gitfted-chat library 를 활용하면
간단하게 채팅 화면을 구성할 수 있습니다.
왼쪽은 gifted-chat 가이드 화면, 우측은 제가 직접 적용한 화면입니다.
firebase 를 미리 구성했다는 전제하에,
gitfted chat 을 프로젝트에 install 합니다.
github.com/FaridSafi/react-native-gifted-chat
- Using npm: npm install react-native-gifted-chat --save
- Using Yarn: yarn add react-native-gifted-chat
아래는 전체 코드입니다.
- firebase-xxx/chat/ 폴더 구조로 구성
- firebase 에 ios/android app 을 등록해놓고 google-services.json 이나 googleservice-info.plist 만 잘 import 시켜놓으면, 아래 코드만 가지고 firebase 와 connect 됩니다.
import {GiftedChat, SystemMessage} from "react-native-gifted-chat";
import React, {Component} from "react";
import db from '@react-native-firebase/database';
import auth from "@react-native-firebase/auth";
import {setFilterText} from '../commonProperty/setFilterText';
import {View, TouchableOpacity, Text} from 'react-native';
import Toast from 'react-native-toast-message';
import {showToast} from '../commonProperty/showToast';
import {handleEmail} from '../commonProperty/handleEmail';
import RBSheet from "react-native-raw-bottom-sheet";
import { globalStyles } from '../commonProperty/globalStyles';
import Ionicons from 'react-native-vector-icons/Ionicons';
import MaterialIcons from "react-native-vector-icons/MaterialIcons";
const database = db().ref("chat");
export default class ChatScreen extends Component {
state = {
messages: //[],
[{
_id: 0,
text: '부적절하거나 불쾌감을 줄 수 있는 대화는 삼가 부탁드립니다. 회원제재를 받을 수 있습니다.',
createdAt: new Date().getTime(),
system: true,
}],
uid: "",
reportUser: null,
};
loadMessages(callback) {
database.off(); //Detaches a callback previously attached with on()
const onReceive = data => {
const message = data.val();
callback({
_id: data.key,
text: message.text,
createdAt: message.createdAt,
user: {
_id: message.user._id,
name: message.user.name,
}
});
};
// let d = this.getLimit();
// console.log(d);
database.orderByChild('locationInfo')
.equalTo(this.props.route.params.city)
.limitToLast(mChatLimit).on("child_added", onReceive);
}
sendMessage(message) {
let today = new Date();
let timestamp = today.toISOString();
for (let i = 0; i < message.length; i++) {
if (setFilterText(message[i].text)) {
database.push({
text: message[i].text,
user: message[i].user,
createdAt: timestamp,
locationInfo: this.props.route.params.city,
email: this.props.route.params.email,
});
} else {
showToast('불쾌감을 줄 수 있는 내용은 삼가 부탁드립니다', '전송 실패', defaultDuration, 'top');
}
}
}
onRenderSystemMessage = (props) => (
<SystemMessage
{...props}
containerStyle={{backgroundColor:'#7cc8c3'}}
textStyle={{ color: "white", fontWeight:"500", fontSize: 17, textAlign:'center'}}
/>
);
closeChat() {
if (database) {
database.off();
}
}
getLimit() {
let today = new Date();
today.setDate(today.getDate() - 31); // last 30 Days
let changedISODate = new Date(today).toISOString();
// console.log(changedISODate);
return changedISODate;
}
componentDidMount() {
auth().onAuthStateChanged(user => {
if (user) {
this.setState({uid:user.uid});
}
});
this.loadMessages(message => {
this.setState(previousState => {
return {
messages: GiftedChat.append(previousState.messages, message)
};
});
});
}
onHandleEmail = () => {
handleEmail(this.state.reportUser, "채팅 중 부적절한 메시지 사용 (스크린샷 첨부 권장)", this.props.route.params.city, null);
}
onPressAvatar = (user) => {
this.setState({reportUser: user.name});
this.Standard.open();
}
componentWillUnmount() {
this.closeChat();
}
render() {
return (
<View style={{ flex: 1 }}>
<GiftedChat
messages={this.state.messages}
onSend={message => {
this.sendMessage(message);
}}
user={{
_id: this.state.uid,
name: this.props.route.params.nickname,
}}
renderSystemMessage={this.onRenderSystemMessage}
placeholder="message 입력"
onPressAvatar={this.onPressAvatar}
// onPressActionButton={this.onPressActionButton}
// renderUsernameOnMessage
/>
<Toast ref={(ref) => Toast.setRef(ref)} />
<RBSheet
ref={ref => {this.Standard = ref;}}
height={230}
closeOnDragDown
customStyles={{
container: {alignItems: "center", backgroundColor: "#F5FCFF",
borderTopLeftRadius: 30, borderTopRightRadius: 30}}}>
<View style={globalStyles.GlobalRawBottomView}>
<TouchableOpacity style={globalStyles.GlobalRawBottomTouchable} onPress={this.onHandleEmail}>
<MaterialIcons name={'report-problem'} style={globalStyles.GlobalRawBottomIcon} />
<Text style={globalStyles.GlobalRawBottomLabelStart}>신고하기</Text>
<Text style={globalStyles.GlobalRawBottomLabelEnd}/>
</TouchableOpacity>
</View>
<View style={globalStyles.GlobalRawBottomView}>
<View style={globalStyles.GlobalRawBottomTouchable}>
<Ionicons name={'ios-person'} style={globalStyles.GlobalRawBottomIcon} />
<Text style={globalStyles.GlobalRawBottomLabelStart}>유저정보</Text>
<Text style={globalStyles.GlobalRawBottomLabelEnd}>{this.state.reportUser}</Text>
</View>
</View>
<View style={globalStyles.GlobalRawBottomView}>
<TouchableOpacity style={globalStyles.GlobalRawBottomTouchable}>
<MaterialIcons name={'thumb-down-alt'} style={globalStyles.GlobalRawBottomGrayIcon} />
<Text style={globalStyles.GlobalRawBottomLabelGray}>싫어요</Text>
<Text style={globalStyles.GlobalRawBottomLabelEnd}/>
</TouchableOpacity>
</View>
</RBSheet>
</View>
);
}
}
firebase hierachy 는 아래와 같이 되어있습니다
마지막으로, 채팅 기능을 넣게되면 AppStore 심사가 까다로워지는데요
아래 심사 통과 방법도 공유 드립니다.
반응형
'Mobile 개발 > RN Project - Map Chat' 카테고리의 다른 글
RN - 클릭 위치 주소 얻기, reverse geocoding 적용 (2) | 2021.01.01 |
---|---|
RN - Project 에서 활용한 라이브러리 (2) | 2020.12.05 |
React Native map-based chat app with firebase (0) | 2020.09.16 |
RN (React Native) - 네이버지도, 클릭 위치 marker 표시 (4) | 2020.09.12 |
RN (React Native) - 네이버지도 연동 (4) | 2020.09.04 |