From 4d9d15004cbbbc7641056ce9f1a70e5b39535a14 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Thu, 7 Dec 2023 16:01:48 +0200 Subject: [PATCH] Reader fixes --- app/build.gradle | 2 +- .../filter/ui/tags/TagsCatalogSheet.kt | 2 +- .../kotatsu/reader/ui/pager/BasePageHolder.kt | 11 ++++--- .../reader/ui/pager/standard/PageHolder.kt | 6 ++-- .../reader/ui/pager/webtoon/WebtoonHolder.kt | 26 +++++++-------- .../ui/pager/webtoon/WebtoonImageView.kt | 20 ++++++++++++ .../ui/pager/webtoon/WebtoonRecyclerView.kt | 32 +++++++++++++++++++ 7 files changed, 75 insertions(+), 24 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8338abc2d..b5a3876f1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -132,7 +132,7 @@ dependencies { implementation 'io.coil-kt:coil-base:2.5.0' implementation 'io.coil-kt:coil-svg:2.5.0' - implementation 'com.github.KotatsuApp:subsampling-scale-image-view:771c8753ae' + implementation 'com.github.KotatsuApp:subsampling-scale-image-view:02e6d6cfe9' implementation 'com.github.solkin:disk-lru-cache:1.4' implementation 'io.noties.markwon:core:4.6.2' diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/filter/ui/tags/TagsCatalogSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/filter/ui/tags/TagsCatalogSheet.kt index cbdade0cc..00e5185ca 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/filter/ui/tags/TagsCatalogSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/filter/ui/tags/TagsCatalogSheet.kt @@ -58,7 +58,7 @@ class TagsCatalogSheet : BaseAdaptiveSheet(), OnListItemClickL override fun onItemClick(item: TagCatalogItem, view: View) { val filter = (requireActivity() as FilterOwner).filter - filter.setTag(item.tag, true) + filter.setTag(item.tag, !item.isChecked) } override fun onClick(v: View) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BasePageHolder.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BasePageHolder.kt index d7e208bda..2c4827207 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BasePageHolder.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BasePageHolder.kt @@ -4,6 +4,7 @@ import android.content.Context import androidx.annotation.CallSuper import androidx.lifecycle.LifecycleOwner import androidx.viewbinding.ViewBinding +import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.os.NetworkState import org.koitharu.kotatsu.core.ui.list.lifecycle.LifecycleAwareViewHolder @@ -69,9 +70,11 @@ abstract class BasePageHolder( delegate.onRecycle() } - protected fun getBackgroundDownsampling() = when { - !settings.isReaderOptimizationEnabled -> 1 - context.isLowRamDevice() -> 8 - else -> 4 + protected fun SubsamplingScaleImageView.applyDownsampling(isForeground: Boolean) { + downsampling = when { + isForeground || !settings.isReaderOptimizationEnabled -> 1 + context.isLowRamDevice() -> 8 + else -> 4 + } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt index 29ffe1bea..e70d7b950 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt @@ -47,12 +47,12 @@ open class PageHolder( override fun onResume() { super.onResume() - binding.ssiv.downsampling = 1 + binding.ssiv.applyDownsampling(isForeground = true) } override fun onPause() { super.onPause() - binding.ssiv.downsampling = getBackgroundDownsampling() + binding.ssiv.applyDownsampling(isForeground = false) } override fun onConfigChanged() { @@ -60,7 +60,7 @@ open class PageHolder( if (settings.applyBitmapConfig(binding.ssiv)) { delegate.reload() } - binding.ssiv.downsampling = if (isResumed()) 1 else getBackgroundDownsampling() + binding.ssiv.applyDownsampling(isResumed()) } @SuppressLint("SetTextI18n") diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt index 6fc1d8432..48111be7b 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt @@ -5,7 +5,6 @@ import android.view.View import androidx.core.view.isVisible import androidx.lifecycle.LifecycleOwner import com.davemorrissey.labs.subscaleview.ImageSource -import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.os.NetworkState @@ -38,22 +37,22 @@ class WebtoonHolder( bindingInfo.buttonErrorDetails.setOnClickListener(this) } + override fun onResume() { + super.onResume() + binding.ssiv.applyDownsampling(isForeground = true) + } + + override fun onPause() { + super.onPause() + binding.ssiv.applyDownsampling(isForeground = false) + } + override fun onConfigChanged() { super.onConfigChanged() if (settings.applyBitmapConfig(binding.ssiv)) { delegate.reload() } - // FIXME binding.ssiv.downsampling = if (isResumed()) 1 else getBackgroundDownsampling() - } - - override fun onResume() { - super.onResume() - binding.ssiv.downsampling = 1 - } - - override fun onPause() { - super.onPause() - // FIXME binding.ssiv.downsampling = getBackgroundDownsampling() + binding.ssiv.applyDownsampling(isResumed()) } override fun onBind(data: ReaderPage) { @@ -97,9 +96,6 @@ class WebtoonHolder( override fun onImageShowing(settings: ReaderSettings) { binding.ssiv.colorFilter = settings.colorFilter?.toColorFilter() with(binding.ssiv) { - minimumScaleType = SubsamplingScaleImageView.SCALE_TYPE_CUSTOM - minScale = width / sWidth.toFloat() - maxScale = minScale scrollTo( when { scrollToRestore != 0 -> scrollToRestore diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt index d663fa2da..fee639014 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt @@ -88,6 +88,18 @@ class WebtoonImageView @JvmOverloads constructor( setMeasuredDimension(width, height) } + override fun onDownsamplingChanged() { + super.onDownsamplingChanged() + adjustScale() + computeScrollRange() + ancestors.firstNotNullOfOrNull { it as? WebtoonRecyclerView }?.updateChildrenScroll() + } + + override fun onReady() { + super.onReady() + adjustScale() + } + override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) if (oldh == h || oldw == 0 || oldh == 0 || scrollRange == SCROLL_UNKNOWN) return @@ -101,6 +113,8 @@ class WebtoonImageView @JvmOverloads constructor( } private fun scrollToInternal(pos: Int) { + minScale = width / sWidth.toFloat() + maxScale = minScale scrollPos = pos ct.set(sWidth / 2f, (height / 2f + pos.toFloat()) / minScale) setScaleAndCenter(minScale, ct) @@ -114,6 +128,12 @@ class WebtoonImageView @JvmOverloads constructor( scrollRange = (totalHeight - height).coerceAtLeast(0) } + private fun adjustScale() { + minScale = width / sWidth.toFloat() + maxScale = minScale + minimumScaleType = SCALE_TYPE_CUSTOM + } + private fun parentHeight(): Int { return ancestors.firstNotNullOfOrNull { it as? RecyclerView }?.height ?: 0 } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt index a8c0ff2e4..77ffa2810 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt @@ -3,9 +3,11 @@ package org.koitharu.kotatsu.reader.ui.pager.webtoon import android.content.Context import android.util.AttributeSet import android.view.View +import android.widget.Toast import androidx.core.view.ViewCompat.TYPE_TOUCH import androidx.core.view.forEach import androidx.recyclerview.widget.RecyclerView +import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.core.util.ext.findCenterViewPosition import java.util.LinkedList import java.util.WeakHashMap @@ -104,12 +106,16 @@ class WebtoonRecyclerView @JvmOverloads constructor( } private fun notifyScrollChanged(dy: Int) { + updateChildrenScroll() val listeners = onPageScrollListeners if (listeners.isNullOrEmpty()) { return } val centerPosition = findCenterViewPosition() listeners.forEach { it.dispatchScroll(this, dy, centerPosition) } + if (BuildConfig.DEBUG) { + validateLayout() + } } fun relayoutChildren() { @@ -121,6 +127,32 @@ class WebtoonRecyclerView @JvmOverloads constructor( } } + fun updateChildrenScroll() { + forEach { child -> + val ssiv = (child as WebtoonFrameLayout).target + when { + child.top < 0 -> ssiv.scrollTo(ssiv.getScrollRange()) + child.top > 0 -> ssiv.scrollTo(0) + else -> ssiv.scrollBy(0) + } + } + } + + private fun validateLayout() { + forEach { child -> + val ssiv = (child as WebtoonFrameLayout).target + val scroll = ssiv.getScroll() + val assertion = when { + child.top < 0 -> scroll == ssiv.getScrollRange() + child.top > 0 -> scroll == 0 + else -> true + } + if (!assertion) { + Toast.makeText(context, "Scroll = $scroll for view with top: ${child.top}", Toast.LENGTH_SHORT).show() + } + } + } + abstract class OnPageScrollListener { private var lastPosition = NO_POSITION