Fixed lagging in downloads screen, but screen position in the epub remains broken. Updated README.md.
This commit is contained in:
@@ -213,7 +213,10 @@ fun DownloadsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
items(items) { item ->
|
||||
items(
|
||||
items = items,
|
||||
key = { it.absolutePath }
|
||||
) { item ->
|
||||
ListItem(
|
||||
headlineContent = { Text(item.name) },
|
||||
supportingContent = {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.pythonsden.ao3_.reader
|
||||
|
||||
import android.view.ViewTreeObserver
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -19,6 +20,9 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
@@ -74,12 +78,13 @@ fun ReaderScreen(
|
||||
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
|
||||
}
|
||||
is ReaderUiState.Success -> {
|
||||
var hasRestoredScroll by remember(file.absolutePath) { mutableStateOf(false) }
|
||||
|
||||
AndroidView(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
factory = { ctx ->
|
||||
WebView(ctx).apply {
|
||||
setBackgroundColor(android.graphics.Color.parseColor("#121212"))
|
||||
// Security: Disable JavaScript for EPUB reading unless strictly needed
|
||||
settings.javaScriptEnabled = false
|
||||
settings.allowFileAccess = false
|
||||
settings.allowContentAccess = false
|
||||
@@ -87,18 +92,33 @@ fun ReaderScreen(
|
||||
webViewClient = object : WebViewClient() {
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
super.onPageFinished(view, url)
|
||||
if (state.initialScroll > 0) {
|
||||
// Restore scroll position
|
||||
if (!hasRestoredScroll && state.initialScroll > 0) {
|
||||
view?.scrollTo(0, state.initialScroll)
|
||||
// Multiple attempts to ensure it works after layout
|
||||
view?.postDelayed({ view.scrollTo(0, state.initialScroll) }, 100)
|
||||
view?.postDelayed({ view.scrollTo(0, state.initialScroll) }, 300)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val layoutListener = object : ViewTreeObserver.OnGlobalLayoutListener {
|
||||
override fun onGlobalLayout() {
|
||||
if (!hasRestoredScroll && state.initialScroll > 0) {
|
||||
if (contentHeight > 0) {
|
||||
scrollTo(0, state.initialScroll)
|
||||
// If we've scrolled to or past the target, or reached bottom
|
||||
if (scrollY >= state.initialScroll || scrollY > 0) {
|
||||
hasRestoredScroll = true
|
||||
}
|
||||
}
|
||||
} else if (state.initialScroll == 0) {
|
||||
hasRestoredScroll = true
|
||||
}
|
||||
}
|
||||
}
|
||||
viewTreeObserver.addOnGlobalLayoutListener(layoutListener)
|
||||
|
||||
setOnScrollChangeListener { _, _, _, scrollY, _ ->
|
||||
viewModel.saveScrollPosition(file.absolutePath, scrollY)
|
||||
if (hasRestoredScroll) {
|
||||
viewModel.saveScrollPosition(file.absolutePath, scrollY)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2,11 +2,13 @@ package net.pythonsden.ao3_.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import net.pythonsden.ao3_.data.repository.EpubRepository
|
||||
import net.pythonsden.ao3_.data.repository.FileRepository
|
||||
import java.io.File
|
||||
@@ -46,23 +48,26 @@ class DownloadsViewModel(
|
||||
}
|
||||
|
||||
private suspend fun refreshFiles(dir: File, query: String, sort: SortOrder) {
|
||||
val allItems = fileRepository.listFiles(dir)
|
||||
val filtered = if (query.isBlank()) {
|
||||
allItems
|
||||
} else {
|
||||
allItems.filter { it.name.contains(query, ignoreCase = true) }
|
||||
}
|
||||
withContext(Dispatchers.Default) {
|
||||
val allItems = fileRepository.listFiles(dir)
|
||||
val filtered = if (query.isBlank()) {
|
||||
allItems
|
||||
} else {
|
||||
allItems.filter { it.name.contains(query, ignoreCase = true) }
|
||||
}
|
||||
|
||||
_items.value = filtered.sortedWith { f1, f2 ->
|
||||
if (f1.isDirectory && !f2.isDirectory) -1
|
||||
else if (!f1.isDirectory && f2.isDirectory) 1
|
||||
else {
|
||||
when (sort) {
|
||||
SortOrder.NAME -> f1.name.lowercase().compareTo(f2.name.lowercase())
|
||||
SortOrder.DATE -> f2.lastModified().compareTo(f1.lastModified())
|
||||
SortOrder.SIZE -> f2.length().compareTo(f1.length())
|
||||
val sorted = filtered.sortedWith { f1, f2 ->
|
||||
if (f1.isDirectory && !f2.isDirectory) -1
|
||||
else if (!f1.isDirectory && f2.isDirectory) 1
|
||||
else {
|
||||
when (sort) {
|
||||
SortOrder.NAME -> f1.name.lowercase().compareTo(f2.name.lowercase())
|
||||
SortOrder.DATE -> f2.lastModified().compareTo(f1.lastModified())
|
||||
SortOrder.SIZE -> f2.length().compareTo(f1.length())
|
||||
}
|
||||
}
|
||||
}
|
||||
_items.value = sorted
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user