Warning
Minor releases (a.B.c) of the Readium toolkit may now include minor breaking changes, such as dependency upgrades or small API modifications. Major version numbers are reserved for significant architectural changes.
Take a look at the migration guide
Changelog
Added
Navigator
- Added
VisualNavigatorDelegate.navigatorContentInset(_:)to customize the content and safe-area insets used by the navigator.- By default, the navigator uses the window's
safeAreaInsets, which can cause content to shift when the status bar is shown or hidden (since those insets change). To avoid this, implementnavigatorContentInset(_:)and return insets that remain stable across status bar visibility changes — for example, a top inset large enough to accommodate the maximum expected status bar height.
- By default, the navigator uses the window's
- Added
[TTSVoice].filterByLanguage(_:)to filter TTS voices by language and region. - Added
[TTSVoice].sorted()to sort TTS voices by region, quality, and gender. - New experimental positioning of EPUB decorations that places highlights behind text to improve legibility with opaque decorations (contributed by @ddfreiling).
- To opt-in, initialize the
EPUBNavigatorViewController.Configurationobject withdecorationTemplates: HTMLDecorationTemplate.defaultTemplates(alpha: 1.0, experimentalPositioning: true).
- To opt-in, initialize the
LCP
- Added an initializer parameter for providing a custom device identifier (contributed by @dewantawsif).
- You must ensure the identifier is unique and stable for the device (persist and reuse across app launches).
- Recommended: generate an app-scoped UUID and store it securely (e.g., in the Keychain); avoid hardware or advertising identifiers.
- You can use
LCPService.injectLicenseDocument(_:in)to insert an LCPL into a package, if you downloaded it manually instead of usingLCPService.acquirePublication().
Changed
Navigator
EPUBNavigatorViewController.Configuration.contentInsetnow expects values that already include the safe area insets.- If you previously supplied content-only margins, update them to add the safe-area values to preserve the same visible layout.
- Alternatively, implement
VisualNavigatorDelegate.navigatorContentInset(_:)to compute and return the full insets (content + safe area), helping avoid layout shifts when system UI (e.g., the status bar) appears or disappears.
- Eloquence and novelty TTS voices are removed from the
PublicationSpeechSynthesizerAPI, as they are not a good fit to read publications.
LCP
- The LCP License Document is now accessible via
publication.lcpLicense?.license, even if the license validation fails with a status error or missing passphrase. This is useful for checking the end date of an expired license or renew a license.
Fixed
Navigator
- The safe area insets strategy was adjusted to take into account changes in iOS/iPadOS 26.
- Fixed the lost progression with the EPUB navigator when the application becomes active again after the system terminated the WebKit process.
Commits
- Allow access to the LCP License Document even if the status check fails by @mickael-menu in #647
- Don't treat a missing passphrase as a validation error by @mickael-menu in #648
- Adjust safe area insets strategy for 26 by @mickael-menu in #650
- Fixed lost progression when the system kills the WebKit process by @mickael-menu in #654
- End editing of internal navigator view when resigning first responder by @mickael-menu in #657
- Remove
Package.resolvedby @mickael-menu in #658 - Implement parsing of the element in OPDS 1.x feeds by @x0000ff in #656
- Implement parsing of the element in OPDS 1.x feeds by @x0000ff in #655
- New navigator content inset strategy by @mickael-menu in #662
- Add an initializer parameter to LCP to pass a custom device id by @dewantawsif in #661
- Add sorting and filtering of TTS voices by @mickael-menu in #663
- Add injectLicense to LCPService by @qnga in #664
- Add experimental EPUB decoration positioning by @ddfreiling in #665
- 3.5.0 by @mickael-menu in #667
New Contributors
- @x0000ff made their first contribution in #656
- @dewantawsif made their first contribution in #661
- @ddfreiling made their first contribution in #665
Full Changelog: 3.4.0...3.5.0