diff --git a/src/components/QuillEditor.tsx b/src/components/QuillEditor.tsx index c38e1d7..f8a55fd 100644 --- a/src/components/QuillEditor.tsx +++ b/src/components/QuillEditor.tsx @@ -1,4 +1,4 @@ -import { FC, useEffect, useRef } from 'react' +import { FC, useCallback, useEffect, useRef } from 'react' import Quill from 'quill' import VideoBlot, { getEmbedUrl } from './VideoBlot' import 'quill/dist/quill.snow.css' @@ -27,57 +27,62 @@ const QuillEditor: FC = ({ }) => { const editorRef = useRef(null) const quillRef = useRef(null) + const defaultAltTextRef = useRef(defaultAltText) + const onChangeRef = useRef(onChange) useEffect(() => { - if (!editorRef.current) return + defaultAltTextRef.current = defaultAltText || 'تصویر' + }, [defaultAltText]) - // تابع سفارشی برای مدیریت آپلود تصویر - const imageHandler = () => { - const input = document.createElement('input') - input.setAttribute('type', 'file') - input.setAttribute('accept', 'image/*') - input.click() + useEffect(() => { + onChangeRef.current = onChange + }, [onChange]) - input.onchange = async () => { - const file = input.files?.[0] - if (file && quillRef.current) { - // درخواست alt text از کاربر - const altText = prompt('متن جایگزین (Alt Text) تصویر را وارد کنید:', defaultAltText) + const imageHandler = useCallback(() => { + const input = document.createElement('input') + input.setAttribute('type', 'file') + input.setAttribute('accept', 'image/*') + input.click() - if (altText !== null) { // اگر کاربر Cancel نکرد - const reader = new FileReader() - reader.onload = (e) => { - const imageUrl = e.target?.result as string - const range = quillRef.current?.getSelection(true) + input.onchange = async () => { + const file = input.files?.[0] + if (file && quillRef.current) { + const altText = prompt('متن جایگزین (Alt Text) تصویر را وارد کنید:', defaultAltTextRef.current) - if (range && quillRef.current) { - // درج تصویر - quillRef.current.insertEmbed(range.index, 'image', imageUrl) + if (altText !== null) { + const reader = new FileReader() + reader.onload = (e) => { + const imageUrl = e.target?.result as string + const range = quillRef.current?.getSelection(true) - // اضافه کردن alt text به تصویر - setTimeout(() => { - const images = quillRef.current?.root.querySelectorAll('img') - if (images && images.length > 0) { - const lastImage = images[images.length - 1] - lastImage.setAttribute('alt', altText || defaultAltText) - } + if (range && quillRef.current) { + quillRef.current.insertEmbed(range.index, 'image', imageUrl) - // فراخوانی onChange برای ذخیره تغییرات - if (quillRef.current) { - onChange?.(quillRef.current.root.innerHTML) - } - }, 0) + setTimeout(() => { + const images = quillRef.current?.root.querySelectorAll('img') + if (images && images.length > 0) { + const lastImage = images[images.length - 1] + const cleanedAlt = altText.trim() + lastImage.setAttribute('alt', cleanedAlt || defaultAltTextRef.current) + } - quillRef.current.setSelection(range.index + 1) - } + if (quillRef.current) { + onChangeRef.current?.(quillRef.current.root.innerHTML) + } + }, 0) + + quillRef.current.setSelection(range.index + 1) } - reader.readAsDataURL(file) } + reader.readAsDataURL(file) } } } + }, []) + + useEffect(() => { + if (!editorRef.current || quillRef.current) return - // پیکربندی toolbar سفارشی const toolbarOptions = [ ['bold', 'italic', 'underline'], [{ 'header': 1 }, { 'header': 2 }, { 'header': 3 }], @@ -102,25 +107,28 @@ const QuillEditor: FC = ({ } }) - // تنظیم محتوای اولیه if (value) { - quill.root.innerHTML = value + quill.clipboard.dangerouslyPasteHTML(value) } - // مدیریت تغییرات - quill.on('text-change', () => { + const handleTextChange = () => { const html = quill.root.innerHTML - onChange?.(html) - }) + onChangeRef.current?.(html) + } + + quill.on('text-change', handleTextChange) quillRef.current = quill return () => { + quill.off('text-change', handleTextChange) quillRef.current = null + if (editorRef.current) { + editorRef.current.innerHTML = '' + } } - }, [placeholder, defaultAltText]) + }, [imageHandler, placeholder, value]) - // بروزرسانی محتوا از خارج useEffect(() => { if (quillRef.current && value !== quillRef.current.root.innerHTML) { quillRef.current.root.innerHTML = value