Skip to content
Closed
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 4 additions & 4 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,21 @@ jobs:
runs-on: macos-latest
if: ${{ !github.event.pull_request.draft }}
env:
scripts: ${{ 'readium/navigators/web/scripts' }}
scripts: ${{ 'readium/navigators/web/internals/scripts' }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
package_json_file: readium/navigators/web/scripts/package.json
package_json_file: readium/navigators/web/internals/scripts/package.json
run_install: false
- name: Setup cache
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: readium/navigators/web/scripts/pnpm-lock.yaml
cache-dependency-path: readium/navigators/web/internals/scripts/pnpm-lock.yaml
- name: Install dependencies
run: pnpm --dir "$scripts" install --frozen-lockfile
- name: Lint
Expand All @@ -98,4 +98,4 @@ jobs:
- name: Check if bundled scripts are up-to-date
run: |
make scripts-new
git diff --exit-code --name-only readium/navigators/web/src/main/assets/*
git diff --exit-code --name-only readium/navigators/web/internals/src/main/assets/*
4 changes: 4 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
SCRIPTS_PATH := readium/navigator/src/main/assets/_scripts
SCRIPTS_NAVIGATOR_WEB_PATH := readium/navigators/web/scripts
SCRIPTS_NAVIGATOR_WEB_PATH := readium/navigators/web/internals/scripts

help:
@echo "Usage: make <target>\n\n\
Expand Down Expand Up @@ -38,7 +38,8 @@ scripts-new:
pnpm run format; \
pnpm run lint; \
pnpm run bundle; \
mv dist/* ../src/main/assets/readium/navigators/web/
rm -r ../src/main/assets/readium/navigator/web/internals/generated/*; \
mv dist/* ../src/main/assets/readium/navigator/web/internals/generated/

.PHONY: scripts
scripts: scripts-legacy scripts-new
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ android {
compileSdk = (property("android.compileSdk") as String).toInt()

defaultConfig {
minSdk = (property("android.minSdk") as String).toInt()
minSdk = 23
targetSdk = (property("android.targetSdk") as String).toInt()

applicationId = "org.readium.navigator.demo"
Expand Down Expand Up @@ -56,22 +56,25 @@ android {
assets.srcDirs("src/main/assets")
}
}
namespace = "org.readium.navigator.demo"
namespace = "org.readium.demo.navigator"
}

dependencies {
implementation(project(":readium:readium-shared"))
implementation(project(":readium:readium-streamer"))
implementation(project(":readium:readium-navigator"))
implementation(project(":readium:navigators:readium-navigator-web"))
implementation(project(":readium:navigators:web:readium-navigator-web-reflowable"))
implementation(project(":readium:navigators:web:readium-navigator-web-fixedlayout"))
implementation(project(":readium:adapters:pdfium"))

coreLibraryDesugaring(libs.desugar.jdk.libs)

implementation(libs.timber)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.collections.immutable)
implementation(libs.kotlin.stdlib)
implementation(libs.bundles.compose)
implementation(libs.google.material)
implementation(libs.androidx.core)
implementation(libs.androidx.fragment.ktx)
implementation(libs.androidx.appcompat)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@android:style/Theme.Material.Light.NoActionBar">
android:theme="@style/Theme.AppTheme">
<activity
android:name=".DemoActivity"
android:exported="true">
Expand Down
1 change: 1 addition & 0 deletions demos/navigator/src/main/assets/annotation-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* available in the top-level LICENSE file of the project.
*/

package org.readium.navigator.demo
package org.readium.demo.navigator

import android.net.Uri
import android.os.Bundle
Expand All @@ -17,7 +17,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.core.view.WindowCompat
import androidx.fragment.app.FragmentActivity
import org.readium.navigator.demo.util.Theme
import org.readium.demo.navigator.theme.Theme
import org.readium.r2.shared.util.toAbsoluteUrl

class DemoActivity : FragmentActivity() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* available in the top-level LICENSE file of the project.
*/

package org.readium.navigator.demo
package org.readium.demo.navigator

import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Box
Expand All @@ -21,16 +21,17 @@ import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalTextToolbar
import androidx.core.view.WindowInsetsControllerCompat
import org.readium.navigator.demo.reader.Reader
import org.readium.navigator.demo.util.Fullscreenable
import org.readium.demo.navigator.reader.Rendition
import org.readium.demo.navigator.util.Fullscreenable

@Composable
fun Scaffold(
fullscreenState: State<Boolean>,
insetsController: WindowInsetsControllerCompat,
snackbarHostState: SnackbarHostState,
content: @Composable () -> Unit
content: @Composable () -> Unit,
) {
Fullscreenable(
fullscreenState = fullscreenState,
Expand All @@ -41,6 +42,7 @@ fun Scaffold(
) {
content.invoke()

LocalTextToolbar
SnackbarHost(
modifier = Modifier
.align(Alignment.BottomCenter)
Expand All @@ -56,7 +58,7 @@ fun MainContent(
viewmodel: DemoViewModel,
launchBookSelection: () -> Unit,
snackbarHostState: SnackbarHostState,
fullscreenState: MutableState<Boolean>
fullscreenState: MutableState<Boolean>,
) {
val viewmodelState = viewmodel.state.collectAsState().value

Expand Down Expand Up @@ -98,7 +100,7 @@ fun MainContent(
viewmodel.onBookClosed()
}

Reader(
Rendition(
readerState = viewmodelState.readerState,
fullScreenState = fullscreenState
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* available in the top-level LICENSE file of the project.
*/

package org.readium.navigator.demo
package org.readium.demo.navigator

import android.app.Application
import androidx.lifecycle.AndroidViewModel
Expand All @@ -13,14 +13,14 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.readium.navigator.demo.reader.ReaderOpener
import org.readium.navigator.demo.reader.ReaderState
import org.readium.demo.navigator.reader.ReaderOpener
import org.readium.demo.navigator.reader.ReaderState
import org.readium.r2.shared.util.AbsoluteUrl
import org.readium.r2.shared.util.toDebugDescription
import timber.log.Timber

class DemoViewModel(
application: Application
application: Application,
) : AndroidViewModel(application) {

sealed interface State {
Expand All @@ -32,11 +32,11 @@ class DemoViewModel(
State

data class Error(
val error: org.readium.r2.shared.util.Error
val error: org.readium.r2.shared.util.Error,
) : State

data class Reader(
val readerState: ReaderState<*, *>
val readerState: ReaderState<*, *, *, *>,
) : State
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Copyright 2025 Readium Foundation. All rights reserved.
* Use of this source code is governed by the BSD-style license
* available in the top-level LICENSE file of the project.
*/

@file:OptIn(ExperimentalReadiumApi::class)

package org.readium.demo.navigator.decorations

import android.graphics.Color
import androidx.annotation.ColorInt
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.toPersistentList
import org.readium.navigator.common.Decoration
import org.readium.navigator.web.common.WebDecorationTemplate
import org.readium.navigator.web.reflowable.ReflowableWebDecorationLocation
import org.readium.r2.navigator.epub.EpubNavigatorFragment
import org.readium.r2.navigator.html.toCss
import org.readium.r2.shared.ExperimentalReadiumApi
import org.readium.r2.shared.publication.Publication
import org.readium.r2.shared.publication.epub.pageList

/**
* Decoration Style for a page margin icon.
*
* This is an example of a custom Decoration Style declaration.
*/
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.
*/
data class DecorationStylePageNumber(val label: String) : Decoration.Style

/**
* This decoration template 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.
*/
fun annotationMarkTemplate(@ColorInt defaultTint: Int = Color.YELLOW): WebDecorationTemplate {
val className = "demo-annotation-mark"
val iconUrl = checkNotNull(EpubNavigatorFragment.assetUrl("annotation-icon.svg"))
return WebDecorationTemplate(
layout = WebDecorationTemplate.Layout.BOUNDS,
width = WebDecorationTemplate.Width.PAGE,
element = {
val style = it as? DecorationStyleAnnotationMark
val tint = style?.tint ?: defaultTint
// Using `data-activable=1` prevents the whole decoration container from being
// clickable. Only the icon will respond to activation events.
"""
<div><div data-activable="1" class="$className" style="background-color: ${tint.toCss()} !important"/></div>"
"""
},
stylesheet = """
.$className {
float: left;
margin-left: 8px;
width: 30px;
height: 30px;
border-radius: 50%;
background: url('$iconUrl') no-repeat center;
background-size: auto 50%;
opacity: 0.8;
}
"""
)
}

/**
* This decoration template 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
*/
fun pageNumberTemplate(): WebDecorationTemplate {
val className = "demo-page-number"
return WebDecorationTemplate(
layout = WebDecorationTemplate.Layout.BOUNDS,
width = WebDecorationTemplate.Width.PAGE,
element = {
val style = it 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;
}
"""
)
}

/**
* Decorations to 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
*/
val Publication.pageNumberDecorations: PersistentList<Decoration<ReflowableWebDecorationLocation>> get() =
pageList
.mapIndexedNotNull { index, link ->
val label = link.title ?: return@mapIndexedNotNull null

val location = locatorFromLink(link)
?.let { ReflowableWebDecorationLocation(it) }
?: return@mapIndexedNotNull null

Decoration<ReflowableWebDecorationLocation>(
id = Decoration.Id("page-$index"),
location = location,
style = DecorationStylePageNumber(label = label)
)
}.toPersistentList()
Loading