1. 코드 작성
- 유저리스트 화면에서 유저를 클릭하면 채팅방을 오픈하는 코드를 작성
- 코드 설명 :
- 유저리스트 데이터를 받아 화면을 그리는 getUserList 메소드에서 화면을 그리고 난 뒤 유저별로 클릭 이벤트를 바인딩 하는 코드를 입력.
- 클릭시 수행되는 코드는 onUserListClick 메소드 입니다.
- onUserListClick 메소드는 아직까지는 단순하게 숨겨져있던 백버튼과 친구 초대버튼을 보이게 하고 openChatRoom메소드를 통해서 채팅방 화면을 보이게 하는 역할을 수행
- 채팅방 화면은 앱에서 보이는 탭은 3개 뿐이나 보이지 않는 4번째 탭 영역에 메세지를 볼수 있는 채팅방 화면을 숨겨져있음.
- 숨겨져있는 4번째 탭을 클릭 함으로써 채팅방 화면을 노출.
- isOpenRoom 변수는 방이 오픈된 상태인지 아닌지 구분하는 변수
- 추후에 상단 타이틀을 갱신할 때 이 값을 이용하게 됩니다.
- 코드 설명 :
/**
* 초기 필드 변수 할당
*/
FirebaseChat.prototype.init = function(){
... (생략)
this.tabMessageList = document.getElementById('tabMessageList');
this.aBackBtn = document.getElementById('aBackBtn');
this.aInvite = document.getElementById('aInvite');
}
/**
* loadUserList 에서 데이터를 받아 왔을 때
*/
FirebaseChat.prototype.getUserList = function(snapshot) {
//...생략
/**
* 유저리스트 클릭 이벤트 적용
*/
var arrLiList = this.ulUserList.getElementsByTagName('li')
var arrLiListLength = arrLiList.length;
for(var i=0; i < arrLiListLength; i++){
arrLiList[i].addEventListener('click', this.onUserListClick.bind(this));
}
}
/**
* 유저리스트 클릭
*/
FirebaseChat.prototype.onUserListClick = function(event){
this.aBackBtn.classList.remove('hiddendiv'); // 백버튼 노출
this.aInvite.classList.remove('hiddendiv'); // 초대 버튼 노툴
this.openChatRoom();
}
/**
* 챗방 오픈 , 메세지 로드 및 AddUserList
*/
FirebaseChat.prototype.openChatRoom = function(){
this.isOpenRoom = true; // 방이 열린 상태인지 확인하는 플래그 값
this.tabMessageList.click(); // 채팅방 화면 보이기
}
- 메세지를 불러오는 코드 작성
- 코드 설명 :
- 유저리스트를 클릭하는 시점에서 방 ID 값을 생성.
- init메소드에서 새롭게 추가한 MAKEID_CHAR, DATETIME_CHAR 상수는 방 ID 값을 생성할때 구분자로 사용하기 위한 상수.
- Firebase Realtime Database의 특성상 여러 항목의 조건을 한꺼번에 조회하기 어려운 경우에는 여러 항목의 값을 하나의 값으로 구분자를 중간에 두고 값을 조합해 저장하기도 합니다.
- 현재 방 ID 는 구분자를 앞에 두고 방을 생성한사람의 UID와 생성한 시점의 날짜시간값의 조합으로 되어 있습니다.
- 방 ID(roomId) 값이외에 유저리스트를 클릭하는 시점에서 방의 참여 인원의 ID(roomUserList), 방의 참여인원 이름(roomUserName), 방제목(roomTitle)값이 함께 세팅 됩니다.
- 이런 방의 기본 정보가 세팅이 되고 채팅방을 openChatRoom메소드에서 열게 됩니다.
- openChatRoom메소드에서 화면 상단 제목을 바꾸고, 메세지를 읽어드리며, 방이 open 되어있는지 상태값을 저장할 변수에 true 값을 할당하게 됩니다.
- 실질적으로 메세지를 읽어오는 loadMessageList메소드는 limitToLast 메소드를 통해서 Messages 아래 방ID 아래 하위 50개의 데이터만 데이터를 불러옵니다.
- ‘child_added’ 이벤트는 처음은 기존 데이터를 불러오고 그 다음부터는 새롭게 추가된 데이터가 있을 경우에만 데이터를 수신하는 이벤트 입니다.
- timestampToTime 메소드는 FirebaseChat클래스에 static 형태로 선언된 메세지의 timestamp 형태의 입력 시간을 우리가 읽을 수 있는 일반적인 날짜 시간 형태로 변환하는 유틸 메소드입니다.
- 데이터를 불러와 화면을 그리게되는 방식은 앞서 유저리스트를 그렸던 방식과 같이 underscore template메소드를 활용하게 됩니다.
- 코드 설명 :
/**
* 초기 필드 변수 할당
*/
FirebaseChat.prototype.init = function(){
//...생략
this.MAKEID_CHAR = '@make@';
this.DATETIME_CHAR = '@time@';
this.spTitle = document.getElementById('spTitle');
this.ulMessageList = document.getElementById('ulMessageList');
}
/**
* 유저리스트 클릭
*/
FirebaseChat.prototype.onUserListClick = function(event){
//...생략
var targetUserUid = event.currentTarget.getAttribute('data-targetUserUid');
var targetUserName = event.currentTarget.getAttribute('data-username');
this.roomTitle = targetUserName+'님';
this.roomUserlist = [targetUserUid, this.auth.currentUser.uid]; // 챗방 유저리스트
this.roomUserName = [targetUserName, this.auth.currentUser.displayName] // 챗방 유저 이름
this.roomId = this.MAKEID_CHAR + this.auth.currentUser.uid + this.DATETIME_CHAR + FirebaseChat.yyyyMMddHHmmsss();
this.openChatRoom(this.roomId, this.roomTitle); // 파라미터 추가
}
/**
* 챗방 오픈 , 메세지 로드 및 AddUserList
*/
FirebaseChat.prototype.openChatRoom = function(roomId, roomTitle){ // 파라미터 추가
this.isOpenRoom = true; // 방이 열린 상태인지 확인하는 플래그 값
if(roomTitle){ //상단 타이틀 변경
this.spTitle.innerHTML = this.roomTitle;
}
this.loadMessageList(roomId); //메세지 로드
this.tabMessageList.click();
}
/**
* 메세지 로드
*/
FirebaseChat.prototype.loadMessageList = function(roomId){
if(roomId){
this.ulMessageList.innerHTML = ''; //메세지 화면 리셋
var messageTemplate = document.getElementById('templateMessageList').innerHTML;
if(this.messageRef){ // 이전 메세지 ref 이벤트 제거
this.messageRef.off();
}
this.messageRef = this.database.ref('Messages/' + roomId);
var cbDisplayMessages = function(data) {
var messageHtml = '';
var val = data.val();
messageHtml = _.template(messageTemplate)({
key : data.key
, profileImg : val.profileImg
, userName : val.userName
, time : FirebaseChat.timestampToTime(val.timestamp)
, message : val.message
});
this.ulMessageList.innerHTML = this.ulMessageList.innerHTML + messageHtml;
this.ulMessageList.scrollTop = this.ulMessageList.scrollHeight;
this.roomTitle = val.roomTitle;
}
this.messageRef.limitToLast(50).on('child_added', cbDisplayMessages.bind(this));
}
}
/**
* 현재날짜 yyyyMMddHHmmsss형태로 반환
*/
FirebaseChat.yyyyMMddHHmmsss =function(){
var vDate = new Date();
var yyyy = vDate.getFullYear().toString();
var MM = (vDate.getMonth() + 1).toString();
var dd = vDate.getDate().toString();
var HH = vDate.getHours().toString();
var mm = vDate.getMinutes().toString();
var ss = vDate.getSeconds().toString();
var sss= vDate.getMilliseconds().toString();
return yyyy + (MM[1] ? MM : '0'+MM[0]) + (dd[1] ? dd : '0'+dd[0]) + (HH[1] ? HH : '0'+ HH[0])
+ (mm[1] ? mm : '0'+ mm[0]) + (ss[1] ? ss : '0'+ss[0])+ sss;
};
/**
* timestamp를 날짜 시간 으로 변환
*/
FirebaseChat.timestampToTime = function(timestamp){
var date = new Date(timestamp),
year = date.getFullYear(),
month = date.getMonth()+1,
day = date.getDate(),
hour = date.getHours(),
minute = date.getMinutes(),
week = new Array('일', '월', '화', '수', '목', '금', '토');
var convertDate = year + "년 "+month+"월 "+ day +"일 ("+ week[date.getDay()] +") ";
var convertHour="";
if(hour < 12){
convertHour = "오전 " + FirebaseChat.pad(hour) +":" + FirebaseChat.pad(minute);
}else if(hour === 12){
convertHour = "오후 " + FirebaseChat.pad(hour) +":" + FirebaseChat.pad(minute);
}else{
convertHour = "오후 " + FirebaseChat.pad(hour - 12) +":" + FirebaseChat.pad(minute);
}
return convertDate + convertHour;
}
/**
* 10미만 숫자 앞에 0 붙이기
*/
FirebaseChat.pad = function(n){
return n > 9 ? "" + n: "0" + n;
}