채팅방 읽음 처리

Jian·2022년 10월 23일
0

Firebase

목록 보기
8/9

처리해야하는 경우


  • 채팅방 목록
  • 채팅방 디테일

1. 채팅방 목록


기능 개요

(가) 렌더링되는 리스트들의 메세지 데이터에 접근한다
chatroom 컬렉션에서 리스트의 채팅방 데이터 > messages 컬렉션 내 데이터 접근.
(나) (가)에서 내가 보낸 메세지만 추려낸다
uid가 내 아이디인 것 개수 세기
(다)에서 read 필드 값이 false인 것을 찾는다

코드

전역

// 전역변수 선언 영역
var chatroomID;
var productRef = db.collection('product');
var chatroomRef = db.collection('chatroom');
// var chatMsgRef = db.collection('chatroom');
var tempListNull = `<p class="text-center text-secondary">아직 대화중인 채팅방이 없어요</p>`;

// 함수 호출 영역

findMychatList();

[ 함수: getProduct ] 채팅방 데이터 정보로 product정보 불러온다 > dom 바인딩


function getProduct(a, productID) {
  productRef
    .doc(a.data().productID)
    .get()
    .then((res) => {
      console.log('작성자: ', res.data().uid);
      console.log(res.data().content);
      const authorUID = res.data().uid;
      const productData = res.data();

      // DOM
      $('#chat-list').append(
        `
    <a href=/page/chat-detail.html?id=${productID}>
    <li class="row border-bottom py-1 px-2 align-items-center chatbox">
      <div class="col-2 px-auto">
        <img src="${productData.image}" class="chat-product-thumb product-img">
      </div>

      <div class="col-9 my-auto ps-0">
        <div class="hstack">
          <p class="m-0 fw-semibold username">${productData.username}</p>
          <p class="m-0 text-black-50"><small>∙</small></p>
          <p class="m-0 text-black-50" id="chat-date"><small></small></p>
        </div>

        <p class="m-0" id="chat-msg">${productData.username}님과 대화가 시작되었어요</p>
      </div>

      <div class="col-1 text-end my-auto">
        <div class="chat-badge unread-box">
          <p class="chat-badge-tx unread">22</p>
        </div>
      </div>

    </li>
    <a>
    `
      );
    });
}

[ 함수: findMychatList ] 채팅방 DB서 로그인 유저 UID 포함된 리스트 모두 찾는다



function findMychatList() {
  chatroomRef
    .where('who', 'array-contains', myUID)
    .get()
    .then((result) => {
      console.log(result.size);
      createList(result);
    });
}

[ 함수: createList ] 채팅방 리스트 생성 (findChatList 결과값 받아서)

function createList(a) {
  // 1) 채팅방 목록 없을 경우
  if (a.size == 0) {
    console.log('개설된 채팅방 X');
    // $('#chat-list').append(tempListNull);
    $('#empty').removeClass('d-none');
  }
  // 2) 채팅방 목록 있을 경우
  else {
    a.forEach((doc) => {
      const productID = doc.id;
      const who = doc.data().who;
      const you = findYouinChatroom(who);

      // 바인딩 함수
      getProduct(doc, productID);
      getLastChatMsg(productID);

      countUnReadMsg(productID, you).then((res) => {
        if (res == 0) {
          console.log('모두 읽음');
          $('.unread-box').last().addClass('invisible');
        } else {
          console.log('아직안읽음 :', res);
          // $('.unread').first().text(res);
          $('.unread').last().text(res);
        }
      });

      // let unreadtx = $('.unread').last();
      // console.log('unreadtx: ', unreadtx);
    });
  }
}

[ findYouinChatroom : 참여자 배열로 받아 상대방 UID 찾아냄 ]

function findYouinChatroom(part) {
  var res;
  part.map((a) => {
    if (a != myUID) {
      // console.log('상대:', a);
      res = a;
    }
  });
  return res;
}

[함수 : countUnReadMsg] 내 메세지 찾는다

var countUnReadMsg = (params, paramYou) =>
  new Promise(function (resolve) {
    var resReturn;
    console.log(params);
    // console.log(authorUID);
    console.log(myUID);
    chatroomRef
      .doc(params)
      .collection('messages')
      .where('uid', '==', paramYou)
      .where('read', '==', false)
      .get()
      .then((res) => {
        console.log('읽지않은 상대 메세지 개수 :', res.size);
        // 읽지않은 메세지 수 반환
        resReturn = res.size;
        console.log('resReturn:', resReturn);
        resolve(resReturn);
      });
  });

문제상황 : 상대방의 UID 알아내는 문제

'내 UID가 아닌 것' 명령 줄 때 != 사용하려 했으나
복합쿼리(where)를 연달아 사용할 때, '!=' 연산자는 사용 못함. (할 수 있더라도 DB에 사전 작업 해두어야 함)
해결
이전 체이닝된 함수에서 상대 UID알아내어 이 함수에 전달한다.

2. 채팅방 디테일


기능 개요

읽음 여부 해당 채팅 메세지 도큐먼트 내의 read필드에 저장, 기본값 false.
해당 메세지 가져오면 true로 변경. (읽은 유저가 본인일 경우에는 제외)

코드

메세지 생성 함수. 여기서 메세지 발신 주체 구분한다

function createDOM() {
db.collection('chatroom')
.doc(chatroomID)
.collection('messages')
.orderBy('date')
.onSnapshot((doc) => {
// DB 데이터로 DOM 생성하기 전에 내용 비워준다.

$('#wrap').html('');

doc.forEach((a) => {
let datejs = dayjs(a.data().date.toDate());
var temp = `
<li class="d-flex flex-row-reverse align-items-end my-3">
  <span class="chat-box mine ms-1">${a.data().content}</span>
  <span class="tx-small text-end">
    ${datejs.format('M월D일 HH:mm')}
  </span>
</li>
`;
if (a.data().uid == myUID) {
  console.log('내메세지');
  $('#wrap').append(temp);
} else {
  console.log('상대메세지');
  console.log('메세지 id', a.id);

  changeRead(a);

  $('img').attr('src', '');
  $('#wrap').append(`
      <li class="d-flex flex-row align-items-end my-3">

          <img src=""/>
        </div>

        <span class="chat-box me-1">${a.data().content}</span>
        <span class="tx-small">
          ${datejs.format('M월D일 HH:mm')}
        </span>
      </li>
    `);
}
});
// DOM 생성완료 후 스크롤을 최하단으로 내린다
scrollBottom();
});
}

메세지 발신 주체 따라 읽음 처리하는 함수

function changeRead(params) {
  chatroomRef
    .doc(chatroomID)
    .collection('messages')
    .doc(params.id)
    .update({ read: true })
    .then(() => {
      console.log('읽음 updated');
    });
}

읽음 여부 따라 1 UI 다르게 처리 한다

doc.forEach((a) => {
  let datejs = dayjs(a.data().date.toDate());
  var temp = `
  <li class="d-flex flex-row-reverse align-items-end my-3">
    <span class="chat-box mine ms-1">${a.data().content}</span>
    <div>
      <p  class="text-danger fw-semibold text-end mb-0 read"
      style="font-size: .8rem; line-height: 0;">1</p>
      <span class="tx-small text-end">
        ${datejs.format('M월D일 HH:mm')}
      </span>
    </div>
  </li>
  `;
  if (a.data().uid == myUID) {
    console.log('내메세지');
    $('#wrap').append(temp);

    if (a.data().read == true) {
      console.log('읽음');
      $('.read').addClass('d-none');
    }
  } else {
    console.log('상대메세지');
    console.log('메세지 id', a.id);

    changeRead(a);

    $('img').attr('src', '');
    $('#wrap').append(`
        <li class="d-flex flex-row align-items-end my-3">

            <img src=""/>
          </div>

          <span class="chat-box me-1">${a.data().content}</span>
          <span class="tx-small">
            ${datejs.format('M월D일 HH:mm')}
          </span>
        </li>
      `);
  }
});
// DOM 생성완료 후 스크롤을 최하단으로 내린다
scrollBottom();
});
}
profile
개발 블로그

0개의 댓글