export default function ChatComposer()

in src/components/Chat/ChatComposer/ChatComposer.js [162:302]


export default function ChatComposer({ addMessage, addAttachment, onTyping, contactId, contactStatus, onTypingValidityTime, textInputRef, composerConfig }) {
  const [message, setMessage] = useState("");
  const [attachment, setAttachment] = useState(null);
  const fileInputRef = useRef(null);

  useLayoutEffect(() => {
    if (!textInputRef || !textInputRef.current || !textInputRef.current.focus) {
      return;
    }
    textInputRef.current.focus();
  }, [attachment]);

  function hasSameContent(event) {
    return event.target.innerText === message;
  }

  function onInput(event) {
    if (!event.shiftKey && event.key === KEYBOARD_KEY_CONSTANTS.ENTER) {
      event.preventDefault();
      sendMessage();

      return false;
    } else {
      if (!hasSameContent(event)) {
        throttledOnTyping();
      }
      setMessage(event.target.value);
    }

    if (event.key === KEYBOARD_KEY_CONSTANTS.DELETE || event.key === KEYBOARD_KEY_CONSTANTS.BACKSPACE) {
      if (attachment && message === "") {
        event.preventDefault();
        clearFileInput();
        return;
      }
    }
  }

  /**
   * Cancel any pending (not flushed) typing events, send the message (and attachment if applicable), and clear input bar.
   */
  function sendMessage() {
    throttledOnTyping.cancel();
    sendTextMessage(message);
    setMessage("");

    if (attachment) {
      sendAttachment();
      clearFileInput();
    }
  }

  const throttledOnTyping = useCallback(
      throttle(() => {
        onTyping().then(() => {
          console.log("CCP", "ChatComposer", "On typing event sent successfully");
        });
      }, onTypingValidityTime),
      [onTypingValidityTime]
  );

  function sendTextMessage(text) {
    if (text.trim()) {
      addMessage(contactId, { text });
    }
  }

  function onFileInput(e) {
    const file = e.target.files[0];
    setAttachment(file);
  }

  function clearFileInput() {
    setAttachment(null);
    fileInputRef.current.value = null;
  }

  function sendAttachment() {
    addAttachment(contactId, attachment);
  }

  const ariaLabel = "Type a message";
  const placeholder = attachment == null ? ariaLabel : "";

  return (
      <ChatComposerWrapper>
        {(contactStatus === CONTACT_STATUS.CONNECTED) && (
            <React.Fragment>
              {composerConfig.attachmentsEnabled &&
              <PaperClipContainer>
                <IconButton aria-label={"Attach a file"}>
                  <label htmlFor={`customer-chat-file-select-${contactId}`}>
                    <PaperClipIcon>
                      <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24">
                        <path d="M0 0h24v24H0z" fill="none"/>
                        <path d="M16.5 6v11.5c0 2.21-1.79 4-4 4s-4-1.79-4-4V5c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5v10.5c0 .55-.45 1-1 1s-1-.45-1-1V6H10v9.5c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5V5c0-2.21-1.79-4-4-4S7 2.79 7 5v12.5c0 3.04 2.46 5.5 5.5 5.5s5.5-2.46 5.5-5.5V6h-1.5z"/>
                      </svg>
                    </PaperClipIcon>
                    <input ref={fileInputRef} type="file" id={`customer-chat-file-select-${contactId}`} data-testid={`customer-chat-file-select`}
                           accept={ATTACHMENT_ACCEPT_CONTENT_TYPES.join(',')}
                           onChange={onFileInput} aria-label={"Attach a file"} tabIndex={-1}/>
                  </label>
                </IconButton>
              </PaperClipContainer>}
              {(attachment != null) && (
                  <AttachmentContainer>
                    <div>
                      <span>{attachment.name}</span>
                      <IconButton onClick={clearFileInput} aria-label={"Remove attachment"}>
                        <CloseIcon>
                          <svg viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
                            <path d="M13 1.3L11.7 0 6.5 5.2 1.3 0 0 1.3l5.2 5.2L0 11.7 1.3 13l5.2-5.2 5.2 5.2 1.3-1.3-5.2-5.2z" fillRule="evenodd"/>
                          </svg>
                        </CloseIcon>
                      </IconButton>
                    </div>
                  </AttachmentContainer>
              )}
              <TextInput
                  data-testid={`customer-chat-text-input`}
                  ref={textInputRef}
                  value={message}
                  onInput={onInput}
                  onKeyPress={onInput}
                  onKeyDown={onInput}
                  aria-label={ariaLabel}
                  placeholder={placeholder}
                  tabIndex="0"
                  spellCheck="true"
              />
              <SendMessageButtonContainer>
                <SendMessageButton
                  isActive={!!message || attachment}
                  sendMessage={sendMessage.bind(this)}
                />
              </SendMessageButtonContainer>
            </React.Fragment>
        )}
      </ChatComposerWrapper>
  );
}