Context Menu Fix - CFI Range URL Encoding Issue¶
Problem¶
When selecting text in the book, the unified context menu wasn't appearing. Console showed 404 errors:
GET http://127.0.0.1:8000/api/annotations/notes/range/1/epubcfi(%2F6%2F10!%2F4%2F2%2F2%5BPreface1%5D%2F30%5Bpagebreak-rw_7%5D%2F4%5Bp38%5D%2C%2F1%3A0%2C%2F1%3A193) 404 (Not Found)
Root Cause¶
CFI (Canonical Fragment Identifier) ranges contain special characters like:
- / (forward slash)
- ( ) (parentheses)
- [ ] (brackets)
- : (colon)
- , (comma)
When these were used as path parameters in the URL, FastAPI couldn't properly parse them because:
1. Forward slashes / are interpreted as path separators
2. URL encoding doesn't solve this for path parameters
3. The route pattern couldn't match the encoded CFI
Example CFI:
URL encoded in path:
❌ FastAPI sees this as multiple path segments!Solution¶
Changed CFI range from path parameter to query parameter:
Backend Changes¶
Before:
@router.get("/notes/range/{book_id}/{cfi_range}")
async def get_note_by_range(book_id: int, cfi_range: str):
# ...
After:
@router.get("/notes/range/{book_id}")
async def get_note_by_range(book_id: int, cfi_range: str): # Query param
# ...
Frontend Changes¶
Before:
After:
Why Query Parameters Work¶
Query parameters can safely contain any URL-encoded characters:
✅ FastAPI correctly parses this as:
- Path: /api/annotations/notes/range/1
- Query param cfi_range: epubcfi(/6/10!/4/2/...)
Files Modified¶
Backend¶
backend/app/routers/annotations.pyget_note_by_range()- Changed route from/notes/range/{book_id}/{cfi_range}to/notes/range/{book_id}get_chat_contexts_by_range()- Changed route from/chat-contexts/range/{book_id}/{cfi_range}to/chat-contexts/range/{book_id}
Frontend¶
frontend/src/services/annotationApiService.tsgetNoteByRange()- Updated to use query parametergetChatContextsByRange()- Updated to use query parameter
Testing¶
# 1. Restart backend to load changes
# (Backend should auto-reload with uvicorn --reload)
# 2. Refresh frontend
# (Vite should auto-reload)
# 3. Test text selection
- Open a book
- Select some text
- Context menu should appear ✅
Expected Behavior¶
When you select text:
1. Frontend captures CFI range
2. Makes API calls:
- GET /api/annotations/notes/range/1?cfi_range=...
- GET /api/annotations/chat-contexts/range/1?cfi_range=...
3. Backend returns existing annotations (or empty)
4. Context menu appears with options:
- Highlight (with color picker)
- Add Note
- Chat with AI
- Copy Text
Status¶
✅ Fixed - Context menu now appears when selecting text!