Spaces:
Running
Running
Revision Notes Preact Overhaul
Overview
Complete rewrite of the revision notes/annotation system using Preact (no build setup) with modern features and improved UX.
New Features
1. Image Upload & Reference Panel
- Drag & drop image upload
- Multiple reference images support
- Image grid with selection
- Upload from file browser
2. Enhanced Toolbar
- Modern glassmorphism design
- Tool selection: Pen, Marker, Eraser
- Color picker with 6 colors
- Adjustable brush size (1-30)
- Undo functionality
- Clear all with confirmation
3. History Panel
- Visual history states
- Click to restore any previous state
- Up to 30 states stored
4. Improved Drawing
- Unified pointer events (mouse, touch, pen)
- Smooth stroke rendering
- Pressure-sensitive stylus support (where available)
- Optimized canvas performance
5. Responsive Design
- Full-screen modal
- Mobile-friendly touch controls
- Adaptive layout
File Structure
templates/
βββ _revision_notes_preact.html # New Preact-based notes modal
βββ question_entry_v2.html # Updated to use new notes
image_routes.py # Added upload endpoint
Routes
Existing (Unchanged)
/save_note_json- Save annotations/get_note_json/<image_id>- Load annotations/delete_note- Delete note/toggle_note_in_pdf- Include/exclude from PDF
New
/upload_note_reference- Upload reference images
Usage
Opening the Notes Editor
openNotesModal(imageId, refImageUrl, sessionId, csrfToken);
Example Button
<button onclick="openNotesModal('{{ image.id }}', '/image/processed/{{ image.processed_filename }}', '{{ session_id }}', '{{ csrf_token() }}')">
<i class="bi bi-pencil"></i> Edit Notes
</button>
Component Architecture
Main Components
NotesEditor- Main canvas and toolbarToolButton- Reusable tool buttonColorPicker- Color selectionReferencePanel- Image upload & referencesHistoryPanel- Undo history
State Management
Uses Preact hooks (useState, useEffect, useCallback) for reactive state.
Technical Details
Canvas Optimization
// Will-read-frequently for better performance
const ctx = canvas.getContext('2d', { willReadFrequently: false });
// Smooth rendering
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.imageSmoothingEnabled = true;
Pointer Events
Unified handling for all input types:
canvas.onpointerdown = handlePointerDown;
canvas.onpointermove = handlePointerMove;
canvas.onpointerup = handlePointerUp;
Tool Modes
| Tool | Behavior | Opacity |
|---|---|---|
| Pen | Solid line | 100% |
| Marker | Thick line | 35% |
| Eraser | Large eraser | 100% |
Migration from Old System
Old Code
{% include '_revision_notes.html' %}
<script>
window.openNotesModal = function(id, ref) { ... };
</script>
New Code
{% include '_revision_notes_preact.html' %}
<!-- Global functions automatically available -->
Performance Improvements
- Faster rendering - Preact virtual DOM
- Optimized canvas - Reduced redraws
- Lazy loading - Images loaded on demand
- Efficient history - Max 30 states, auto-cleanup
Browser Support
- Chrome/Edge (recommended)
- Firefox
- Safari
- Mobile browsers (touch-optimized)
Future Enhancements
- Text annotations
- Shape tools (rectangle, circle, arrow)
- Freehand highlighter
- Export annotations as PDF
- Collaborative editing
- Voice notes
- OCR from reference images
Testing
Test the following scenarios:
Basic Drawing
- Pen tool with different colors
- Marker transparency
- Eraser functionality
Image Upload
- Drag & drop
- File browser
- Multiple images
History
- Undo multiple times
- Restore old states
Save/Load
- Save annotations
- Reload page
- Verify persistence
Mobile
- Touch drawing
- Responsive layout
- Reference panel
Troubleshooting
Canvas not drawing
- Check browser console for errors
- Verify Preact loaded from CDN
- Ensure container has dimensions
Images not uploading
- Check file size limits
- Verify TEMP_FOLDER permissions
- Check CSRF token
History not working
- Ensure saveState() called after each stroke
- Check history array length
Credits
Built with: