Skip to content

feat(reader): add document mode to the PDF viewer, overhaul PDF viewer, add different modes to CBX viewer#306

Merged
balazs-szucs merged 3 commits intogrimmory-tools:developfrom
balazs-szucs:reader-overhaul
Mar 31, 2026
Merged

feat(reader): add document mode to the PDF viewer, overhaul PDF viewer, add different modes to CBX viewer#306
balazs-szucs merged 3 commits intogrimmory-tools:developfrom
balazs-szucs:reader-overhaul

Conversation

@balazs-szucs
Copy link
Copy Markdown
Member

@balazs-szucs balazs-szucs commented Mar 31, 2026

Description

Linked Issue: Fixes #

Changes

This pull request introduces several enhancements and fixes to both the backend and frontend of the Booklore project, focusing on improved PDF/CBX handling, user settings, and support for new features in the document viewer. Notably, it adds support for dark theme preferences in PDF viewing, allows book content replacement via API, exposes CBX page dimensions, and updates default viewer settings. There are also infrastructure updates for WASM-based PDF rendering and some frontend dependency/configuration changes.

Backend Enhancements:

PDF and CBX Viewer Improvements

  • Added a new boolean field isDarkTheme to PDF viewer preferences (including database migration, DTO, entity, and service layer updates) to support dark mode in the PDF viewer.
  • Introduced an endpoint and service logic to retrieve page dimensions (width, height, wide flag) for CBX books, including the new DTO CbxPageDimension.

Book Content Management

  • Added a new API endpoint and service method to allow replacing the primary PDF file for a book, enabling document viewer annotation changes to be persisted.

Viewer Settings and Defaults

  • Changed the default PDF viewer page spread from 'odd' to 'off' (single page view), including a migration to update user and per-book settings.
  • Extended the CbxPageScrollMode enum to include a LONG_STRIP mode.

Security and WASM Support

  • Added a servlet filter to set Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers, required for WASM-based PDF rendering (pdfium).

Frontend and Infrastructure:

PDFium and WASM Integration

  • Added @embedpdf/pdfium and @embedpdf/snippet as dependencies, and updated Angular build configuration to copy their assets and set required cross-origin headers during development.

User Settings and Filters

  • Refactored the BookFilterComponent to use a reactive effect for user settings, simplifying the subscription logic.
  • Updated the PdfViewerSetting interface to include the new isDarkTheme property.
  • Minor import fix for CBX page split option.

Yarn and Package Management

  • Updated .yarnrc.yml to configure node linker and caching strategy for the frontend project.

Most important changes:

PDF/CBX Viewer Features:

  • Added dark theme support for PDF viewer preferences across backend, database, and frontend.
  • Added endpoint and logic to retrieve CBX page dimensions, with a new DTO and service method.
    Book Content API:
  • Implemented a new API and service for replacing book content (PDF file), enabling annotation persistence.

Viewer Defaults and Enums:

  • Changed default PDF page spread from 'odd' to 'off' (single page view) and migrated existing settings; added LONG_STRIP to CBX scroll modes

WASM/PDFium Support:

  • Added a servlet filter and Angular dev server headers for Cross-Origin isolation, and included pdfium/embedpdf assets and dependencies for WASM-based PDF rendering.

Frontend Refactors:

  • Refactored user settings effect in BookFilterComponent for improved reactivity and maintainability.

Summary by CodeRabbit

Release Notes

  • New Features
    • Added PDF reader dark theme toggle and fullscreen mode.
    • Added PDF document viewer mode for enhanced compatibility.
    • Added Comic reader brightness control, book-emulation mode (with spine effect), and click-to-paginate navigation.
    • Added Comic reader long-strip (webtoon) reading mode with automatic page dimension detection.
    • Added eBook reader immersive mode for distraction-free fullscreen reading.
    • Added screen wake lock support to prevent display sleep during reading sessions.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2fdc5683-9292-4fc4-b107-aa6076f7eae0

📥 Commits

Reviewing files that changed from the base of the PR and between 40123ee and 58e1650.

⛔ Files ignored due to path filters (1)
  • frontend/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (14)
  • booklore-api/src/main/java/org/booklore/model/enums/CbxPageScrollMode.java
  • frontend/package.json
  • frontend/src/app/features/readers/cbx-reader/cbx-reader.component.html
  • frontend/src/app/features/readers/cbx-reader/cbx-reader.component.scss
  • frontend/src/app/features/readers/cbx-reader/cbx-reader.component.ts
  • frontend/src/app/features/readers/cbx-reader/core/cbx-page-dimension.service.ts
  • frontend/src/app/features/readers/cbx-reader/layout/quick-settings/cbx-quick-settings.component.html
  • frontend/src/app/features/readers/cbx-reader/layout/quick-settings/cbx-quick-settings.component.ts
  • frontend/src/app/features/readers/cbx-reader/layout/quick-settings/cbx-quick-settings.service.spec.ts
  • frontend/src/app/features/readers/pdf-reader/pdf-reader.component.scss
  • frontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts
  • frontend/src/app/features/settings/reader-preferences/cbx-reader-preferences/cbx-reader-preferences-component.ts
  • frontend/src/app/features/settings/user-management/user.service.ts
  • frontend/src/assets/embedpdf-frame.html

📝 Walkthrough

Walkthrough

This PR adds comprehensive multimedia viewer enhancements across the application. Backend changes introduce dark theme support for PDF viewers, a book content replacement endpoint, and CBX page dimension retrieval. Frontend changes include a canvas-based CBX renderer with brightness control and book-emulation mode, PDF viewer dark theme and fullscreen capabilities with an EmbedPDF document mode, ebook reader immersive mode, and a wake-lock service. Database migrations update PDF preferences schema and change spread-mode defaults.

Changes

Cohort / File(s) Summary
Backend Security & Endpoints
booklore-api/src/main/java/org/booklore/config/security/filter/SharedArrayBufferHeaderFilter.java, booklore-api/src/main/java/org/booklore/controller/BookController.java
Added OncePerRequestFilter to set COOP/COEP headers. Added PUT /api/v1/books/{bookId}/content endpoint for book content replacement.
CBX Reader Backend Support
booklore-api/src/main/java/org/booklore/controller/CbxReaderController.java, booklore-api/src/main/java/org/booklore/service/reader/CbxReaderService.java
Added GET /api/v1/cbx/{bookId}/page-dimensions endpoint and service methods to fetch/parse CBX page dimensions including width, height, and wide-flag detection; handles per-page errors gracefully.
PDF Viewer Dark Theme & Preferences
booklore-api/src/main/java/org/booklore/model/dto/PdfViewerPreferences.java, booklore-api/src/main/java/org/booklore/model/entity/PdfViewerPreferencesEntity.java, booklore-api/src/main/java/org/booklore/service/book/BookService.java, booklore-api/src/main/java/org/booklore/service/book/BookUpdateService.java, booklore-api/src/main/resources/db/migration/V134\\__Add_is_dark_theme_to_pdf_viewer_preference.sql
Extended PDF viewer preferences with isDarkTheme field across DTO, entity, and service layers; added database migration with default value TRUE.
PDF Spread Mode & User Settings
booklore-api/src/main/java/org/booklore/service/user/DefaultUserSettingsProvider.java, booklore-api/src/main/resources/db/migration/V135\\__Change_pdf_default_spread_to_off.sql
Changed default PDF spread mode from odd to off in settings provider and migrated existing user preferences.
CBX Scroll Modes & Enums
booklore-api/src/main/java/org/booklore/model/enums/CbxPageScrollMode.java, booklore-api/src/main/java/org/booklore/model/dto/response/CbxPageDimension.java
Added LONG_STRIP enum constant to scroll modes. Added new CbxPageDimension response DTO with page number, width, height, and wide flag.
Frontend Build Configuration
frontend/.yarnrc.yml, frontend/angular.json, frontend/package.json
Added Yarn configuration for node-modules linking. Extended Angular build assets to include EmbedPDF distributions. Added COOP/COEP headers to dev-server. Added @embedpdf/pdfium and @embedpdf/snippet dependencies.
Book Model & Dimension Service
frontend/src/app/features/book/model/book.model.ts, frontend/src/app/features/readers/cbx-reader/models/cbx-page-dimension.model.ts, frontend/src/app/features/readers/cbx-reader/core/cbx-page-dimension.service.ts
Extended PdfViewerSetting with isDarkTheme and CbxViewerSetting with split/brightness/emulation/click options. Added page dimension service for fetching, caching, and computing webtoon detection heuristics and page pairing logic.
CBX Reader Canvas & Rendering
frontend/src/app/features/readers/cbx-reader/renderers/canvas-renderer.component.ts
Added new standalone CanvasRendererComponent supporting horizontal split rendering with safari canvas-size limits and crossOrigin handling.
CBX Reader Main Component
frontend/src/app/features/readers/cbx-reader/cbx-reader.component.ts, frontend/src/app/features/readers/cbx-reader/cbx-reader.component.html, frontend/src/app/features/readers/cbx-reader/cbx-reader.component.scss
Major overhaul: integrated canvas rendering with split-state management, page dimension fetching, new settings (brightness, emulate-book, click-pagination, auto-close-menu), long-strip scroll mode implementation, dynamic swipe thresholds, click-overlay UI with RTL support, book emulation spine styling, and wake-lock integration.
CBX Quick Settings
frontend/src/app/features/readers/cbx-reader/layout/quick-settings/cbx-quick-settings.component.ts, frontend/src/app/features/readers/cbx-reader/layout/quick-settings/cbx-quick-settings.component.html, frontend/src/app/features/readers/cbx-reader/layout/quick-settings/cbx-quick-settings.service.ts, frontend/src/app/features/readers/cbx-reader/layout/quick-settings/cbx-quick-settings.service.spec.ts
Extended quick-settings state with brightness (0-100 range), emulate-book, click-pagination, and auto-close-menu toggles. Added UI controls with slider and toggle buttons. Updated service with RxJS subjects and emitter methods. Updated test expectations.
CBX Reader Preferences
frontend/src/app/features/settings/reader-preferences/cbx-reader-preferences/cbx-reader-preferences-component.ts
Added LONG_STRIP scroll mode option to preferences component.
PDF Reader Components
frontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts, frontend/src/app/features/readers/pdf-reader/pdf-reader.component.html, frontend/src/app/features/readers/pdf-reader/pdf-reader.component.scss
Extensive overhaul: added EmbedPDF document-mode viewer with iframe/postMessage communication, dark-theme toggle persistence, fullscreen support, custom toolbar/footer with pagination controls (first/prev/next/last, slider, go-to-page), header/footer trigger zones, annotation toolbar injection via MutationObserver, and mode-switching logic with save/restore. Completely restyled viewer internals via deep selectors.
EmbedPDF Iframe
frontend/src/assets/embedpdf-frame.html
Added self-contained iframe page for EmbedPDF viewer with WASM initialization, theme configuration, document callbacks, save/export via registry plugin, and Grimmory CSS injection into shadow DOM.
EBook Reader Immersive Mode
frontend/src/app/features/readers/ebook-reader/core/event.service.ts, frontend/src/app/features/readers/ebook-reader/ebook-reader.component.ts, frontend/src/app/features/readers/ebook-reader/ebook-reader.component.html, frontend/src/app/features/readers/ebook-reader/ebook-reader.component.scss, frontend/src/app/features/readers/ebook-reader/shared/visibility.util.ts
Added toggle-immersive event and immersive mode state with header/footer auto-hide and temporary-show logic. Updated visibility manager to suppress auto-visibility during immersive mode. Added keyboard shortcut (i/I key) and CSS rules to hide Foliate head/foot parts.
EBook Reader Shortcuts
frontend/src/app/features/readers/ebook-reader/dialogs/shortcuts-help.component.ts
Added keyboard shortcut help entry for immersive mode toggle.
Shared Services
frontend/src/app/shared/service/wake-lock.service.ts
Added WakeLockService (root-provided) to acquire/release browser wake lock with visibility-change auto-reacquisition and safe fallback for unsupported browsers.
User Settings & Enums
frontend/src/app/features/settings/user-management/user.service.ts
Extended CbxReaderSetting interface with split option, brightness, emulate-book, click-pagination, and auto-close-menu fields. Added CbxPageSplitOption enum (NO_SPLIT, FIT_SPLIT, SPLIT_LEFT_TO_RIGHT, SPLIT_RIGHT_TO_LEFT). Added TWO_PAGE_REVERSED to CbxPageViewMode.
UI Layout & Topbar
frontend/src/app/shared/layout/component/layout-topbar/app.topbar.component.html
Reformatted indentation and whitespace (no functional changes).
Localization
frontend/src/i18n/en/common.json, frontend/src/i18n/en/reader-cbx.json, frontend/src/i18n/en/reader-ebook.json, frontend/src/i18n/en/reader-pdf.json
Added i18n entries for on/off labels, CBX brightness/emulate/click/auto-close, ebook immersive toggle, and PDF rotation/fullscreen/footer pagination.
Book Filter Component
frontend/src/app/features/book/components/book-browser/book-filter/book-filter.component.ts
Refactored subscribeToUserSettings() method into inline userSettingsEffect class field using Angular signals effect pattern.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CBXReader as CBX Reader Component
    participant DimensionSvc as Page Dimension Service
    participant Backend as Backend API
    participant Canvas as Canvas Renderer

    User->>CBXReader: Load book
    par Load Data
        CBXReader->>Backend: GET /api/v1/pages
        Backend-->>CBXReader: Image URLs
    and
        CBXReader->>DimensionSvc: getPageDimensions(bookId)
        DimensionSvc->>Backend: GET /api/v1/cbx/{bookId}/page-dimensions
        Backend-->>DimensionSvc: CbxPageDimension[]
        DimensionSvc->>DimensionSvc: Cache & compute doublePairs
        DimensionSvc-->>CBXReader: pageDimensions + doublePairs
    end
    
    CBXReader->>CBXReader: updateCurrentImageUrls() with pageDimensions
    CBXReader->>CBXReader: Determine if wide page (use pageDimensions[i].wide)
    
    alt Canvas Rendering Enabled
        CBXReader->>Canvas: Render with splitState
        Canvas->>Canvas: Load image with CORS
        Canvas->>Canvas: Draw full or split half
        Canvas-->>CBXReader: Rendered canvas
    else Standard Image Rendering
        CBXReader->>CBXReader: Render <img> list
    end
Loading
sequenceDiagram
    participant User
    participant PDFReader as PDF Reader Component
    participant EmbedPDF as EmbedPDF iFrame
    participant Backend as Backend API
    
    User->>PDFReader: Load PDF
    PDFReader->>PDFReader: Check viewerMode (book/document)
    
    alt Book Mode
        PDFReader->>Backend: GET PDF content
        Backend-->>PDFReader: PDF blob
        PDFReader->>PDFReader: Load in ngx-extended-pdf-viewer
        PDFReader->>PDFReader: Apply isDarkTheme setting
    else Document Mode
        PDFReader->>EmbedPDF: Create iframe
        PDFReader->>EmbedPDF: postMessage({type: 'init', pdf, theme})
        EmbedPDF->>EmbedPDF: Load WASM, initialize viewer
        EmbedPDF-->>PDFReader: postMessage({type: 'ready'})
        User->>PDFReader: Toggle dark theme
        PDFReader->>EmbedPDF: postMessage({type: 'setTheme'})
        User->>PDFReader: Save/Close
        PDFReader->>EmbedPDF: postMessage({type: 'save'})
        EmbedPDF-->>PDFReader: postMessage({type: 'saveResponse', buffer})
    end
    
    PDFReader->>Backend: Persist isDarkTheme setting
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

The PR involves substantial heterogeneous changes across multiple reader components (CBX, PDF, EBook) with significant new logic: canvas-based rendering with split-state management, dimension-aware page pairing, EmbedPDF integration with iframe communication, immersive mode with visibility management, and extended settings persistence. While individual file changes follow consistent patterns, the cross-component interactions, new services, and complex state management in multiple readers demand careful reasoning for each subsystem.

Poem

🐰 Beneath the pixels, dimensions align,
Canvas splits pages with perfect design,
Dark themes and brightness now grace every view,
Immersive modes hide what's old, bring what's new!
Wake locks keep screens aglow, readers entranced—
By whiskers and code, this viewer has danced! 🎨📖✨

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
✨ Simplify code
  • Create PR with simplified code

Comment @coderabbitai help to get the list of available commands and usage tips.

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

@balazs-szucs balazs-szucs marked this pull request as ready for review March 31, 2026 15:24
@balazs-szucs balazs-szucs merged commit b492788 into grimmory-tools:develop Mar 31, 2026
13 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants