UNPKG

stream-chat-react

Version:

React components to create chat conversations or livestream style chat

79 lines (78 loc) 3.14 kB
import { useCallback, useEffect, useRef } from 'react'; import { logChatPromiseExecution } from 'stream-chat'; import { useChannelStateContext } from '../../../context/ChannelStateContext'; export const useMessageInputText = (props, state, dispatch, findAndEnqueueURLsToEnrich) => { const { channel } = useChannelStateContext('useMessageInputText'); const { additionalTextareaProps, focus, parent, publishTypingEvent = true } = props; const { text } = state; const textareaRef = useRef(undefined); // Focus useEffect(() => { if (focus && textareaRef.current) { textareaRef.current.focus(); } }, [focus]); // Text + cursor position const newCursorPosition = useRef(undefined); const insertText = useCallback((textToInsert) => { const { maxLength } = additionalTextareaProps || {}; if (!textareaRef.current) { return dispatch({ getNewText: (text) => { const updatedText = text + textToInsert; if (maxLength && updatedText.length > maxLength) { return updatedText.slice(0, maxLength); } return updatedText; }, type: 'setText', }); } const { selectionEnd, selectionStart } = textareaRef.current; newCursorPosition.current = selectionStart + textToInsert.length; dispatch({ getNewText: (prevText) => { const updatedText = prevText.slice(0, selectionStart) + textToInsert + prevText.slice(selectionEnd); if (maxLength && updatedText.length > maxLength) { return updatedText.slice(0, maxLength); } return updatedText; }, type: 'setText', }); }, // eslint-disable-next-line react-hooks/exhaustive-deps [additionalTextareaProps, newCursorPosition, textareaRef]); useEffect(() => { const textareaElement = textareaRef.current; if (textareaElement && newCursorPosition.current !== undefined) { textareaElement.selectionStart = newCursorPosition.current; textareaElement.selectionEnd = newCursorPosition.current; newCursorPosition.current = undefined; } }, [text, newCursorPosition]); const handleChange = useCallback((event) => { event.preventDefault(); if (!event || !event.target) { return; } const newText = event.target.value; dispatch({ getNewText: () => newText, type: 'setText', }); findAndEnqueueURLsToEnrich?.(newText); if (publishTypingEvent && newText && channel) { logChatPromiseExecution(channel.keystroke(parent?.id), 'start typing event'); } }, // eslint-disable-next-line react-hooks/exhaustive-deps [channel, findAndEnqueueURLsToEnrich, parent, publishTypingEvent]); return { handleChange, insertText, textareaRef, }; };