diff --git a/readium/navigator-media2/src/main/java/org/readium/navigator/media2/MediaNavigator.kt b/readium/navigator-media2/src/main/java/org/readium/navigator/media2/MediaNavigator.kt index 4c5529855d..e4d797b1a8 100644 --- a/readium/navigator-media2/src/main/java/org/readium/navigator/media2/MediaNavigator.kt +++ b/readium/navigator-media2/src/main/java/org/readium/navigator/media2/MediaNavigator.kt @@ -34,6 +34,7 @@ import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import org.readium.navigator.media2.MediaNavigator.Companion.create import org.readium.r2.navigator.Navigator +import org.readium.r2.navigator.extensions.normalizeLocator import org.readium.r2.shared.publication.Link import org.readium.r2.shared.publication.Locator import org.readium.r2.shared.publication.Publication @@ -243,6 +244,8 @@ public class MediaNavigator private constructor( * Seeks to the given locator. */ public suspend fun go(locator: Locator): Try { + @Suppress("NAME_SHADOWING") val locator = publication.normalizeLocator(locator) + val itemIndex = publication.readingOrder.indexOfFirstWithHref(locator.href) ?: return Try.failure(Exception.InvalidArgument("Invalid href ${locator.href}.")) val position = locator.locations.time ?: Duration.ZERO diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFragment.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFragment.kt index 7607939b78..c55b3656e8 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFragment.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFragment.kt @@ -80,6 +80,7 @@ import org.readium.r2.shared.publication.Link import org.readium.r2.shared.publication.Locator import org.readium.r2.shared.publication.Publication import org.readium.r2.shared.publication.ReadingProgression as PublicationReadingProgression +import org.readium.r2.navigator.extensions.normalizeLocator import org.readium.r2.shared.publication.epub.EpubLayout import org.readium.r2.shared.publication.presentation.presentation import org.readium.r2.shared.publication.services.isRestricted @@ -571,6 +572,8 @@ public class EpubNavigatorFragment internal constructor( } override fun go(locator: Locator, animated: Boolean, completion: () -> Unit): Boolean { + @Suppress("NAME_SHADOWING") val locator = publication.normalizeLocator(locator) + listener?.onJumpToLocator(locator) val href = locator.href @@ -718,6 +721,9 @@ public class EpubNavigatorFragment internal constructor( } override suspend fun applyDecorations(decorations: List, group: String) { + @Suppress("NAME_SHADOWING") val decorations = decorations + .map { it.copy(locator = publication.normalizeLocator(it.locator)) } + run(viewModel.applyDecorations(decorations, group)) } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Publication.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Publication.kt index 194c2fc562..d1b305f08e 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Publication.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Publication.kt @@ -10,6 +10,7 @@ package org.readium.r2.navigator.extensions import kotlinx.coroutines.runBlocking +import org.readium.r2.shared.InternalReadiumApi import org.readium.r2.shared.publication.Locator import org.readium.r2.shared.publication.Publication import org.readium.r2.shared.publication.services.positions @@ -21,3 +22,17 @@ internal val Publication.positionsSync: List internal val Publication.positionsByResource: Map> get() = runBlocking { positions().groupBy { it.href } } + +/** + * Historically, we used to have "absolute" HREFs starting with a `/` in the manifest for packaged + * publications. We removed the root prefix, but we still need to support the locators created with + * the old HREFs. + */ +@InternalReadiumApi +public fun Publication.normalizeLocator(locator: Locator): Locator { + if (linkWithRel("self") != null) { + return locator + } + + return locator.copy(href = locator.href.removePrefix("/")) +} diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/image/ImageNavigatorFragment.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/image/ImageNavigatorFragment.kt index 389fc765a4..7e2d0ecb5f 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/image/ImageNavigatorFragment.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/image/ImageNavigatorFragment.kt @@ -42,6 +42,7 @@ import org.readium.r2.shared.publication.Link import org.readium.r2.shared.publication.Locator import org.readium.r2.shared.publication.Publication import org.readium.r2.shared.publication.ReadingProgression as PublicationReadingProgression +import org.readium.r2.navigator.extensions.normalizeLocator import org.readium.r2.shared.publication.indexOfFirstWithHref import org.readium.r2.shared.publication.services.isRestricted import org.readium.r2.shared.publication.services.positions @@ -185,6 +186,8 @@ public class ImageNavigatorFragment private constructor( } override fun go(locator: Locator, animated: Boolean, completion: () -> Unit): Boolean { + @Suppress("NAME_SHADOWING") val locator = publication.normalizeLocator(locator) + val resourceIndex = publication.readingOrder.indexOfFirstWithHref(locator.href) ?: return false diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsNavigator.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsNavigator.kt index 250d5440b9..825f625267 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsNavigator.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsNavigator.kt @@ -13,6 +13,7 @@ import androidx.media3.common.Player import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.MainScope import kotlinx.coroutines.flow.StateFlow +import org.readium.r2.navigator.extensions.normalizeLocator import org.readium.r2.navigator.media3.api.Media3Adapter import org.readium.r2.navigator.media3.api.MediaMetadataProvider import org.readium.r2.navigator.media3.api.MediaNavigator @@ -197,7 +198,7 @@ public class TtsNavigator, } public fun go(locator: Locator) { - player.go(locator) + player.go(publication.normalizeLocator(locator)) } override fun goToPreviousUtterance() { @@ -227,7 +228,7 @@ public class TtsNavigator, location.mapStateIn(coroutineScope) { it.tokenLocator ?: it.utteranceLocator } override fun go(locator: Locator, animated: Boolean, completion: () -> Unit): Boolean { - player.go(locator) + player.go(publication.normalizeLocator(locator)) return true } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/PdfNavigatorFragment.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/PdfNavigatorFragment.kt index 995d37adce..dc34f50a32 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/PdfNavigatorFragment.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/PdfNavigatorFragment.kt @@ -45,6 +45,7 @@ import org.readium.r2.shared.publication.Link import org.readium.r2.shared.publication.Locator import org.readium.r2.shared.publication.Publication import org.readium.r2.shared.publication.ReadingProgression as PublicationReadingProgression +import org.readium.r2.navigator.extensions.normalizeLocator import org.readium.r2.shared.publication.services.isRestricted import org.readium.r2.shared.resource.Resource import org.readium.r2.shared.util.mediatype.MediaType @@ -224,6 +225,7 @@ public class PdfNavigatorFragment Unit): Boolean { + @Suppress("NAME_SHADOWING") val locator = publication.normalizeLocator(locator) listener?.onJumpToLocator(locator) val pageNumber = locator.locations.page ?: locator.locations.position ?: 1 return goToPageIndex(pageNumber - 1, animated, completion)