import React, { useState, useEffect, useRef } from 'react' import Icon from './Icon' import Button from './Button' import UploadButton from './UploadButton' import toast from 'react-hot-toast' /** * StackOverflow-driven development: https://stackoverflow.com/a/10158364/1097384 * @param {HTMLTextAreaElement & {createTextRange?: Function}} el element */ function moveCaretToEnd(el) { if (typeof el.selectionStart == 'number') { el.selectionStart = el.selectionEnd = el.value.length } else if (typeof el.createTextRange != 'undefined') { // Internet Explorer el.focus() var range = el.createTextRange() range.collapse(false) range.select() } } /** @external Promise */ /** * @typedef {object} MessageInputProps * @property {string} text text * @property {function({body:string, attach:string | File}):Promise} onSend onSend * @property {number=} rows rows * @property {string=} placeholder placeholder */ /** * MessageInput * @param {React.ComponentProps & MessageInputProps} props props */ export default function MessageInput({ text, rows, placeholder, onSend }) { /** * @type {React.MutableRefObject} */ let textareaRef = useRef(null) /** * @type {React.MutableRefObject} */ let fileinput = useRef(null) let updateFocus = () => { const isDesktop = window.matchMedia('(min-width: 62.5rem)') if (isDesktop.matches) { const textarea = textareaRef.current if (textarea) { textarea.focus() moveCaretToEnd(textarea) } } } useEffect(() => { textChanged({ target: { value: text } }) updateFocus() }, [text]) let [body, setBody] = useState(text) let handleCtrlEnter = (event) => { if (event.ctrlKey && (event.charCode == 10 || event.charCode == 13)) { onSubmit({}) } } const textChanged = (event) => { setBody(event.target.value) const el = textareaRef.current if (el) { const offset = el.offsetHeight - el.clientHeight const height = el.scrollHeight + offset el.style.height = `${height + offset}px` } } const [attach, setAttach] = useState('') let uploadValueChanged = (attach) => { setAttach(attach) } let onSubmit = (event) => { if (event.preventDefault) { event.preventDefault() } const input = fileinput.current if (input && input.files) { onSend({ body: body, attach: attach ? input.files[0] : '' }).then((success) => { if (success) { setAttach('') setBody('') if (textareaRef.current) { textareaRef.current.style.height = '' } updateFocus() } else { toast('Can not update this message') } }).catch(console.log) } } return (