Added screen position saving in the epub reader
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -786,4 +813,4 @@ fun openFile(context: Context, file: File) {
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(context, "No app found to open this file", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user