본문 바로가기

Project/sendbird를 활용한 웹 채팅

[Sendbird를 활용한 웹 채팅] 9. 채팅 페이지 - 메세지 송수신, UI, 파일 다운로드

반응형

1. 채팅 메세지 불러오는 프로세스

채팅 페이지(Pages/Chatting.js)는

  • 채팅 리스트에서 하나의 채팅 방을 클릭하면 이동하는 페이지이다. 
  • 페이지의 도메인은 유니크하며 채팅 url(url)오픈채팅여부(isopen)의 정보가 담겨있다.

 

프로세스

  1. 페이지 주소를 통해 채팅 url과 오픈 채팅 여부를 판단
  2. getChannel 호출
    • 채널 정보 저장
    • getMessageList 호출
    • 오픈 채팅인 경우 enter, 그룹 채팅인 경우 markAsRead 이벤트 수행
  3. getMessageList 호출
    • 메세지 리스트 저장
    • scrollToBottom 호출

 

메세지 수신 이벤트

채팅 페이지에 들어와 있을 때 도착하는 메세지에 대한 이벤트 설정

->채팅방에 있을 때 새로고침없이 전달된 채팅 출력

  sb.onMessageReceivedHandler({
    handler: (channel, message) => {
      if (chatUrl === message.channelUrl) {
        setMessageList([...messageList, message]);
        scrollToBottom();
        if (!isOpenChannel) sb.markAsRead(channel);
      }
    },
  });

 

 

채팅 창 스크롤 제어

scrollToBottom

  const scrollToBottom = useCallback(() => {
    const msgWrapEl = document.getElementById("message-wrap");
    msgWrapEl.scrollTop = msgWrapEl.scrollHeight;
  }, []);

 

2. 메세지 보내기

텍스트 메세지

  const onChangemessage = (e) => {
    setMessage(e.target.value);
  };

  const onClickSubmit = () => {
    setMessage("");
    sb.sendUserMessage({
      channel,
      message,
      handler: (message, error) => {
        if (error) return;
        if (chatUrl === message.channelUrl) {
          setMessageList([...messageList, message]);
          scrollToBottom();
        }
      },
    });
  };

 

파일 메세지

  const onChangeFile = (e) => {
    const file = e.target.files[0];
    const thumbnailSizes = [{ maxWidth: 100, maxHeight: 100 }];
    sb.sendFileMessage({
      channel,
      file,
      thumbnailSizes,
      handler: (message, error) => {
        if (error) return;
        if (chatUrl === message.channelUrl) {
          setMessageList([...messageList, message]);
          scrollToBottom();
        }
      },
    });
  };

 

[시행착오]

🔒문제

오픈 채팅 페이지에서 sendUserMessage 메서드를 통해 메세지 보내기 시도 → not a member 에러 발생

🔑해결

메세지를 보내기 전에 해당 채널에 입장을 해야한다. 입장을 우선해야 메세지를 보낼 수 있다!

즉, 오픈 채팅에서 메세지를 보내는 방법은,

  1. getChannel
  2. enter
  3. sendUserMessage

cf. 그룹 채팅에서는 해당하지 않는다.

 

3. 채팅 UI 구성하기

Flex Box 안에서 아래로 정렬하는 방법

Body(빨간부분) 안에서 MessageWrap(파란부분)을 아래쪽으로 정렬하는 방법

<Body>
  <MessageWrap>
    <MessageDate>2021.07.10</MessageDate>
    <MessageList messageList={messageList} />
  </MessageWrap>
</Body>
const Body = styled.div`
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  height: 500px;
  border: 2px solid red;
`;

const MessageWrap = styled.div`
  display: flex;
  flex-direction: column;
  border: 2px solid blue;
`;

-> justify-content: flex-end를 사용하면 부모 영역을 기준으로 자식을 끝으로 정렬시킬 수 있다.

 

텍스트 사이즈 조절

🔒 문제

텍스트가 div 안에 있지 않고 밖으로 나가는 문제 발생

🔑 해결

해당 div의 style에 아래 설정을 추가해준다.

word-break: break-all;

 

 

Timestamps (feat. Unix Time)

센드버드에서 넘어오는 날짜의 데이터의 값은 우리가 일상적으로 보는 날짜와 형식이 다르다. 아래 링크를 참고해 원하는 포멧으로 변경해주면 된다.

 

최종 UI

    <Layout history={history} title={channel.name}>
      <Body>
        <MessageWrap id="message-wrap">
          <MessageList messageList={messageList} />
        </MessageWrap>
      </Body>
      <FooterWrap>
        <Footer>
          <FileWrap>
            <Label htmlFor="file">
              <img src={AddIcon} alt="addFile" />
            </Label>
            <FileInput id="file" type="file" onChange={onChangeFile} />
          </FileWrap>
          <Message
            id="message"
            type="text"
            value={message}
            placeholder="메세지를 입력하세요"
            onChange={onChangemessage}
            onKeyPress={onKeyPress}
          />
          <Btn onClick={onClickSubmit}></Btn>
        </Footer>
      </FooterWrap>
    </Layout>

 

4. 파일 다운로드

  const onClickDownload = async () => {
    const image = await fetch(message.url);
    const imageBlob = await image.blob();
    const imageUrl = URL.createObjectURL(imageBlob);

    const link = document.createElement("a");
    link.href = imageUrl;
    link.download = `${message.name}`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };

 

Reference

반응형