From d11a623f9f4c14e402c9aa6646999720934e1ae7 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Sun, 7 Jun 2026 00:04:03 -0400 Subject: [PATCH] fix(sync): skip CRE->CFI conversion for image-based fixed formats The CRE->CFI converter works by text search / character-offset mapping across the EPUB spine. Image-based fixed content (fixed-layout comic EPUBs, PDFs, comic archives) has no extractable text, so the conversion can never succeed and only wastes time parsing content docs while logging a failed percentage-precision result. Guard the conversion in the KOReader progress handler: when the matched media item's FormatGroup is fixed_layout or comic_archive, skip ConvertCREToStandard entirely. The incoming xpointer is left as-is so KOReader<->KOReader restore via GotoXPointer still works; the web reader restores by page index (the canonical locator for these formats). This covers fixed-layout comic EPUBs in particular: KOReader routes all EPUBs through CREngine (has_pages == false), so they send a real xpointer that passes IsCREXPointer and would otherwise trigger the doomed text extraction. Reflowable EPUBs (format_group == reflowable) still run the conversion exactly as before. --- internal/handlers/koreader.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/handlers/koreader.go b/internal/handlers/koreader.go index 438df42..e7b3461 100644 --- a/internal/handlers/koreader.go +++ b/internal/handlers/koreader.go @@ -457,6 +457,14 @@ func (h *KOReaderHandler) updateProgressForBook(c *echo.Context, deviceID pgtype mediaItem, err := h.db.GetMediaItem(ctx, mediaItemID) if err != nil { log.Printf("Bookhoard: CRE→CFI failed to get media item: %v", err) + } else if mediaItem.FormatGroup == string(wsync.FormatGroupFixedLayout) || + mediaItem.FormatGroup == string(wsync.FormatGroupComicArchive) { + // Image-based fixed content (fixed-layout comic EPUBs, PDF, + // comic archives) has no extractable text, so CRE→CFI conversion + // cannot succeed. The page index (page/total_pages) is the + // canonical locator. Keep the incoming xpointer for device-native + // restore; the web reader restores by page. + log.Printf("Bookhoard: CRE→CFI skipped for %s format", mediaItem.FormatGroup) } else if h.libraryService == nil { log.Printf("Bookhoard: CRE→CFI libraryService is nil, skipping conversion") } else {