fix bug quileditor

This commit is contained in:
hamid zarghami
2025-11-10 11:35:31 +03:30
parent 45a4a9e561
commit 5fcc98486f
+53 -45
View File
@@ -1,4 +1,4 @@
import { FC, useEffect, useRef } from 'react' import { FC, useCallback, useEffect, useRef } from 'react'
import Quill from 'quill' import Quill from 'quill'
import VideoBlot, { getEmbedUrl } from './VideoBlot' import VideoBlot, { getEmbedUrl } from './VideoBlot'
import 'quill/dist/quill.snow.css' import 'quill/dist/quill.snow.css'
@@ -27,57 +27,62 @@ const QuillEditor: FC<QuillEditorProps> = ({
}) => { }) => {
const editorRef = useRef<HTMLDivElement>(null) const editorRef = useRef<HTMLDivElement>(null)
const quillRef = useRef<Quill | null>(null) const quillRef = useRef<Quill | null>(null)
const defaultAltTextRef = useRef(defaultAltText)
const onChangeRef = useRef(onChange)
useEffect(() => { useEffect(() => {
if (!editorRef.current) return defaultAltTextRef.current = defaultAltText || 'تصویر'
}, [defaultAltText])
// تابع سفارشی برای مدیریت آپلود تصویر useEffect(() => {
const imageHandler = () => { onChangeRef.current = onChange
const input = document.createElement('input') }, [onChange])
input.setAttribute('type', 'file')
input.setAttribute('accept', 'image/*')
input.click()
input.onchange = async () => { const imageHandler = useCallback(() => {
const file = input.files?.[0] const input = document.createElement('input')
if (file && quillRef.current) { input.setAttribute('type', 'file')
// درخواست alt text از کاربر input.setAttribute('accept', 'image/*')
const altText = prompt('متن جایگزین (Alt Text) تصویر را وارد کنید:', defaultAltText) input.click()
if (altText !== null) { // اگر کاربر Cancel نکرد input.onchange = async () => {
const reader = new FileReader() const file = input.files?.[0]
reader.onload = (e) => { if (file && quillRef.current) {
const imageUrl = e.target?.result as string const altText = prompt('متن جایگزین (Alt Text) تصویر را وارد کنید:', defaultAltTextRef.current)
const range = quillRef.current?.getSelection(true)
if (range && quillRef.current) { if (altText !== null) {
// درج تصویر const reader = new FileReader()
quillRef.current.insertEmbed(range.index, 'image', imageUrl) reader.onload = (e) => {
const imageUrl = e.target?.result as string
const range = quillRef.current?.getSelection(true)
// اضافه کردن alt text به تصویر if (range && quillRef.current) {
setTimeout(() => { quillRef.current.insertEmbed(range.index, 'image', imageUrl)
const images = quillRef.current?.root.querySelectorAll('img')
if (images && images.length > 0) {
const lastImage = images[images.length - 1]
lastImage.setAttribute('alt', altText || defaultAltText)
}
// فراخوانی onChange برای ذخیره تغییرات setTimeout(() => {
if (quillRef.current) { const images = quillRef.current?.root.querySelectorAll('img')
onChange?.(quillRef.current.root.innerHTML) if (images && images.length > 0) {
} const lastImage = images[images.length - 1]
}, 0) 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 = [ const toolbarOptions = [
['bold', 'italic', 'underline'], ['bold', 'italic', 'underline'],
[{ 'header': 1 }, { 'header': 2 }, { 'header': 3 }], [{ 'header': 1 }, { 'header': 2 }, { 'header': 3 }],
@@ -102,25 +107,28 @@ const QuillEditor: FC<QuillEditorProps> = ({
} }
}) })
// تنظیم محتوای اولیه
if (value) { if (value) {
quill.root.innerHTML = value quill.clipboard.dangerouslyPasteHTML(value)
} }
// مدیریت تغییرات const handleTextChange = () => {
quill.on('text-change', () => {
const html = quill.root.innerHTML const html = quill.root.innerHTML
onChange?.(html) onChangeRef.current?.(html)
}) }
quill.on('text-change', handleTextChange)
quillRef.current = quill quillRef.current = quill
return () => { return () => {
quill.off('text-change', handleTextChange)
quillRef.current = null quillRef.current = null
if (editorRef.current) {
editorRef.current.innerHTML = ''
}
} }
}, [placeholder, defaultAltText]) }, [imageHandler, placeholder, value])
// بروزرسانی محتوا از خارج
useEffect(() => { useEffect(() => {
if (quillRef.current && value !== quillRef.current.root.innerHTML) { if (quillRef.current && value !== quillRef.current.root.innerHTML) {
quillRef.current.root.innerHTML = value quillRef.current.root.innerHTML = value