import { useRef, useEffect, type FC, useCallback, useState } from 'react' import Linkify from 'react-linkify' import useIsMounted from '../../../shared/hooks/use-is-mounted' import { loadMathJax } from '../../mathjax/load-mathjax' import { debugConsole } from '@/utils/debugging' import { Message, useChatContext } from '@/features/chat/context/chat-context' import OLButton from '@/shared/components/ol/ol-button' import { useTranslation } from 'react-i18next' import AutoExpandingTextArea from '@/shared/components/auto-expanding-text-area' const MessageContent: FC<{ content: Message['content'] messageId: Message['id'] edited: Message['edited'] }> = ({ content, messageId, edited }) => { const { t } = useTranslation() const root = useRef(null) const mounted = useIsMounted() const { idOfMessageBeingEdited, cancelMessageEdit, editMessage } = useChatContext() const [editedContent, setEditedContent] = useState(content) const editing = idOfMessageBeingEdited === messageId useEffect(() => { if (root.current) { // adds attributes to all the links generated by , required due to https://github.com/tasti/react-linkify/issues/99 for (const a of root.current.getElementsByTagName('a')) { a.setAttribute('target', '_blank') a.setAttribute('rel', 'noreferrer noopener') } // MathJax v3 typesetting loadMathJax() .then(async MathJax => { if (mounted.current) { const element = root.current try { await MathJax.typesetPromise([element]) MathJax.typesetClear([element]) } catch (error) { debugConsole.error(error) } } }) .catch(debugConsole.error) } }, [content, mounted]) const completeEdit = useCallback(() => { editMessage(messageId, editedContent) }, [editMessage, editedContent, messageId]) const handleKeyDown = useCallback( (e: React.KeyboardEvent) => { if (e.key === 'Enter') { e.preventDefault() completeEdit() } else if (e.key === 'Escape') { e.preventDefault() cancelMessageEdit() setEditedContent(content) } }, [cancelMessageEdit, completeEdit, content] ) const handleChange = useCallback( (e: React.ChangeEvent) => { setEditedContent(e.target.value) }, [] ) const handleAutoFocus = useCallback( (textarea: HTMLTextAreaElement) => textarea.select(), [] ) return editing ? ( <>
{ cancelMessageEdit() setEditedContent(content) }} > {t('cancel')} completeEdit()}> {t('save')} ) : (

{content} {edited ? ( <> {' '} ({t('edited')}) ) : null}

) } export default MessageContent