Skip to content

Read Kindle, text and comic formats with cancellable preparation - #25

Open
Eoic wants to merge 1 commit into
developmentfrom
feature/24-additional-book-formats
Open

Eoic wants to merge 1 commit into
developmentfrom
feature/24-additional-book-formats

Conversation

@Eoic

@Eoic Eoic commented Nov 8, 2026 •

Copy link
Copy Markdown
Member

Adds MOBI, AZW3, TXT, CBR and CBZ reading alongside EPUB and PDF. Previously these formats could reach library/import flows without a working reader route; they now open through the reflow or fixed-page engine, retain original-format locators, and allow Back during preparation.

Closes #24. Implements format coverage within FR-3_1; does not close the whole requirement or certify NFR-4_2 performance. Companion client integration: client PR #141, which pins this reader commit. Merge this reader PR first.

Implementation

  • Convert DRM-free Kindle/text inputs to reflow documents and comic archives to transient page documents in cancellable native isolates/browser workers. Original source files are unchanged.
  • Decode RAR4/RAR5 comics in natural page order, retain comic colors, and transfer comic PDF bytes as binary data.
  • Vendor kindle_unpack 0.2.0 with its GPL-3.0 license and provenance, pure-Dart font decoding, and dual MOBI/KF8 fixes. The worker build includes its notices and resolves it correctly in Git consumers.
  • Add real MOBI/AZW3 and compressed comic fixtures, all-format browser checks, and opt-in native/browser stress runners. Large downloads and screenshots stay outside Git.

Validation

On Apple Silicon macOS with the workspace-pinned Flutter SDK:

  • Reader analyzer and full suite: 250 passed, seven opt-in corpus tests skipped; explicit large-book suite: 7 passed.
  • Example analysis/tests/web build, all-format browser reading/navigation checks, and worker build checks passed, including Git-consumer resolution and native asset exclusion.
  • All seven large samples opened and displayed readable pages. Active-worker Back/cancellation checks passed for every format.
  • Native stress checks exercised loading, seeking to 90%, serialized locator restoration and main-event-loop progress; they do not render Flutter viewports.

Browser observations used a fresh Chrome instance per book. Times measure document readiness, not guaranteed first rasterized paint. Memory is peak aggregate browser-process RSS across open/read/reopen/cancel, including GPU and workers, with about 0.81 GiB baseline.

Sample Size Readiness Largest opening frame gap Peak browser RSS
Webster EPUB 12.3 MB 15.04 s 33.3 ms 1.25 GiB
Webster TXT 29.0 MB 16.01 s 33.4 ms 1.44 GiB
Webster MOBI 19.9 MB 160.11 s 249.9 ms 3.69 GiB
Webster AZW3 22.7 MB 24.65 s 216.6 ms 1.49 GiB
Scanned Alice PDF 140.1 MB 0.33 s 16.8 ms 1.87 GiB
Generated 272-page CBZ 240.3 MB 4.96 s 33.3 ms 4.76 GiB
Generated 272-page CBR 240.3 MB 4.91 s 33.3 ms 4.96 GiB
Original compressed Whiz CBR 59.3 MB 2.40 s 33.4 ms 2.00 GiB

Corpus sources: Webster's Dictionary, Gutenberg 29765, scanned Alice PDF, and Whiz Comics #6. The 272-page comic fixtures repeat the original 68 JPEGs four times using stored ZIP/RAR5 entries; the separate original CBR checks compressed input. Reproduction instructions are in docs/VALIDATION.md.

Known limits

Large-book functionality is established for these samples, but uniformly non-blocking behavior is not: MOBI and AZW3 produced 232 ms and 227 ms main-thread long tasks, and whole-comic conversion has substantial memory cost. These remain optimization work. The 12 MB dictionary EPUB also exceeds the NFR-4_2 opening-time target.

Physical Android/iOS and low-memory behavior, arbitrary publisher files, every page, and long-distance Flutter pagination in the monolithic MOBI remain unverified. Encrypted books, password/multi-volume archives, Topaz and Kindle Print Replica remain unsupported.

Closes #24. Adds real-format coverage and opt-in large-book stress checks; records remaining performance limits.
Copilot AI balanced review requested due to automatic review settings November 8, 2026 01:46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-08T01:48:25.241276Z b4aafaf PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b4aafafcb4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +127 to +130
if (lc.contains('<svg')) return FlowKind.svg;
if (lc.contains('<html') ||
lc.contains('<?xml') && lc.contains('<head')) {
return FlowKind.html;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Distinguish SVG roots from SVG embedded in HTML flows

For a KF8 book whose primary HTML flow contains an SVG cover within its first 256 bytes, such as <html><body><svg ...>, this check classifies the entire HTML flow as SVG before checking for <html>. BookFlows.primaryHtml then returns null, and both the reconstruction and fallback paths in KindleBook.fromBytes dereference flows.primaryHtml!, causing an otherwise readable AZW3 or dual-format MOBI to fail opening as an invalid document. Check the root element rather than the presence of any SVG descendant, or identify the primary flow by its defined index.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Read MOBI, AZW3, TXT and comic archives with cancellable preparation

2 participants