@@ -17,6 +17,9 @@ import androidx.appcompat.widget.SearchView
1717import androidx.fragment.app.FragmentResultListener
1818import androidx.fragment.app.commit
1919import androidx.fragment.app.commitNow
20+ import androidx.lifecycle.lifecycleScope
21+ import org.readium.r2.navigator.DecorableNavigator
22+ import org.readium.r2.navigator.Decoration
2023import org.readium.r2.navigator.ExperimentalDecorator
2124import org.readium.r2.navigator.epub.*
2225import org.readium.r2.navigator.epub.css.FontStyle
@@ -25,6 +28,7 @@ import org.readium.r2.navigator.html.toCss
2528import org.readium.r2.navigator.preferences.FontFamily
2629import org.readium.r2.shared.ExperimentalReadiumApi
2730import org.readium.r2.shared.publication.Locator
31+ import org.readium.r2.shared.publication.epub.pageList
2832import org.readium.r2.testapp.LITERATA
2933import org.readium.r2.testapp.R
3034import org.readium.r2.testapp.reader.preferences.UserPreferencesViewModel
@@ -66,8 +70,9 @@ class EpubReaderFragment : VisualReaderFragment(), EpubNavigatorFragment.Listene
6670 " annotation-icon.svg"
6771 )
6872
69- // Register the HTML template for our custom [DecorationStyleAnnotationMark] .
73+ // Register the HTML templates for our custom decoration styles .
7074 decorationTemplates[DecorationStyleAnnotationMark ::class ] = annotationMarkTemplate()
75+ decorationTemplates[DecorationStylePageNumber ::class ] = pageNumberTemplate()
7176
7277 // Declare a custom font family for reflowable EPUBs.
7378 addFontFamilyDeclaration(FontFamily .LITERATA ) {
@@ -126,6 +131,33 @@ class EpubReaderFragment : VisualReaderFragment(), EpubNavigatorFragment.Listene
126131 @Suppress(" Unchecked_cast" )
127132 (model.settings as UserPreferencesViewModel <EpubSettings , EpubPreferences >)
128133 .bind(navigator, viewLifecycleOwner)
134+
135+ viewLifecycleOwner.lifecycleScope.launchWhenStarted {
136+ // Display page number labels if the book contains a `page-list` navigation document.
137+ (navigator as ? DecorableNavigator )?.applyPageNumberDecorations()
138+ }
139+ }
140+
141+ /* *
142+ * Will display margin labels next to page numbers in an EPUB publication with a `page-list`
143+ * navigation document.
144+ *
145+ * See http://kb.daisy.org/publishing/docs/navigation/pagelist.html
146+ */
147+ private suspend fun DecorableNavigator.applyPageNumberDecorations () {
148+ val decorations = publication.pageList
149+ .mapIndexedNotNull { index, link ->
150+ val label = link.title ? : return @mapIndexedNotNull null
151+ val locator = publication.locatorFromLink(link) ? : return @mapIndexedNotNull null
152+
153+ Decoration (
154+ id = " page-$index " ,
155+ locator = locator,
156+ style = DecorationStylePageNumber (label = label),
157+ )
158+ }
159+
160+ applyDecorations(decorations, " pageNumbers" )
129161 }
130162
131163 override fun onCreateOptionsMenu (menu : Menu , menuInflater : MenuInflater ) {
@@ -218,11 +250,11 @@ class EpubReaderFragment : VisualReaderFragment(), EpubNavigatorFragment.Listene
218250 }
219251}
220252
253+ // Examples of HTML templates for custom Decoration Styles.
254+
221255/* *
222- * Example of an HTML template for a custom Decoration Style.
223- *
224- * This one will display a tinted "pen" icon in the page margin to show that a highlight has an
225- * associated note.
256+ * This Decorator Style will display a tinted "pen" icon in the page margin to show that a highlight
257+ * has an associated note.
226258 *
227259 * Note that the icon is served from the app assets folder.
228260 */
@@ -256,3 +288,39 @@ private fun annotationMarkTemplate(@ColorInt defaultTint: Int = Color.YELLOW): H
256288 """
257289 )
258290}
291+
292+ /* *
293+ * This Decoration Style is used to display the page number labels in the margins, when a book
294+ * provides a `page-list`. The label is stored in the [DecorationStylePageNumber] itself.
295+ *
296+ * See http://kb.daisy.org/publishing/docs/navigation/pagelist.html
297+ */
298+ @OptIn(ExperimentalDecorator ::class )
299+ private fun pageNumberTemplate (): HtmlDecorationTemplate {
300+ val className = " testapp-page-number"
301+ return HtmlDecorationTemplate (
302+ layout = HtmlDecorationTemplate .Layout .BOUNDS ,
303+ width = HtmlDecorationTemplate .Width .PAGE ,
304+ element = { decoration ->
305+ val style = decoration.style as ? DecorationStylePageNumber
306+
307+ // Using `var(--RS__backgroundColor)` is a trick to use the same background color as
308+ // the Readium theme. If we don't set it directly inline in the HTML, it might be
309+ // forced transparent by Readium CSS.
310+ """
311+ <div><span class="$className " style="background-color: var(--RS__backgroundColor) !important">${style?.label} </span></div>"
312+ """
313+ },
314+ stylesheet = """
315+ .$className {
316+ float: left;
317+ margin-left: 8px;
318+ padding: 0px 4px 0px 4px;
319+ border: 1px solid;
320+ border-radius: 20%;
321+ box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
322+ opacity: 0.8;
323+ }
324+ """
325+ )
326+ }
0 commit comments