Added screen position saving in the epub reader
This commit is contained in:
Generated
+1
-1
@@ -4,7 +4,7 @@
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2026-03-22T22:43:40.813806872Z">
|
||||
<DropdownSelection timestamp="2026-03-22T23:16:51.147475690Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
<handle>
|
||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=42011JEKB06640" />
|
||||
|
||||
Generated
+1
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
|
||||
Generated
-1
@@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||
|
||||
@@ -42,6 +42,7 @@ android {
|
||||
dependencies {
|
||||
implementation(libs.androidx.core.ktx)
|
||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||
implementation(libs.androidx.lifecycle.runtime.compose)
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(platform(libs.androidx.compose.bom))
|
||||
implementation(libs.androidx.compose.ui)
|
||||
|
||||
Binary file not shown.
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"version": 3,
|
||||
"artifactType": {
|
||||
"type": "APK",
|
||||
"kind": "Directory"
|
||||
},
|
||||
"applicationId": "net.pythonsden.ao3_",
|
||||
"variantName": "debug",
|
||||
"elements": [
|
||||
{
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"attributes": [],
|
||||
"versionCode": 1,
|
||||
"versionName": "1.0",
|
||||
"outputFile": "app-debug.apk"
|
||||
}
|
||||
],
|
||||
"elementType": "File",
|
||||
"minSdkVersionForDexing": 24
|
||||
}
|
||||
@@ -72,6 +72,9 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavGraph.Companion.findStartDestination
|
||||
import androidx.navigation.NavType
|
||||
@@ -165,7 +168,8 @@ fun MainScreen() {
|
||||
if (lastRoute == "reader/{filePath}") {
|
||||
val lastEpubPath = prefs.getString("last_epub_path", null)
|
||||
if (lastEpubPath != null) {
|
||||
navController.navigate("reader/$lastEpubPath")
|
||||
val encoded = URLEncoder.encode(lastEpubPath, StandardCharsets.UTF_8.toString())
|
||||
navController.navigate("reader/$encoded")
|
||||
}
|
||||
} else if (!isOfflineMode || lastRoute == Screen.Downloads.route) {
|
||||
navController.navigate(lastRoute) {
|
||||
@@ -678,6 +682,7 @@ fun DownloadsScreen(navController: NavController, modifier: Modifier = Modifier)
|
||||
@Composable
|
||||
fun EpubReaderScreen(file: File, navController: NavController) {
|
||||
val context = LocalContext.current
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
val prefs = remember { context.getSharedPreferences("ao3_prefs", Context.MODE_PRIVATE) }
|
||||
val scrollKey = "scroll_${file.absolutePath}"
|
||||
|
||||
@@ -685,18 +690,30 @@ fun EpubReaderScreen(file: File, navController: NavController) {
|
||||
var title by remember { mutableStateOf("Reading...") }
|
||||
var webViewRef by remember { mutableStateOf<WebView?>(null) }
|
||||
|
||||
// Save scroll position
|
||||
DisposableEffect(file.absolutePath) {
|
||||
onDispose {
|
||||
webViewRef?.let { wv ->
|
||||
val scrollY = wv.scrollY
|
||||
if (scrollY > 0) {
|
||||
prefs.edit().putInt(scrollKey, scrollY).apply()
|
||||
}
|
||||
// Helper function to save scroll
|
||||
fun saveScroll(wv: WebView?) {
|
||||
wv?.let {
|
||||
val scrollY = it.scrollY
|
||||
if (scrollY > 0) {
|
||||
prefs.edit().putInt(scrollKey, scrollY).apply()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save scroll position on pause or dispose
|
||||
DisposableEffect(lifecycleOwner, file.absolutePath, webViewRef) {
|
||||
val observer = LifecycleEventObserver { _, event ->
|
||||
if (event == Lifecycle.Event.ON_PAUSE) {
|
||||
saveScroll(webViewRef)
|
||||
}
|
||||
}
|
||||
lifecycleOwner.lifecycle.addObserver(observer)
|
||||
onDispose {
|
||||
saveScroll(webViewRef)
|
||||
lifecycleOwner.lifecycle.removeObserver(observer)
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(file) {
|
||||
try {
|
||||
val book: Book = EpubReader().readEpub(FileInputStream(file))
|
||||
@@ -759,17 +776,27 @@ fun EpubReaderScreen(file: File, navController: NavController) {
|
||||
super.onPageFinished(view, url)
|
||||
val lastScroll = prefs.getInt(scrollKey, 0)
|
||||
if (lastScroll > 0) {
|
||||
view?.post {
|
||||
view.scrollTo(0, lastScroll)
|
||||
}
|
||||
// Try scrolling after several delays to ensure layout is done
|
||||
view?.postDelayed({ view.scrollTo(0, lastScroll) }, 100)
|
||||
view?.postDelayed({ view.scrollTo(0, lastScroll) }, 300)
|
||||
view?.postDelayed({ view.scrollTo(0, lastScroll) }, 600)
|
||||
}
|
||||
}
|
||||
}
|
||||
setOnScrollChangeListener { _, _, _, scrollY, _ ->
|
||||
if (scrollY > 0) {
|
||||
prefs.edit().putInt(scrollKey, scrollY).apply()
|
||||
}
|
||||
}
|
||||
webViewRef = this
|
||||
}
|
||||
},
|
||||
update = { webView ->
|
||||
webView.loadDataWithBaseURL(null, htmlContent, "text/html", "UTF-8", null)
|
||||
// Avoid reloading if content is the same
|
||||
if (webView.tag != htmlContent && htmlContent.isNotBlank()) {
|
||||
webView.loadDataWithBaseURL(null, htmlContent, "text/html", "UTF-8", null)
|
||||
webView.tag = htmlContent
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ junit = "4.13.2"
|
||||
junitVersion = "1.1.5"
|
||||
espressoCore = "3.5.1"
|
||||
lifecycleRuntimeKtx = "2.6.1"
|
||||
lifecycleRuntimeCompose = "2.6.1"
|
||||
activityCompose = "1.8.0"
|
||||
kotlin = "2.2.10"
|
||||
composeBom = "2024.09.00"
|
||||
@@ -17,6 +18,7 @@ junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
|
||||
androidx-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycleRuntimeCompose" }
|
||||
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
|
||||
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
|
||||
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }
|
||||
|
||||
Reference in New Issue
Block a user