Skip to content

Commit

Permalink
Add the Navigator user guide
Browse files Browse the repository at this point in the history
  • Loading branch information
mickael-menu committed Jul 20, 2023
1 parent 6a489f7 commit 3e6b366
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 7 deletions.
9 changes: 5 additions & 4 deletions docs/guides/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

* [Extracting the content of a publication](content.md)
* [Supporting PDF documents](pdf.md)
* [Configuring the Navigator](navigator-preferences.md)
* [Font families in the EPUB navigator](epub-fonts.md)
* [Media Navigator](media-navigator.md)
* [Text-to-speech](tts.md)
* [Text-to-speech](tts.md)
* [Navigator](navigator/navigator.md)
* [Configuring the Navigator](navigator/preferences.md)
* [Font families in the EPUB navigator](navigator/epub-fonts.md)
* [Media Navigator](navigator/media-navigator.md)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Font families in the EPUB navigator

Readium allows users to customize the font family used to render a reflowable EPUB, by changing the [EPUB navigator preferences](navigator-preferences.md).
Readium allows users to customize the font family used to render a reflowable EPUB, by changing the [EPUB navigator preferences](preferences.md).

:warning: You cannot change the default font family of a fixed-layout EPUB (with zoomable pages), as it is similar to a PDF or a comic book.

Expand Down
File renamed without changes.
196 changes: 196 additions & 0 deletions docs/guides/navigator/navigator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
# Navigator

## Overview

A navigator is a component of the [Readium architecture](https://readium.org/architecture/) used to render and navigate through the content of a publication. This is a core building block for adding a reader to your application.

The Readium toolkit comes with several navigator implementations that work with different publication formats. Some are Android `Fragment`s, designed to be added to your view hierarchy (e.g. `EpubNavigatorFragment`). Others are chromeless and can be used in the background, such as `TtsNavigator` and `AudioNavigator`.

| | EPUB | PDF | LCP PDF | WebPub | Audiobook | CBZ | Divina |
|--------------------------|--------------------|--------------------|--------------------|--------------------|--------------------|--------------------|--------------------|
| `EpubNavigatorFragment` | :heavy_check_mark: | | | :heavy_check_mark: | | | |
| `PdfNavigatorFragment` | | :heavy_check_mark: | :heavy_check_mark: | | | | |
| `ImageNavigatorFragment` | | | | | | :heavy_check_mark: | :heavy_check_mark: |
| `AudioNavigator` | | | | | :heavy_check_mark: | | |
| `TtsNavigator` | :heavy_check_mark: | | | | | | |

### Navigator APIs

The navigators implement a set of shared interfaces to help reuse the reading logic across publication formats. For example, use the `Navigator` interface instead of specific implementations (e.g. `EpubNavigatorFragment`) to create a location history manager that works with all types of navigators.

You can write your own navigators and integrate them into your app with minimal changes by implementing the same interfaces.

#### `Navigator` interface

All navigators implement the `Navigator` interface, which provides the foundation for navigating resources in a `Publication`. Use it to traverse the content of the publication or observe the current location with `currentLocator`.

It does not specify how the content is presented to the user.

#### `VisualNavigator` interface

Navigators rendering the content visually on the screen should implement the `VisualNavigator` interface. It provides information about the nature of the presentation (e.g. scrolled, right-to-left, etc.) and can be used to observe input events, such as taps or keyboard strokes.

#### `MediaNavigator` interface

The `MediaNavigator` interface is implemented by navigators rendering a publication as audio or video content. You can use it to control the playback or observe its status.

[See the corresponding user guide for more information](media-navigator.md).

##### `TimeBasedMediaNavigator` interface

A time-based `MediaNavigator` renders an audio or video content with time locations. It is suited for audiobook or media overlay navigators.

##### `TextAwareMediaNavigator` interface

A text-aware `MediaNavigator` synchronizes utterances (e.g. sentences) with their corresponding audio or video clips. It can be used for text-to-speech, media overlays, and subtitled navigators.

#### `SelectableNavigator` interface

Navigators that enable users to select parts of the content, such as text or audio range selection, should implement `SelectableNavigator`. An app can use a selectable navigator to extract the `Locator` and content of the selected portion.

#### `DecorableNavigator` interface

A decorable navigator is able to render arbitrary decorations over a publication. It can be used to draw highlights over a publication.

[See the corresponding proposal for more information](https://readium.org/architecture/proposals/008-decorator-api.html).

## Instantiating a navigator

### Visual navigators

The Visual navigators are implemented as `Fragment` and must be added to your Android view hierarchy.

#### `EpubNavigatorFragment`

First, create an `EpubNavigatorFactory` from your `Publication` instance. You can optionally provide custom defaults for the user preferences.

```kotlin
val navigatorFactory = EpubNavigatorFactory(
publication = publication,
configuration = EpubNavigatorFactory.Configuration(
defaults = EpubDefaults(
pageMargins = 1.4
)
)
)
```

Then, you need to setup the `FragmentFactory` in your custom parent `Fragment`. See `EpubReaderFragment` in the Test App for a complete example.

:point_up: This is one way to set up the `EpubNavigatorFragment` in your view hierarchy. Choose what works best for your application.

```kotlin
class EpubReaderFragment : Fragment(), EpubNavigatorFragment.Listener {

lateinit var navigator: EpubNavigatorFragment

override fun onCreate(savedInstanceState: Bundle?) {
// You are responsible for creating/restoring the `NavigatorFactory`,
// for example from an in-memory repository.
// See `ReaderRepository` in the Test App for an example.
val navigatorFactory = ...

// You should restore the initial location from your view model.
childFragmentManager.fragmentFactory =
navigatorFactory.createFragmentFactory(
initialLocator = viewModel.initialLocator,
listener = this
)

// IMPORTANT: Set the `fragmentFactory` before calling `super`.
super.onCreate(savedInstanceState)
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val view = super.onCreateView(inflater, container, savedInstanceState)
val tag = "EpubNavigatorFragment"

if (savedInstanceState == null) {
childFragmentManager.commitNow {
add(R.id.navigator_container, EpubNavigatorFragment::class.java, Bundle(), tag)
}
}

navigator = childFragmentManager.findFragmentByTag(tag) as EpubNavigatorFragment

return view
}
}
```

```xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>

<androidx.fragment.app.FragmentContainerView
android:id="@+id/navigator_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
```

#### `PdfNavigatorFragment`

Use the same approach as described with the `EpubNavigatorFragment`, using a `PdfNavigatorFactory` instead.

#### `ImageNavigatorFragment`

Use the same approach as described with the `EpubNavigatorFragment`, except that there is no `ImageNavigatorFactory`. Instead, you can build the `FragmentFactory` directly with:

```kotlin
childFragmentManager.fragmentFactory =
ImageNavigatorFragment.createFactory(
publication = publication,
initialLocator = viewModel.initialLocator,
listener = this
)
```

### `AudioNavigator`

The audio navigator is chromeless and independent of the Android view hierarchy, making it much simpler to use than the visual navigators.

First, create an instance of the `AudioNavigatorFactory`, with the audio engine provider you want to use.

```kotlin
val navigatorFactory = AudioNavigatorFactory(
publication = publication,
audioEngineProvider = ExoPlayerEngineProvider(
application,
defaults = ExoPlayerDefaults(
pitch = 0.8
)
)
)
```

Then, simply request an instance of the `AudioNavigator` at the given initial location.

```kotlin
val navigator = navigatorFactory.createNavigator(initialLocator)
```

### `TtsNavigator`

The text-to-speech navigator is very similar to the `AudioNavigator`.

```kotlin
val navigatorFactory = TtsNavigatorFactory(
application,
publication,
defaults = AndroidTtsDefaults(
pitch = 0.8
)
)

val navigator = navigatorFactory.createNavigator(initialLocator)
```
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

:warning: The Navigator Setting API is still experimental and currently only available with `EpubNavigatorFragment` and `PdfNavigatorFragment`.

Take a look at the [migration guide](../migration-guide.md) if you are already using the legacy EPUB settings.
Take a look at the [migration guide](../../migration-guide.md) if you are already using the legacy EPUB settings.

## Overview

Expand All @@ -12,7 +12,7 @@ You cannot directly overwrite the Navigator settings. Instead, you submit a set

For instance: "font size" is a **setting**, and the application can submit the font size value `150%` as a **preference**.

<img src="assets/settings-flow.svg">
<img src="../assets/settings-flow.svg">

```kotlin
// 1. Create a set of preferences.
Expand Down

0 comments on commit 3e6b366

Please sign in to comment.