Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ All notable changes to this project will be documented in this file. Take a look
* `hyphens` - Enable hyphenation.
* `ligatures` - Enable ligatures in Arabic.
* Fixed scroll inertia when scrolling an EPUB.
* EPUB decorations can now be attached to `Locator` objects containing only an HTML ID (`locations.fragments`) or a CSS selector (`locations.cssSelector`).

### Changed

Expand Down
56 changes: 40 additions & 16 deletions readium/navigator/src/main/assets/_scripts/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,29 +228,53 @@ export function snapCurrentOffset() {
}

export function rangeFromLocator(locator) {
let text = locator.text;
if (!text || !text.highlight) {
return null;
}
try {
var root;
let locations = locator.locations;
if (locations && locations.cssSelector) {
root = document.querySelector(locations.cssSelector);
}
if (!root) {
root = document.body;
let text = locator.text;
if (text && text.highlight) {
var root;
if (locations && locations.cssSelector) {
root = document.querySelector(locations.cssSelector);
}
if (!root) {
root = document.body;
}

let anchor = new TextQuoteAnchor(root, text.highlight, {
prefix: text.before,
suffix: text.after,
});
return anchor.toRange();
}

let anchor = new TextQuoteAnchor(root, text.highlight, {
prefix: text.before,
suffix: text.after,
});
return anchor.toRange();
if (locations) {
var element = null;

if (!element && locations.cssSelector) {
element = document.querySelector(locations.cssSelector);
}

if (!element && locations.fragments) {
for (const htmlId of locations.fragments) {
element = document.getElementById(htmlId);
if (element) {
break;
}
}
}

if (element) {
let range = document.createRange();
range.setStartBefore(element);
range.setEndAfter(element);
return range;
}
}
} catch (e) {
logError(e);
return null;
}

return null;
}

/// User Settings.
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import androidx.appcompat.widget.SearchView
import androidx.fragment.app.FragmentResultListener
import androidx.fragment.app.commit
import androidx.fragment.app.commitNow
import androidx.lifecycle.lifecycleScope
import org.readium.r2.navigator.DecorableNavigator
import org.readium.r2.navigator.Decoration
import org.readium.r2.navigator.ExperimentalDecorator
import org.readium.r2.navigator.epub.*
import org.readium.r2.navigator.epub.css.FontStyle
Expand All @@ -25,6 +28,7 @@ import org.readium.r2.navigator.html.toCss
import org.readium.r2.navigator.preferences.FontFamily
import org.readium.r2.shared.ExperimentalReadiumApi
import org.readium.r2.shared.publication.Locator
import org.readium.r2.shared.publication.epub.pageList
import org.readium.r2.testapp.LITERATA
import org.readium.r2.testapp.R
import org.readium.r2.testapp.reader.preferences.UserPreferencesViewModel
Expand Down Expand Up @@ -66,8 +70,9 @@ class EpubReaderFragment : VisualReaderFragment(), EpubNavigatorFragment.Listene
"annotation-icon.svg"
)

// Register the HTML template for our custom [DecorationStyleAnnotationMark].
// Register the HTML templates for our custom decoration styles.
decorationTemplates[DecorationStyleAnnotationMark::class] = annotationMarkTemplate()
decorationTemplates[DecorationStylePageNumber::class] = pageNumberTemplate()

// Declare a custom font family for reflowable EPUBs.
addFontFamilyDeclaration(FontFamily.LITERATA) {
Expand Down Expand Up @@ -126,6 +131,33 @@ class EpubReaderFragment : VisualReaderFragment(), EpubNavigatorFragment.Listene
@Suppress("Unchecked_cast")
(model.settings as UserPreferencesViewModel<EpubSettings, EpubPreferences>)
.bind(navigator, viewLifecycleOwner)

viewLifecycleOwner.lifecycleScope.launchWhenStarted {
// Display page number labels if the book contains a `page-list` navigation document.
(navigator as? DecorableNavigator)?.applyPageNumberDecorations()
}
}

/**
* Will display margin labels next to page numbers in an EPUB publication with a `page-list`
* navigation document.
*
* See http://kb.daisy.org/publishing/docs/navigation/pagelist.html
*/
private suspend fun DecorableNavigator.applyPageNumberDecorations() {
val decorations = publication.pageList
.mapIndexedNotNull { index, link ->
val label = link.title ?: return@mapIndexedNotNull null
val locator = publication.locatorFromLink(link) ?: return@mapIndexedNotNull null

Decoration(
id = "page-$index",
locator = locator,
style = DecorationStylePageNumber(label = label),
)
}

applyDecorations(decorations, "pageNumbers")
}

override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
Expand Down Expand Up @@ -218,11 +250,11 @@ class EpubReaderFragment : VisualReaderFragment(), EpubNavigatorFragment.Listene
}
}

// Examples of HTML templates for custom Decoration Styles.

/**
* Example of an HTML template for a custom Decoration Style.
*
* This one will display a tinted "pen" icon in the page margin to show that a highlight has an
* associated note.
* This Decorator Style will display a tinted "pen" icon in the page margin to show that a highlight
* has an associated note.
*
* Note that the icon is served from the app assets folder.
*/
Expand Down Expand Up @@ -256,3 +288,39 @@ private fun annotationMarkTemplate(@ColorInt defaultTint: Int = Color.YELLOW): H
"""
)
}

/**
* This Decoration Style is used to display the page number labels in the margins, when a book
* provides a `page-list`. The label is stored in the [DecorationStylePageNumber] itself.
*
* See http://kb.daisy.org/publishing/docs/navigation/pagelist.html
*/
@OptIn(ExperimentalDecorator::class)
private fun pageNumberTemplate(): HtmlDecorationTemplate {
val className = "testapp-page-number"
return HtmlDecorationTemplate(
layout = HtmlDecorationTemplate.Layout.BOUNDS,
width = HtmlDecorationTemplate.Width.PAGE,
element = { decoration ->
val style = decoration.style as? DecorationStylePageNumber

// Using `var(--RS__backgroundColor)` is a trick to use the same background color as
// the Readium theme. If we don't set it directly inline in the HTML, it might be
// forced transparent by Readium CSS.
"""
<div><span class="$className" style="background-color: var(--RS__backgroundColor) !important">${style?.label}</span></div>"
"""
},
stylesheet = """
.$className {
float: left;
margin-left: 8px;
padding: 0px 4px 0px 4px;
border: 1px solid;
border-radius: 20%;
box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
opacity: 0.8;
}
"""
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -536,3 +536,14 @@ abstract class VisualReaderFragment : BaseReaderFragment(), VisualNavigator.List
@Parcelize
@OptIn(ExperimentalDecorator::class)
data class DecorationStyleAnnotationMark(@ColorInt val tint: Int) : Decoration.Style

/**
* Decoration Style for a page number label.
*
* This is an example of a custom Decoration Style declaration.
*
* @param label Page number label as declared in the `page-list` link object.
*/
@Parcelize
@OptIn(ExperimentalDecorator::class)
data class DecorationStylePageNumber(val label: String) : Decoration.Style