Fix crashes and improve predictive back support

This commit is contained in:
Koitharu
2024-05-25 10:14:39 +03:00
parent a7e2cfc878
commit 2ae488544b
10 changed files with 56 additions and 22 deletions

View File

@@ -94,6 +94,7 @@ dependencies {
implementation 'androidx.core:core-ktx:1.13.1'
implementation 'androidx.activity:activity-ktx:1.9.0'
implementation 'androidx.fragment:fragment-ktx:1.7.1'
implementation 'androidx.transition:transition-ktx:1.5.0'
implementation 'androidx.collection:collection-ktx:1.4.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.0'
implementation 'androidx.lifecycle:lifecycle-service:2.8.0'

View File

@@ -108,8 +108,10 @@ class BrowserActivity : BaseActivity<ActivityBrowserBinding>(), BrowserCallback
override fun onDestroy() {
super.onDestroy()
viewBinding.webView.stopLoading()
viewBinding.webView.destroy()
if (hasViewBinding()) {
viewBinding.webView.stopLoading()
viewBinding.webView.destroy()
}
}
override fun onLoadingStateChanged(isLoading: Boolean) {

View File

@@ -16,6 +16,7 @@ import okhttp3.OkHttpClient
import okhttp3.Response
import okhttp3.ResponseBody.Companion.asResponseBody
import okio.Buffer
import okio.IOException
import org.koitharu.kotatsu.core.network.MangaHttpClient
import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar
import org.koitharu.kotatsu.core.prefs.SourceSettings
@@ -29,6 +30,7 @@ import org.koitharu.kotatsu.parsers.bitmap.Bitmap
import org.koitharu.kotatsu.parsers.config.MangaSourceConfig
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.network.UserAgents
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
import java.lang.ref.WeakReference
import java.util.Locale
import javax.inject.Inject
@@ -75,7 +77,10 @@ class MangaLoaderContextImpl @Inject constructor(
return LocaleListCompat.getAdjustedDefault().toList()
}
override fun redrawImageResponse(response: Response, redraw: (image: Bitmap) -> Bitmap): Response {
override fun redrawImageResponse(
response: Response,
redraw: (image: Bitmap) -> Bitmap
): Response = runCatchingCancellable {
val image = response.requireBody().byteStream()
val opts = BitmapFactory.Options()
@@ -87,9 +92,15 @@ class MangaLoaderContextImpl @Inject constructor(
result.compressTo(it.outputStream())
}.asResponseBody("image/jpeg".toMediaType())
return response.newBuilder()
response.newBuilder()
.body(body)
.build()
}.getOrElse { error ->
if (error is IOException) {
throw error
} else {
throw IOException(error.message, error)
}
}
override fun createBitmap(width: Int, height: Int): Bitmap {

View File

@@ -92,9 +92,6 @@ abstract class BaseActivity<B : ViewBinding> :
}
override fun onSupportNavigateUp(): Boolean {
if (supportFragmentManager.popBackStackImmediate()) {
return false
}
dispatchNavigateUp()
return true
}
@@ -159,6 +156,8 @@ abstract class BaseActivity<B : ViewBinding> :
}
}
protected fun hasViewBinding() = ::viewBinding.isInitialized
@EntryPoint
@InstallIn(SingletonComponent::class)
interface BaseActivityEntryPoint {

View File

@@ -1,22 +1,34 @@
package org.koitharu.kotatsu.core.ui.sheet
import android.annotation.SuppressLint
import android.view.View
import android.view.ViewGroup
import androidx.activity.BackEventCompat
import androidx.activity.OnBackPressedCallback
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_COLLAPSED
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HALF_EXPANDED
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN
class BottomSheetCollapseCallback(
private val behavior: BottomSheetBehavior<*>,
) : OnBackPressedCallback(behavior.state == STATE_EXPANDED) {
private val sheet: ViewGroup,
private val behavior: BottomSheetBehavior<*> = BottomSheetBehavior.from(sheet),
) : OnBackPressedCallback(behavior.state == STATE_EXPANDED || behavior.state == STATE_HALF_EXPANDED) {
init {
behavior.addBottomSheetCallback(
object : BottomSheetBehavior.BottomSheetCallback() {
@SuppressLint("SwitchIntDef")
override fun onStateChanged(view: View, state: Int) {
isEnabled = state == STATE_EXPANDED || state == STATE_HALF_EXPANDED
when (state) {
STATE_EXPANDED,
STATE_HALF_EXPANDED -> isEnabled = true
STATE_COLLAPSED,
STATE_HIDDEN -> isEnabled = false
}
}
override fun onSlide(p0: View, p1: Float) = Unit
@@ -24,7 +36,11 @@ class BottomSheetCollapseCallback(
)
}
override fun handleOnBackPressed() {
behavior.state = STATE_COLLAPSED
}
override fun handleOnBackPressed() = behavior.handleBackInvoked()
override fun handleOnBackCancelled() = behavior.cancelBackProgress()
override fun handleOnBackProgressed(backEvent: BackEventCompat) = behavior.updateBackProgress(backEvent)
override fun handleOnBackStarted(backEvent: BackEventCompat) = behavior.startBackProgress(backEvent)
}

View File

@@ -31,7 +31,6 @@ import coil.request.ImageRequest
import coil.request.SuccessResult
import coil.transform.CircleCropTransformation
import coil.util.CoilUtils
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.chip.Chip
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
@@ -153,8 +152,8 @@ class DetailsActivity :
viewBinding.textViewDescription.movementMethod = LinkMovementMethodCompat.getInstance()
viewBinding.chipsTags.onChipClickListener = this
TitleScrollCoordinator(viewBinding.textViewTitle).attach(viewBinding.scrollView)
viewBinding.containerBottomSheet?.let { BottomSheetBehavior.from(it) }?.let { behavior ->
onBackPressedDispatcher.addCallback(BottomSheetCollapseCallback(behavior))
viewBinding.containerBottomSheet?.let { sheet ->
onBackPressedDispatcher.addCallback(BottomSheetCollapseCallback(sheet))
}
viewModel.details.filterNotNull().observe(this, ::onMangaUpdated)

View File

@@ -125,7 +125,7 @@ class SettingsActivity :
supportFragmentManager.commit {
setReorderingAllowed(true)
replace(R.id.container, fragment)
setTransition(FragmentTransaction.TRANSIT_FRAGMENT_MATCH_ACTIVITY_OPEN)
setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
if (!isMasterDetails || (hasFragment && !isFromRoot)) {
addToBackStack(null)
}

View File

@@ -11,7 +11,6 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.viewModels
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
@@ -41,7 +40,13 @@ class MangaDirectorySelectDialog : AlertDialogFragment<DialogDirectorySelectBind
) {
if (it) {
viewModel.refresh()
pickFileTreeLauncher.launch(null)
if (!pickFileTreeLauncher.tryLaunch(null)) {
Toast.makeText(
context ?: return@registerForActivityResult,
R.string.operation_not_supported,
Toast.LENGTH_SHORT,
).show()
}
}
}

View File

@@ -68,7 +68,7 @@
tools:text="@string/appearance" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/container"
android:id="@id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@@ -9,12 +9,13 @@
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="true"
app:liftOnScroll="false">
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_height="wrap_content"
app:layout_collapseMode="pin" />
</com.google.android.material.appbar.AppBarLayout>