mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-05 03:02:56 +00:00
dev day #65,5
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
# Rich Text Editor Image Insertion Fix
|
||||
|
||||
**Date**: January 2025
|
||||
**Issue**: Quill.js image insertion errors and image duplication on drag
|
||||
|
||||
## Problems Fixed
|
||||
|
||||
### 1. Quill.js Emitter Error
|
||||
**Error Message**: `Uncaught TypeError: can't access property "emit", this.emitter is undefined`
|
||||
|
||||
**Root Cause**:
|
||||
- The Quill editor's internal state wasn't fully initialized when `insertEmbed` was called
|
||||
- Calling `insertEmbed` immediately after upload without ensuring the editor is ready caused the emitter to be undefined
|
||||
|
||||
**Solution**:
|
||||
```typescript
|
||||
// Insert into editor
|
||||
const quill = quillRef.current?.getEditor();
|
||||
if (quill) {
|
||||
// Ensure editor is focused and ready
|
||||
quill.focus();
|
||||
|
||||
// Use setTimeout to ensure Quill's internal state is ready
|
||||
setTimeout(() => {
|
||||
try {
|
||||
const range = quill.getSelection();
|
||||
const index = range ? range.index : quill.getLength();
|
||||
|
||||
// Insert the image with 'api' source to prevent event loops
|
||||
quill.insertEmbed(index, 'image', res.url, 'api');
|
||||
|
||||
// Move cursor after the image
|
||||
quill.setSelection(index + 1, 0, 'api');
|
||||
|
||||
// Force content change to trigger re-render
|
||||
onChangeRef.current(quill.root.innerHTML);
|
||||
|
||||
toast({ title: 'Obrázek vložen', status: 'success', duration: 2000 });
|
||||
} catch (embedError) {
|
||||
console.error('Error inserting image:', embedError);
|
||||
toast({ title: 'Chyba při vkládání obrázku', description: String(embedError), status: 'error' });
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
```
|
||||
|
||||
**Key Changes**:
|
||||
- Added `quill.focus()` before insertion to ensure the editor has focus
|
||||
- Wrapped insertion in `setTimeout(50ms)` to allow Quill's internal state to stabilize
|
||||
- Changed source parameter from `'user'` to `'api'` to prevent triggering user-initiated event handlers
|
||||
- Added try-catch block for better error handling
|
||||
- Force content update with `onChangeRef.current(quill.root.innerHTML)` to trigger re-render
|
||||
|
||||
### 2. Image Not Showing After Insertion
|
||||
**Problem**: After uploading and inserting an image, it didn't appear in the editor
|
||||
|
||||
**Solution**:
|
||||
- Added explicit `onChangeRef.current(quill.root.innerHTML)` call after insertion
|
||||
- This forces React to recognize the DOM change and re-render the component
|
||||
- The `'api'` source parameter prevents infinite loops while still triggering the necessary updates
|
||||
|
||||
### 3. Image Duplication on Drag
|
||||
**Problem**: Dragging images created duplicates due to default browser drag-and-drop behavior
|
||||
|
||||
**Solution (Multiple Layers)**:
|
||||
|
||||
#### A. Set draggable attribute on image selection
|
||||
```typescript
|
||||
const selectImage = (img: HTMLImageElement) => {
|
||||
// ... other code ...
|
||||
|
||||
// Prevent default drag behavior to avoid duplication
|
||||
img.setAttribute('draggable', 'false');
|
||||
|
||||
createResizeHandle(img);
|
||||
// ... rest of code ...
|
||||
}
|
||||
```
|
||||
|
||||
#### B. Added dragstart event listener
|
||||
```typescript
|
||||
// Prevent default drag behavior on images
|
||||
const handleDragStart = (e: DragEvent) => {
|
||||
const target = e.target as HTMLElement;
|
||||
if (target.tagName === 'IMG') {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
editor.root.addEventListener('dragstart', handleDragStart);
|
||||
```
|
||||
|
||||
#### C. Added CSS to disable drag
|
||||
```typescript
|
||||
img: {
|
||||
cursor: 'pointer',
|
||||
maxWidth: '100%',
|
||||
height: 'auto',
|
||||
display: 'block',
|
||||
margin: '12px 0',
|
||||
transition: 'all 0.2s ease',
|
||||
borderRadius: '4px',
|
||||
userSelect: 'none',
|
||||
pointerEvents: 'auto',
|
||||
WebkitUserDrag: 'none', // Disable WebKit drag
|
||||
userDrag: 'none', // Disable standard drag
|
||||
// ... hover styles ...
|
||||
}
|
||||
```
|
||||
|
||||
## Files Modified
|
||||
|
||||
### `/frontend/src/components/common/CustomRichEditor.tsx`
|
||||
|
||||
**Lines 274-301**: Image insertion with proper Quill initialization
|
||||
**Lines 523-524**: Set draggable="false" on image selection
|
||||
**Lines 735-743**: Added dragstart event handler
|
||||
**Lines 755**: Added dragstart cleanup in useEffect return
|
||||
**Lines 1146-1147**: Added CSS properties to disable drag
|
||||
|
||||
## Testing Recommendations
|
||||
|
||||
1. **Test Image Insertion**:
|
||||
- Open any admin page with rich text editor (Articles, Activities, About)
|
||||
- Click "Vložit obrázek" button
|
||||
- Upload an image and crop it
|
||||
- Verify image appears immediately in the editor
|
||||
- Check browser console for no errors
|
||||
|
||||
2. **Test Image Drag Behavior**:
|
||||
- Insert an image in the editor
|
||||
- Click to select the image (blue outline appears)
|
||||
- Try to drag the image left/right
|
||||
- Verify alignment changes but no duplicate is created
|
||||
- Verify the image doesn't create a "ghost" drag preview
|
||||
|
||||
3. **Test Image Resize**:
|
||||
- Select an image
|
||||
- Grab the blue corner/edge handles
|
||||
- Resize the image
|
||||
- Verify smooth resizing without duplication
|
||||
|
||||
4. **Test Multiple Images**:
|
||||
- Insert several images
|
||||
- Interact with each one
|
||||
- Verify no interference between images
|
||||
|
||||
## Browser Compatibility
|
||||
|
||||
The fixes use standard web APIs and should work in:
|
||||
- ✅ Chrome/Edge (Chromium-based)
|
||||
- ✅ Firefox
|
||||
- ✅ Safari (WebKit)
|
||||
|
||||
The `-webkit-user-drag` CSS property specifically targets WebKit browsers.
|
||||
|
||||
## Known Limitations
|
||||
|
||||
- The 50ms delay in image insertion is a workaround for Quill's initialization timing
|
||||
- If issues persist, the delay can be increased to 100ms, but this may cause noticeable lag
|
||||
- The drag prevention is comprehensive but may interfere with future drag-and-drop features if needed
|
||||
|
||||
## Related Files
|
||||
|
||||
- `/frontend/src/components/common/RichTextEditor.tsx` - Wrapper component
|
||||
- `/frontend/src/services/imageProcessing.ts` - Image upload/crop backend services
|
||||
- `/frontend/src/styles/custom-editor.css` - Additional editor styles
|
||||
|
||||
## Future Improvements
|
||||
|
||||
1. Consider migrating to Quill 2.0 when stable (better event handling)
|
||||
2. Add loading state during image upload to prevent multiple insertions
|
||||
3. Add image compression options in the crop modal
|
||||
4. Consider lazy loading for large images
|
||||
Reference in New Issue
Block a user