Annotation Navigation Fix¶
Problem¶
When clicking on an annotation in the sidebar to navigate to it, the app would:
1. Navigate to the wrong page
2. Throw an error: Cannot read properties of undefined (reading 'forEach')
3. The error occurred in EPUB.js when trying to parse the CFI
Error Stack:
Uncaught TypeError: Cannot read properties of undefined (reading 'forEach')
at _EpubCFI.stepsToXpath (epubjs.js:16994:11)
at Annotations.add (epubjs.js:21580:11)
at pulse @ BookViewer.tsx:679
Root Cause¶
The "pulse" effect (yellow flash animation) was trying to add a highlight annotation immediately after navigation, but:
- Timing issue: The page hadn't fully rendered yet (only 100ms wait)
- No error handling: If the CFI couldn't be parsed, the entire function would crash
- Missing re-render: Annotations weren't being re-rendered after navigation
The CFI parser in EPUB.js expects the DOM to be fully loaded before it can find the text nodes to highlight. When we tried to add the pulse effect too quickly, the content wasn't ready.
Solution¶
1. Increased Wait Time¶
Changed from 100ms to 500ms to give the page more time to render:
2. Added Error Handling¶
Wrapped the pulse effect in try-catch blocks:
try {
rendition.annotations.add(...);
} catch (pulseError) {
logger.error('Reader', `Pulse effect error: ${pulseError}`);
// Continue to next pulse even if this one fails
pulseCount++;
if (pulseCount < maxPulses) {
setTimeout(pulse, 200);
}
}
3. Re-render Annotations¶
Added await renderAllAnnotations() after navigation to ensure all annotations are visible:
4. Added Logging¶
Added comprehensive logging to track navigation:
logger.info('Reader', `Navigating to annotation: ${cfi}`);
logger.error('Reader', `Pulse effect error: ${pulseError}`);
logger.error('Reader', `Pop effect error: ${effectError}`);
How It Works Now¶
- User clicks annotation in sidebar
- Navigate to CFI location
- Re-render all annotations to ensure they're visible
- Wait 500ms for page to fully render
- Try to add pulse effect:
- If successful: Show yellow flash 3 times
- If fails: Log error and continue (navigation still works)
- Effect is optional: Navigation works even if pulse fails
Benefits¶
- ✅ Navigation always works (even if pulse effect fails)
- ✅ Annotations are visible after navigation
- ✅ Better error handling prevents crashes
- ✅ Logging helps diagnose issues
- ✅ Graceful degradation (effect is optional)
Testing¶
# Refresh the app
# Should auto-reload with Vite
# Test:
1. Create some highlights/notes in different parts of the book
2. Open annotations sidebar (icon in top right)
3. Click on an annotation
4. Should navigate to correct location
5. Should see yellow flash effect (if page renders in time)
6. All annotations should be visible
Files Modified¶
frontend/src/components/Reader/BookViewer.tsxhandleNavigateToAnnotation()- Added error handling, logging, and increased wait time
Status¶
✅ Fixed - Annotation navigation now works reliably!