Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
525ac80
wip: start work on AudioReaderFragment
ddfreiling Aug 26, 2025
0d7a2d7
feat(example-app): load audiobooks to bookshelf
m-abs Aug 27, 2025
0586fa3
small refactor and cleanup
m-abs Aug 27, 2025
15f108f
Merge branch 'main' into feat/audiobook-navigator
m-abs Sep 2, 2025
3a815d9
minnor update to isReaderReady for android
m-abs Sep 2, 2025
e62093c
feat: basic audiobook navigator bootstrapping on iOS
ddfreiling Sep 2, 2025
247a170
Merge branch 'feat/audiobook-navigator' of github.com:Notalib/flutter…
ddfreiling Sep 2, 2025
f394672
refactor: improve API by having a single publication open at a time
ddfreiling Sep 4, 2025
4e73dca
fix(iOS): set currentPublication on opening
ddfreiling Sep 4, 2025
e256a29
minor cleanups
m-abs Sep 5, 2025
8667a44
fix: audioStart crashed on android
m-abs Sep 8, 2025
118dc30
fix: iOS audioStart threw an exception
m-abs Sep 8, 2025
27bcb3a
fix(android): loadPublication set the loaded publication as current, …
m-abs Sep 8, 2025
b373441
refactor: same methods for playback control, whether TTS or audiobook
ddfreiling Sep 8, 2025
73243a9
chore: remove Nota x-properties
ddfreiling Sep 8, 2025
34900b5
fix: minor corrections for audiobooks to play
ddfreiling Sep 8, 2025
c26dafa
feat(android): Readium-class is now the singleton ReadiumReader
m-abs Sep 8, 2025
d9df277
Merge branch 'feat/audiobook-navigator' of github.com:Notalib/flutter…
m-abs Sep 8, 2025
4d72eb2
refactoring audio and tts navigators
m-abs Sep 9, 2025
74fecfd
being timebased events from android
m-abs Sep 9, 2025
792221a
refactor: rename audioStart to audioEnable and add AudioPreferences a…
ddfreiling Sep 9, 2025
f04cb34
chore: update Android impl to new audioStart and audioSetPreferences API
ddfreiling Sep 9, 2025
8bf2752
fix: rename from audioStart to audioEnable wasn't complete
ddfreiling Sep 10, 2025
8049027
fix(example): open-success should reset error property
ddfreiling Sep 10, 2025
ba39e71
fix(ios): updated audioEnable forgot to return
ddfreiling Sep 10, 2025
c73c91c
chor(ios): use configured seek interval
ddfreiling Sep 10, 2025
6830750
refactor(ios): minor naming changes
ddfreiling Sep 10, 2025
60c1d34
feat(ios): send audio-locator stream updates
ddfreiling Sep 10, 2025
1735cc9
chor: Moved currentReadiumReaderView to ReadiumReader.currentReaderVi…
m-abs Sep 10, 2025
edbca03
fix: restoration broke
m-abs Sep 10, 2025
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,4 @@ lib/**/*.freezed.dart
**/.build/
**/*.freezed.dart
**/*.g.dart
flutter_readium/example/devtools_options.yaml
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"kotlinx",
"podfile",
"podspec",
"prefs",
"Prefs",
"readium"
]
Expand Down
3 changes: 1 addition & 2 deletions bin/forAll
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ then
fi

dir=(
"./flutter_readium"
"./flutter_readium"
"./flutter_readium_platform_interface"
"./flutter_readium_web"
)
for i in "${dir[@]}"; do
echo -e "\033[35;1m=== $@ $i ===\033[0m"
Expand Down
4 changes: 2 additions & 2 deletions flutter_readium/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ dependencies {
implementation "org.readium.kotlin-toolkit:readium-navigator-media-tts:$readium_version"
// implementation "androidx.compose.ui:ui:1.8.2" // UI
// implementation "androidx.activity:activity-compose:1.10.1" // Activity Compose integration
// implementation "org.readium.kotlin-toolkit:readium-navigator-media-audio:$readium_version"
// implementation "org.readium.kotlin-toolkit:readium-adapter-exoplayer-audio:$readium_version"
implementation "org.readium.kotlin-toolkit:readium-navigator-media-audio:$readium_version"
implementation "org.readium.kotlin-toolkit:readium-adapter-exoplayer-audio:$readium_version"
// implementation "org.readium.kotlin-toolkit:readium-adapter-pspdfkit-document:$readium_version"
// implementation "org.readium.kotlin-toolkit:readium-adapter-pspdfkit-navigator:$readium_version"
//implementation "org.readium.kotlin-toolkit:readium-lcp:$readium_version"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ class FlutterReadiumPlugin : FlutterPlugin, ActivityAware, MethodCallHandler {
}

// Setup publication channel
publicationMethodCallHandler =
PublicationMethodCallHandler(flutterPluginBinding.applicationContext)
publicationMethodCallHandler = PublicationMethodCallHandler()
publicationChannel = MethodChannel(messenger, publicationChannelName)
publicationChannel.setMethodCallHandler(publicationMethodCallHandler)

ReadiumReader.init(flutterPluginBinding.applicationContext)
}

override fun onMethodCall(call: MethodCall, result: Result) {
Expand All @@ -58,6 +59,7 @@ class FlutterReadiumPlugin : FlutterPlugin, ActivityAware, MethodCallHandler {
override fun onDetachedFromEngine(binding: FlutterPluginBinding) {
Log.d(TAG, "onDetachedFromEngine")
publicationChannel.setMethodCallHandler(null)
ReadiumReader.close()
}

private fun listAssetFiles(c: Context, rootPath: String): List<String> {
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ sealed class PublicationError(
class InvalidPublication(cause: Error) :
PublicationError(cause.message, cause.cause)

class InvalidPublicationUrl(msg: String) :
PublicationError(msg)

class Unexpected(cause: Error) :
PublicationError(cause.message, cause.cause)

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
@file:OptIn(ExperimentalReadiumApi::class)
@file:OptIn(ExperimentalReadiumApi::class, ExperimentalReadiumApi::class)

package dk.nota.flutter_readium

import android.graphics.Color
import android.util.Log
import org.json.JSONObject
import org.readium.adapter.exoplayer.audio.ExoPlayerPreferences
import org.readium.navigator.media.tts.android.AndroidTtsEngine.Voice.Id
import org.readium.navigator.media.tts.android.AndroidTtsPreferences
import org.readium.r2.navigator.Decoration
Expand All @@ -14,14 +15,20 @@ 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.util.Language
import androidx.core.graphics.toColorInt
import org.readium.r2.navigator.preferences.Configurable

private fun readiumColorFromCSS(cssColor: String): ReadiumColor {
val color = Color.parseColor(cssColor)
val color = cssColor.toColorInt()
return ReadiumColor(color)
}

fun androidTtsPreferencesFromMap(ttsPrefsMap: Map<String, Any>): AndroidTtsPreferences {
fun androidTtsPreferencesFromMap(ttsPrefsMap: Map<String, Any>?): AndroidTtsPreferences {
try {
if (ttsPrefsMap == null) {
return AndroidTtsPreferences()
}

val speed = ttsPrefsMap["speed"] as Double?
val pitch = ttsPrefsMap["pitch"] as Double?
val voiceId = ttsPrefsMap["voiceIdentifier"] as String?
Expand Down Expand Up @@ -50,8 +57,10 @@ fun decorationFromMap(decoMap: Map<String, Any>): Decoration? {
}
}

fun decorationStyleFromMap(decoMap: Map<String, String>): Decoration.Style? {
fun decorationStyleFromMap(decoMap: Map<String, String>?): Decoration.Style? {
try {
if (decoMap == null) return null

val styleStr = decoMap["style"]
val tintColorStr = decoMap["tint"]!!
val style = when (styleStr) {
Expand All @@ -72,17 +81,67 @@ fun epubPreferencesFromMap(
): EpubPreferences? {
try {
val newPreferences = EpubPreferences(
fontFamily = prefMap["fontFamily"]?.let { FontFamily(it) } ?: defaults?.fontFamily,
fontSize = prefMap["fontSize"]?.toDoubleOrNull() ?: defaults?.fontSize,
fontWeight = prefMap["fontWeight"]?.toDoubleOrNull() ?: defaults?.fontWeight,
scroll = prefMap["verticalScroll"]?.toBoolean() ?: defaults?.scroll,
backgroundColor = prefMap["backgroundColor"]?.let { readiumColorFromCSS(it) } ?: defaults?.backgroundColor,
textColor = prefMap["textColor"]?.let { readiumColorFromCSS(it) } ?: defaults?.textColor,
pageMargins = prefMap["pageMargins"]?.toDoubleOrNull() ?: defaults?.pageMargins,
fontFamily = prefMap["fontFamily"]?.let { FontFamily(it) } ?: defaults?.fontFamily,
fontSize = prefMap["fontSize"]?.toDoubleOrNull() ?: defaults?.fontSize,
fontWeight = prefMap["fontWeight"]?.toDoubleOrNull() ?: defaults?.fontWeight,
scroll = prefMap["verticalScroll"]?.toBoolean() ?: defaults?.scroll,
backgroundColor = prefMap["backgroundColor"]?.let { readiumColorFromCSS(it) } ?: defaults?.backgroundColor,
textColor = prefMap["textColor"]?.let { readiumColorFromCSS(it) } ?: defaults?.textColor,
pageMargins = prefMap["pageMargins"]?.toDoubleOrNull() ?: defaults?.pageMargins,
)
return newPreferences
} catch (ex: Exception) {
Log.e("ReadiumExtensions", "Error mapping JSONObject to EpubPreferences: $ex")
return null
}
}

@kotlinx.serialization.Serializable
public data class FlutterAudioPreferences(
val volume: Double? = null,
val pitch: Double? = null,
val speed: Double? = null,
val seekInterval: Double? = 30.0,
) : Configurable.Preferences<FlutterAudioPreferences> {

override fun plus(other: FlutterAudioPreferences): FlutterAudioPreferences =
FlutterAudioPreferences(
volume = other.volume ?: volume,
pitch = other.pitch ?: pitch,
speed = other.speed ?: speed,
seekInterval = other.seekInterval ?: seekInterval
)

fun toExoPlayerPreferences(): ExoPlayerPreferences {
return ExoPlayerPreferences(
pitch = this.pitch,
speed = this.speed
);
}

companion object {
fun fromJSON(jsonObject: JSONObject): FlutterAudioPreferences {
return FlutterAudioPreferences(
volume = jsonObject.getDouble("volume"),
pitch = jsonObject.getDouble("pitch"),
speed = jsonObject.getDouble("speed"),
seekInterval = jsonObject.getDouble("seekInterval"),
)
}
}
}

fun ExoPlayerPreferencesFromMap(
prefMap: Map<String, String>,
defaults: ExoPlayerPreferences?
): ExoPlayerPreferences? {
try {
return ExoPlayerPreferences(
pitch = prefMap["pitch"]?.toDoubleOrNull() ?: defaults?.pitch,
speed = prefMap["speed"]?.toDoubleOrNull() ?: defaults?.speed
)
} catch (ex: Exception) {
Log.e("ReadiumExtensions", "Error mapping JSONObject to ExoPlayerPreferences: $ex")
}
return null
}
Loading