From 6805d0b66db472e0397cc769c5b4ca2d4ddf9340 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Mon, 6 Apr 2026 17:01:05 -0400 Subject: [PATCH] fix(ebook-reader): load SVG images and fix progress update ID - Add SVG image support: process elements in addition to HTML tags for cover pages and embedded images - Fix progress update: use 'id' from API response instead of 'media_item_id' which the backend never returns for this endpoint - Update reader context interfaces to include currentPage field - Add debug logging for all resource keys to help troubleshoot image loading issues in future epubs --- web/src/reader/core/reader-context.ts | 6 ++++- web/src/reader/core/reader-navigation.ts | 34 +++++++++++++++--------- web/src/reader/core/reader-state.ts | 2 +- web/src/types/reader.d.ts | 2 +- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/web/src/reader/core/reader-context.ts b/web/src/reader/core/reader-context.ts index f6fecdf..9ee3ee7 100644 --- a/web/src/reader/core/reader-context.ts +++ b/web/src/reader/core/reader-context.ts @@ -28,7 +28,11 @@ interface MangaReader { readingDirection: "rtl" | "vertical"; } -type CurrentReader = UniversalReader | PDFReader | ComicReader | MangaReader; +export type CurrentReader = + | UniversalReader + | PDFReader + | ComicReader + | MangaReader; export interface ReaderContext { getState: () => { diff --git a/web/src/reader/core/reader-navigation.ts b/web/src/reader/core/reader-navigation.ts index 13ac6ed..9bd44a7 100644 --- a/web/src/reader/core/reader-navigation.ts +++ b/web/src/reader/core/reader-navigation.ts @@ -279,6 +279,7 @@ export async function renderSpineItem() { if (!container || !spineItem) return; // Get the actual content from resources using the href const resources = state.currentReader.cif.resources; + console.log("ALL resource keys:", Array.from(resources.keys())); const contentBlob = resources?.get(spineItem.content); if (!contentBlob) { // Fallback: try to fetch directly if not in resources @@ -326,16 +327,11 @@ export async function renderSpineItem() { // Rewrite image src paths to use blob URLs from resources const modifiedContent = rewriteImageUrls(contentText, resources); - const images = modifiedContent.match(/]+>/g); - console.log("Found images in content:", images); - // Test resource lookup - console.log("Trying to find image:", { - direct: resources.get("image/1.png"), - withoutFolder: resources.get("1.png"), - allImageKeys: Array.from(resources.keys()).filter( - (k: string) => k.includes("image") || k.includes("png"), - ), - }); + const htmlImages = modifiedContent.match(/]+>/g); + const svgImages = + modifiedContent.match(/]+xlink:href="([^"]+)"[^>]*>/gi) || []; + const allImages = [...htmlImages, ...svgImages]; + console.log("Found images in content:", allImages); // Parse HTML and process images BEFORE setting innerHTML const parser = new DOMParser(); @@ -354,6 +350,20 @@ export async function renderSpineItem() { img.setAttribute("src", blobUrl); } } + + // Process SVG elements with xlink:href + const svgImgElements = Array.from(doc.querySelectorAll("image")); + for (const img of svgImgElements) { + const src = img.getAttribute("xlink:href"); + if (!src) continue; + + let blob = findImageInResources(resources, src); + if (blob) { + const blobUrl = URL.createObjectURL(blob); + img.setAttribute("xlink:href", blobUrl); + } + } + container.innerHTML = doc.body.innerHTML; // Apply reader styling applyReaderTheme(); @@ -498,7 +508,7 @@ function sendProgressUpdate() { if (!state.currentReader || !state.readerMetadata) return; const mediaItemId = - state.readerMetadata.media_item_id || + state.readerMetadata.id || document.body.dataset.mediaItemId || window.location.pathname.split("/").pop(); @@ -541,7 +551,7 @@ function sendProgressUpdate() { const percentage = totalPages > 0 ? (currentPage / totalPages) * 100 : 0; updateReadingProgress( - state.readerMetadata.media_item_id, + state.readerMetadata.id, { current_page: currentPage, total_pages: totalPages, diff --git a/web/src/reader/core/reader-state.ts b/web/src/reader/core/reader-state.ts index fad3e9c..8f1fa39 100644 --- a/web/src/reader/core/reader-state.ts +++ b/web/src/reader/core/reader-state.ts @@ -1,4 +1,4 @@ -import type { ReaderMetadata, ReaderState } from "./reader-context"; +import type { ReaderState } from "./reader-context"; type CurrentReader = import("./reader-context").CurrentReader; diff --git a/web/src/types/reader.d.ts b/web/src/types/reader.d.ts index c1e6ab7..77389b4 100644 --- a/web/src/types/reader.d.ts +++ b/web/src/types/reader.d.ts @@ -72,7 +72,7 @@ interface ParserCapabilities { // ============================================================ interface ReaderMetadata { - media_item_id: string; + id: string; title: string; author: string; cover_image_path: string;