Skip to content

Latest commit

 

History

History
751 lines (471 loc) · 36.3 KB

CHANGELOG.md

File metadata and controls

751 lines (471 loc) · 36.3 KB

Changelog

All notable changes to this project will be documented in this file. Take a look at the migration guide to upgrade between two major versions.

Warning: Features marked as alpha may change or be removed in a future release without notice. Use with caution.

Added

Streamer

  • Support for standalone audio files and their metadata (contributed by @domkm).

Changed

  • The Readium Swift toolkit now requires a minimum of iOS 13.
  • Plenty of completion-based APIs were changed to use async functions instead.

Shared

  • A new Format type was introduced to augment MediaType with more precise information about the format specifications of an Asset.
  • Fetcher was replaced with a simpler Container type.
  • PublicationAsset was replaced by Asset, which contains a Format and access to the underlying Container or Resource.
  • The ResourceError hierarchy was revamped and simplified (see ReadError). Now it is your responsibility to provide a localized user message for each error case.
  • The Link property key for archive-based publication assets (e.g. an EPUB/ZIP) is now https://readium.org/webpub-manifest/properties#archive instead of archive.
  • The API of HTTPServer slightly changed to be more future-proof.

Streamer

  • The Streamer object was deprecated in favor of smaller segregated APIs: AssetRetriever and PublicationOpener.

Navigator

LCP

  • The Readium LCP persistence layer was extracted to allow applications to provide their own implementations. Take a look at the migration guide for guidance.

Fixed

Navigator

  • Optimized scrolling to an EPUB text-based locator if it contains a CSS selector.
  • The first resource of a fixed-layout EPUB is now displayed on its own when spreads are enabled and the author has not set a page-spread-* property. This is the default behavior in major reading apps like Apple Books.
  • #471 EPUB: Fixed reporting the current location when submitting new preferences.

Changed

  • The R2Shared, R2Streamer and R2Navigator packages are now called ReadiumShared, ReadiumStreamer and ReadiumNavigator.
  • Many APIs now expect one of the new URL types (RelativeURL, AbsoluteURL, HTTPURL and FileURL). This is helpful because:
    • It validates at compile time that we provide a URL that is supported.
    • The API's capabilities are better documented, e.g. a download API could look like this : download(url: HTTPURL) -> FileURL.

Shared

  • Link and Locator's href are normalized as valid URLs to improve interoperability with the Readium Web toolkits.
    • You MUST migrate your database if you were persisting HREFs and Locators. Take a look at the migration guide for guidance.
  • Links are not resolved to the self URL of a manifest anymore. However, you can still normalize the HREFs yourselves by calling Manifest.normalizeHREFsToSelf().
  • Publication.localizedTitle is now optional, as we cannot guarantee a publication will always have a title.

Fixed

Shared

  • #444 Fixed resolving titles of search results when the table of contents items contain fragment identifiers.

Navigator

  • #428 Fixed crash with the share editing action on iOS 17.
  • #428 Fixed showing look up and translate editing actions on iOS 17.

Added

  • #417 Support for the new 2.x LCP Profiles.

Added

Shared

  • You can now use DefaultHTTPClientDelegate.httpClient(_:request:didReceive:completion:) to handle authentication challenges (e.g. Basic) with DefaultHTTPClient.

Navigator

  • The AudioNavigator API has been promoted to stable and ships with a new Preferences API.
  • The new NavigatorDelegate.didFailToLoadResourceAt(_:didFailToLoadResourceAt:withError:) delegate API notifies when an error occurs while loading a publication resource (contributed by @ettore).

Fixed

  • #390 Fixed logger not logging above the minimum severity level (contributed by @ettore).

Navigator

  • From iOS 13 to 15, PDF text selection is disabled on protected publications disabling the Copy editing action.
  • The Share editing action is disabled for any protected publication.
  • Fixed starting the TTS from the current EPUB position.
  • #396 Ensure we stop the activity indicator when an EPUB resource fails to load correctly (contributed by @ettore).

Streamer

  • #399 Zipped Audio Books and standalone audio files are now recognized.

Added

Navigator

  • You can now customize the playback refresh rate of _AudiobookNavigator in its configuration.
  • The EPUB navigator automatically moves to the next resource when VoiceOver reaches the end of the current one.

Changed

Navigator

  • You should not subclass PDFNavigatorViewController anymore. If you need to override setupPDFView, you can do so by implementing the PDFNavigatorDelegate protocol.

Fixed

Shared

  • Zipped Audio Book archives are now detected even if they contain bitmap entries.

Navigator

  • #344 EPUB: Fixed lost position when rotating quickly the screen several times.
  • #350 Restore the ability to subclass the PDFNavigatorViewController.
  • Fixed activating the scroll mode when VoiceOver is enabled in the EPUB navigator.
  • Support for Xcode 15.

Added

Navigator

  • The PublicationSpeechSynthesizer (TTS) now supports background playback by default.
    • You will need to enable the Audio Background Mode in your app's build info.
  • Support for non-linear EPUB resources with an opt-in in reading apps (contributed by @chrfalch in #332 and #331).
    1. Override loading non-linear resources with VisualNavigatorDelegate.navigator(_:shouldNavigateToLink:).
    2. Present a new EPUBNavigatorViewController by providing a custom readingOrder with only this resource to the constructor.

Fixed

Navigator

  • Improved performance when adding hundreds of HTML decorations at once.
  • Fixed broadcasting the PublicationSpeechSynthesizer with AirPlay when the screen is locked.

Changed

Navigator

  • AudioSession and NowPlayingInfo are now stable!
  • You need to provide the configuration of the Audio Session to the constructor of PublicationSpeechSynthesizer, instead of AVTTSEngine.
  • The Readium toolkit now requires iOS 11.0+.

Added

Navigator

  • The auto spread setting is now available for fixed-layout EPUBs. It will display two pages in landscape and a single one in portrait.

Streamer

  • The EPUB content iterator now returns audio and video elements and fill in the progression and totalProgression locator properties.

Changed

Navigator

  • EPUBNavigatorViewController.firstVisibleElementLocator() now returns the first block element that is visible on the screen, even if it starts on previous pages.
    • This is used to make sure the user will not miss any context when restoring a TTS session in the middle of a resource.

Fixed

Navigator

  • Fixed the PDF auto spread setting and scaling pages when rotating the screen.
  • Fixed navigating to the first chapter of an audiobook with a single resource (contributed by @grighakobian).
  • Prevent auto-playing videos in EPUB publications.
  • Fixed various memory leaks and data races.
  • The WKWebView is now inspectable again with Safari starting from iOS 16.4.
  • Fixed crash in the PublicationSpeechSynthesizer when closing the navigator without stopping it first.
  • Fixed pausing the PublicationSpeechSynthesizer right before starting the utterance.
  • Fixed the audio session kept opened while the app is in the background and paused.
  • Fixed the Attribute dir redefined error when the EPUB resource already has a dir attribute.
  • #309 Fixed restoring the EPUB location when the application was killed in the background (contributed by @triin-ko).

Streamer

  • Fix issue with the TTS starting from the beginning of the chapter instead of the current position.

Added

Streamer

  • Positions computation, TTS and search is now enabled for Readium Web Publications conforming to the EPUB profile.

Navigator

  • New VisualNavigatorDelegate APIs to handle keyboard events (contributed by @lukeslu).
    • This can be used to turn pages with the arrow keys, for example.
  • Support for custom fonts with the EPUB navigator.
  • A brand new user preferences API for configuring the EPUB and PDF Navigators. This new API is easier and safer to use. To learn how to integrate it in your app, please refer to the user guide and migration guide.
    • New EPUB user preferences:
      • fontWeight - Base text font weight.
      • textNormalization - Normalize font style, weight and variants, which improves accessibility.
      • imageFilter - Filter applied to images in dark theme (darken, invert colors)
      • language - Language of the publication content.
      • readingProgression - Direction of the reading progression across resources, e.g. RTL.
      • typeScale - Scale applied to all element font sizes.
      • paragraphIndent - Text indentation for paragraphs.
      • paragraphSpacing - Vertical margins for paragraphs.
      • hyphens - Enable hyphenation.
      • ligatures - Enable ligatures in Arabic.
    • New PDF user preferences:
      • backgroundColor - Background color behind the document pages.
      • offsetFirstPage - Indicate if the first page should be displayed in its own spread.
      • pageSpacing - Spacing between pages in points.
      • readingProgression - Direction of the reading progression across resources, e.g. RTL.
      • scrollAxis - Scrolling direction when scroll is enabled.
      • scroll - Indicate if pages should be handled using scrolling instead of pagination.
      • spread - Enable dual-page mode.
      • visibleScrollbar - Indicate whether the scrollbar should be visible while scrolling.
  • The new DirectionalNavigationAdapter component helps you to turn pages with the arrows and space keyboard keys or taps on the edge of the screen.

Deprecated

Streamer

Navigator

Changed

Navigator

  • The define editing action replaces lookup on iOS 16+. When enabled, it will show both the "Look Up" and "Search Web" menu items.
  • Prevent navigation in the EPUB while it is being loaded.

Fixed

Navigator

  • Fixed a race condition issue with the AVTTSEngine, when pausing utterances.
  • Fixed crash with PublicationSpeechSynthesizer, when the currently played word cannot be resolved.
  • Fixed EPUB tap event sent twice when using a mouse (e.g. on Apple Silicon or with a mouse on an iPad).

Added

Shared

Navigator

Streamer

Deprecated

Shared

  • Locator(link: Link) is deprecated as it may create an incorrect Locator if the link type is missing.
    • Use publication.locate(Link) instead.

Fixed

  • #244 Fixed build with Xcode 14 and Carthage/CocoaPods.

Navigator

  • Fixed memory leaks in the EPUB and PDF navigators.
  • #61 Fixed serving EPUB resources when the HREF contains an anchor or query parameters.
  • Performance issue with EPUB fixed-layout when spreads are enabled.
  • Disable scrolling in EPUB fixed-layout resources, in case the viewport is incorrectly set.
  • Fix vertically bouncing EPUB resources in iOS 16.

Streamer

  • Fixed memory leak in the PublicationServer.

LCP

  • The LCP authentication dialog is now fully localized and supports Dark Mode (contributed by @openm1nd).

Added

Shared

  • Get the sanitized Locator text ready for user display with locator.text.sanitized().
  • A new Publication.conforms(to:) API to identify the profile of a publication.
  • Support for the conformsTo RWPM metadata, to identify the profile of a Publication.
  • Support for right-to-left PDF documents by extracting the reading progression from the ViewerPreferences/Direction metadata.
  • HTTP client:
    • A new HTTPClient.download() API to download HTTP resources to a temporary location.
    • HTTPRequest and DefaultHTTPClient take an optional userAgent property to customize the user agent.

Navigator

  • The new NavigatorDelegate.navigator(_:didJumpTo:) API is called every time the navigator jumps to an explicit location, which might break the linear reading progression.
    • For example, it is called when clicking on internal links or programmatically calling Navigator.go(to:), but not when turning pages.
    • You can use this callback to implement a navigation history by differentiating between continuous and discontinuous moves.

Deprecated

Shared

  • Publication.format is now deprecated in favor of the new Publication.conforms(to:) API which is more accurate.
    • For example, replace publication.format == .epub with publication.conforms(to: .epub) before opening a publication with the EPUBNavigatorViewController.

Changed

LCP

  • The LCPService now uses a provided HTTPClient instance for all HTTP requests.

Fixed

Navigator

  • #14 Backward compatibility (iOS 10+) of JavaScript files is now handled with Babel.
  • Throttle the reload of EPUB spreads to avoid losing the position when the reader gets back to the foreground.

LCP

  • Fixed the notification of acquisition progress.

2.2.0

Added

Shared

  • Support for Paragraph Margins user setting.

Navigator

  • A new translate EPUB and PDF editing action is available for iOS 15.

Fixed

Shared

  • Improved performances of the search service used with EPUB.

Navigator

  • Fixed turning pages of an EPUB reflowable resource with an odd number of columns. A virtual blank trailing column is appended to the resource when displayed as two columns.

2.1.1

Fixed

LCP

  • Fix crash using the default LCPDialogViewController with CocoaPods.

2.1.0

Added

  • Support for Swift Package Manager (contributed by @stevenzeck).

Shared

  • (alpha) A new Publication SearchService to search through the resources' content with a default implementation StringSearchService.
  • Link objects from archive-based publication assets (e.g. an EPUB/ZIP) have additional properties for entry metadata.
    "properties" {
        "archive": {
            "entryLength": 8273,
            "isEntryCompressed": true
        }
    }
  • New UserProperties.removeProperty(forReference:) API to remove unwanted Readium CSS properties (contributed by @ettore).

Navigator

  • EPUB navigator:
    • The EPUB navigator is now able to navigate to a Locator using its text context. This is useful for search results or highlights missing precise locations.
    • New EPUBNavigatorViewController.evaluateJavaScript() API to run a JavaScript on the currently visible HTML resource.
    • New userSettings property for EPUBNavigatorViewController.Configuration to set the default user settings values (contributed by @ettore).
    • You can provide custom editing actions for the text selection menu (contributed by @cbaltzer).
      1. Create a custom action with, for example: EditingAction(title: "Highlight", action: #selector(highlight:))
      2. Then, implement the selector in one of your classes in the responder chain. Typically, in the UIViewController wrapping the navigator view controller.
      class EPUBViewController: UIViewController {
          init(publication: Publication) {
              var config = EPUBNavigatorViewController.Configuration()
              config.editingActions.append(EditingAction(title: "Highlight", action: #selector(highlight)))
              let navigator = EPUBNavigatorViewController(publication: publication, config: config)
          }
      
          @objc func highlight(_ sender: Any) {}
      }
  • New SelectableNavigator protocol for navigators supporting user selection.
    • Get or clear the current selection.
    • Implement navigator(_:canPerformAction:for:) to validate each editing action for the current selection. For example, to make sure the selected text is not too large for a definition look up.
    • Implement navigator(_:shouldShowMenuForSelection:) to override the default edit menu (UIMenuController) with a custom selection pop-up.
  • (alpha) Support for the Decorator API to draw user interface elements over a publication's content.
    • This can be used to render highlights over a text selection, for example.
    • For now, only the EPUB navigator implements DecorableNavigator. You can implement custom decoration styles with HTMLDecorationTemplate.
  • (alpha) A new navigator for audiobooks.
    • The navigator is chromeless, so you will need to provide your own user interface.

Deprecated

Navigator

  • Removed navigator(_:userContentController:didReceive:) which is actually not needed since you can provide your own WKScriptMessageHandler to WKUserContentController.

Changed

Streamer

  • The default EPUB positions service now uses the archive entry length when available. This is similar to how Adobe RMSDK generates page numbers.
    • To use the former strategy, create the Streamer with: Streamer(parsers: [EPUBParser(reflowablePositionsStrategy: .originalLength(pageLength: 1024))])

Fixed

Streamer

  • #208 Crash when reading obfuscated EPUB resources with an empty publication identifier.

Navigator

  • Fixed receiving EPUBNavigatorDelegate.navigator(_:setupUserScripts:) for the first web view.
  • r2-testapp-swift#343 Fixed hiding "Share" editing action (contributed by @rocxteady).

2.0.1

Fixed

Shared

  • #139 Compile error with Xcode 12.4

2.0.0

Deprecated

  • All APIs deprecated in previous versions are now unavailable.

Shared

  • DownloadSession is deprecated and will be removed in the next major version. Please migrate to your own download solution.

2.0.0-beta.2

Added

Shared

  • Resource has a new API to perform progressive asynchronous reads. This is useful when streaming a resource.
  • HTTPFetcher is a new publication fetcher able to serve remote resources through HTTP.
    • The actual HTTP requests are performed with an instance of HTTPClient.
  • HTTPClient is a new protocol exposing a high level API to perform HTTP requests.
    • It supports simple fetches but also progressive downloads.
    • DefaultHTTPClient is an implementation of HTTPClient using standard URLSession APIs. You can use its delegate to customize how requests are created and even recover from errors, e.g. to implement Authentication for OPDS.
    • You can provide your own implementation of HTTPClient to Readium APIs if you prefer to use a third-party networking library.
  • PublicationServiceContext now holds a weak reference to the parent Publication. This can be used to access other services from a given PublicationService implementation.
  • The default LocatorService implementation can be used to get a Locator from a global progression in the publication.
    • publication.locate(progression: 0.5)

Streamer

  • Streamer takes a new optional HTTPClient dependency to handle HTTP requests.

Navigator

  • New EPUBNavigatorDelegate APIs to inject custom JavaScript.
    • Override navigator(_:setupUserScripts:) to register additional user script to the WKUserContentController of each web view.
    • Override navigator(_:userContentController:didReceive:) to receive callbacks from your scripts.

Changed

Shared

  • The Archive API now supports resource ownership at the entry level.
    • The default ZIP implementation takes advantage of this by opening a new ZIP stream for each resource to be served. This improves performances and memory safety.

Streamer

  • The HTTP server now requests that publication resources are not cached by browsers.
    • Caching poses a security risk for protected publications.

LCP

  • We removed the dependency to the private R2LCPClient.framework, which means:
    • Now r2-lcp-swift works as a Carthage dependency, no need to use a submodule anymore.
    • You do not need to modify r2-lcp-swift's Cartfile anymore to add the private liblcp dependency.
    • However, you must provide a facade to LCPService (see README for an example implementation).
  • The Renew Loan API got revamped to better support renewal through a web page.
    • You will need to implement LCPRenewDelegate to coordinate the UX interaction.
    • Readium ships with a default implementation LCPDefaultRenewDelegate to handle web page renewal with SFSafariViewController.

Fixed

Shared

  • Improved performances when reading consecutive ranges of a deflated ZIP entry.
  • HREF normalization when a resource path contains special characters.

Navigator

  • Optimized performances of preloaded EPUB resources.

LCP

  • Fixed really slow opening of large PDF documents.

2.0.0-beta.1

Added

Shared

  • PublicationAsset is a new protocol which can be used to open a publication from various medium, such as a file, a remote URL or a custom source.
    • File was replaced by FileAsset, which implements PublicationAsset.

Changed

Shared

  • Format got merged into MediaType, to simplify the media type APIs.
    • You can use MediaType.of() to sniff the type of a file or bytes.
    • MediaType has now optional name and fileExtension properties.
    • Some publication formats can be represented by several media type aliases. Using mediaType.canonicalized will give you the canonical media type to use, for example when persisting the file type in a database. All Readium APIs are already returning canonical media types, so it only matters if you create a MediaType yourself from its string representation.
  • ContentLayout is deprecated, use publication.metadata.effectiveReadingProgression to determine the reading progression of a publication instead.

Streamer

  • Streamer is now expecting a PublicationAsset instead of a File. You can create custom implementations of PublicationAsset to open a publication from different medium, such as a file, a remote URL, in-memory bytes, etc.
    • FileAsset can be used to replace File and provides the same behavior.

Fixed

Navigator

  • EPUBs declaring multiple languages were laid out from right to left if the first language had an RTL reading progression. Now if no reading progression is set, the effectiveReadingProgression will be LTR.

2.0.0-alpha.2

Added

Shared

  • The Publication Services API allows to extend a Publication with custom implementations of known services. This version ships with a few predefined services:
    • PositionsService provides a list of discrete locations in the publication, no matter what the original format is.
    • CoverService provides an easy access to a bitmap version of the publication cover.
  • The Composite Fetcher API can be used to extend the way publication resources are accessed.
  • Support for exploded directories for any archive-based publication format.
  • Content Protection handles DRM and other format-specific protections in a more systematic way.
    • LCP now ships an LCPContentProtection implementation to be plugged into the Streamer.
    • You can add custom ContentProtection implementations to support other DRMs by providing an instance to the Streamer.
  • A new LinkRelation type to represent link relations, instead of using raw strings.
    • This will improve code safety through type checking and enable code completion.
    • Since LinkRelation conforms to ExpressibleByStringLiteral, you can continue using raw strings in the API. However, migrating your code is recommended, e.g. links.first(withRel: .cover).
    • Known link relations (including from OPDS specifications) are available under the LinkRelation namespace. You can easily add custom relations to the namespace by declaring static properties in a LinkRelation extension.

Streamer

  • Streamer API offers a simple interface to parse a publication and replace standalone parsers.
  • A generic ImageParser for bitmap-based archives (CBZ or exploded directories) and single image files.
  • A generic AudioParser for audio-based archives (Zipped Audio Book or exploded directories) and single audio files.

Navigator

  • Support for the new Publication model using the Content Protection for DRM rights and the Fetcher for resource access.
    • This replaces the Container and DRMLicense objects which were needed by the navigator before.

LCP

  • LCP implementation of the Content Protection API to work with the new Streamer API.
    • It is highly recommended that you upgrade to the new Streamer API to open publications, which will simplify DRM unlocking.
  • Two default implementations of LCPAuthenticating:
    • LCPDialogAuthentication to prompt the user for its passphrase with the official LCP dialog.
    • LCPPassphraseAuthentication to provide directly a passphrase, pulled for example from a database or a web service.
  • LCPService.acquirePublication() is a new API to acquire a publication from a standalone license. Compared to the former importPublication():
    • It doesn't require the passphrase, to allow bulk imports.
    • It can be cancelled by calling cancel() on the returned LCPAcquisition object.
  • LCPService.isLCPProtected() provides a way to check if a file is protected with LCP.

Changed

Shared

  • The Publication and Container types were merged together to offer a single interface to a publication's resources.
    • Use publication.get() to read the content of a resource, such as the cover. It will automatically be decrypted if a ContentProtection was attached to the Publication.

Streamer

  • Container and ContentFilters were replaced by a shared implementation of a Fetcher.
  • PDFFileParser was replaced in favor of a shared PDFDocument protocol. This version ships with two implementations using PDFKit and CoreGraphics.

LCP

  • LCPAuthenticating is now provided with more information and you will need to update your implementation.

Fixed

Streamer

  • Deobfuscating ranges of EPUB resources.

Navigator

  • Layout of right-to–left EPUB.
  • Various EPUB navigation issues:
    • Prevent breaking initial location when calling updateUserSettings too soon.
    • Fix weird scrolling behavior when double tapping on the edges to turn pages.
    • Don't send intermediate incorrect locators when loading a pending locator.
  • Optimize positions calculation for LCP protected PDF.

LCP

2.0.0-alpha.1

Added

Shared

Streamer

  • ReadiumWebPubParser to parse all Readium Web Publication profiles, including Audiobooks and LCP for PDF. It parses both manifests and packages.

Navigator

  • Support for pop-up footnotes (contributed by @tooolbox).
  • In EPUB's user settings:
    • Support for hyphenation (contributed by @ehapmgs).
    • Publishers' default styles are now used by default.
    • Default line height is increased to improve readability.
  • JavaScript errors are logged in Xcode's console for easier debugging.

LCP

Changed

Shared

  • All the Publication shared models are now immutable, to improve code safety. This should not impact reading apps unless you created Publication or other models yourself.
  • The DocumentTypes API was extended and offers an easy way to check if your app supports a given file.
  • Dependencies to format-related third-party libraries such as ZIP, XML and PDF are being consolidated into r2-shared-swift. Therefore, r2-shared-swift now depends on Fuzi and ZIPFoundation. This change will improve maintainability by isolating third-party code and allow (work in progress) to substitute the default libraries with custom ones.

Navigator

LCP

  • LCPAuthenticating can now return hashed passphrases in addition to clear ones. This can be used by reading apps fetching hashed passphrases from a web service or Authentication for OPDS, for example.
  • Provided LCPAuthenticating instances are now retained by the LCP service. Therefore, you can provide one without keeping a reference around in your own code.

Fixed

Streamer

Navigator

  • Jumping to a bookmark (Locator) located in a resource that is not already pre-loaded used to fail for some publications.
  • Touching interactive elements in fixed-layout EPUBs, when two-page spreads are enabled.