diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/entity/HistoryEntity.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/entity/HistoryEntity.kt index 31e2ffc33..43d865aad 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/db/entity/HistoryEntity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/entity/HistoryEntity.kt @@ -32,6 +32,6 @@ data class HistoryEntity( updatedAt = Date(updatedAt), chapterId = chapterId, page = page, - scroll = scroll + scroll = scroll.toInt() ) } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/MangaNotFoundException.kt b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/MangaNotFoundException.kt index be892ea64..9731f97b1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/MangaNotFoundException.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/MangaNotFoundException.kt @@ -1,5 +1,3 @@ package org.koitharu.kotatsu.core.exceptions -import java.lang.NullPointerException - class MangaNotFoundException(s: String? = null) : RuntimeException(s) \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/cache/SetCookieCache.kt b/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/cache/SetCookieCache.kt index b18e0fa0f..b9c899630 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/cache/SetCookieCache.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/cache/SetCookieCache.kt @@ -37,7 +37,7 @@ class SetCookieCache : CookieCache { override fun iterator(): MutableIterator = SetCookieCacheIterator() - private inner class SetCookieCacheIterator() : MutableIterator { + private inner class SetCookieCacheIterator : MutableIterator { private val iterator = cookies.iterator() diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/MangaHistory.kt b/app/src/main/java/org/koitharu/kotatsu/core/model/MangaHistory.kt index 001d7209c..252fa7d66 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/model/MangaHistory.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/model/MangaHistory.kt @@ -10,5 +10,5 @@ data class MangaHistory( val updatedAt: Date, val chapterId: Long, val page: Int, - val scroll: Float + val scroll: Int ) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/UserAgentInterceptor.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/UserAgentInterceptor.kt index 98891b3b5..dd00cfdc2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/UserAgentInterceptor.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/UserAgentInterceptor.kt @@ -3,7 +3,6 @@ package org.koitharu.kotatsu.core.parser import android.annotation.SuppressLint import android.os.Build import okhttp3.Interceptor -import okhttp3.Response import org.koitharu.kotatsu.BuildConfig import java.util.* diff --git a/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt b/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt index 7a79c011a..7033f4c59 100644 --- a/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt +++ b/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.domain import android.graphics.BitmapFactory +import android.net.Uri import android.util.Size import okhttp3.OkHttpClient import okhttp3.Request @@ -12,6 +13,7 @@ import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.utils.ext.await import org.koitharu.kotatsu.utils.ext.medianOrNull import java.io.InputStream +import java.util.zip.ZipFile object MangaUtils : KoinComponent { @@ -23,13 +25,22 @@ object MangaUtils : KoinComponent { try { val page = pages.medianOrNull() ?: return null val url = MangaProviderFactory.create(page.source).getPageFullUrl(page) - val client = get() - val request = Request.Builder() - .url(url) - .get() - .build() - val size = client.newCall(request).await().use { - getBitmapSize(it.body?.byteStream()) + val uri = Uri.parse(url) + val size = if (uri.scheme == "cbz") { + val zip = ZipFile(uri.schemeSpecificPart) + val entry = zip.getEntry(uri.fragment) + zip.getInputStream(entry).use { + getBitmapSize(it) + } + } else { + val client = get() + val request = Request.Builder() + .url(url) + .get() + .build() + client.newCall(request).await().use { + getBitmapSize(it.body?.byteStream()) + } } return when { size.width * 2 < size.height -> ReaderMode.WEBTOON diff --git a/app/src/main/java/org/koitharu/kotatsu/domain/history/HistoryRepository.kt b/app/src/main/java/org/koitharu/kotatsu/domain/history/HistoryRepository.kt index 5c5e388de..c22db90fb 100644 --- a/app/src/main/java/org/koitharu/kotatsu/domain/history/HistoryRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/domain/history/HistoryRepository.kt @@ -24,7 +24,7 @@ class HistoryRepository : KoinComponent { return entities.map { it.manga.toManga(it.tags.map(TagEntity::toMangaTag).toSet()) } } - suspend fun addOrUpdate(manga: Manga, chapterId: Long, page: Int, scroll: Float) { + suspend fun addOrUpdate(manga: Manga, chapterId: Long, page: Int, scroll: Int) { val tags = manga.tags.map(TagEntity.Companion::fromMangaTag) db.withTransaction { db.tagsDao.upsert(tags) @@ -36,7 +36,7 @@ class HistoryRepository : KoinComponent { updatedAt = System.currentTimeMillis(), chapterId = chapterId, page = page, - scroll = scroll + scroll = scroll.toFloat() // we migrate to int, but decide to not update database ) ) trackingRepository.upsert(manga) @@ -45,15 +45,7 @@ class HistoryRepository : KoinComponent { } suspend fun getOne(manga: Manga): MangaHistory? { - return db.historyDao.find(manga.id)?.let { - MangaHistory( - createdAt = Date(it.createdAt), - updatedAt = Date(it.updatedAt), - chapterId = it.chapterId, - page = it.page, - scroll = it.scroll - ) - } + return db.historyDao.find(manga.id)?.toMangaHistory() } suspend fun clear() { diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/common/AlertDialogFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/common/AlertDialogFragment.kt index 6d3e52ce8..573c9728e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/common/AlertDialogFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/common/AlertDialogFragment.kt @@ -5,7 +5,6 @@ import android.os.Bundle import android.view.View import androidx.annotation.LayoutRes import androidx.appcompat.app.AlertDialog -import androidx.fragment.app.DialogFragment import moxy.MvpAppCompatDialogFragment abstract class AlertDialogFragment(@LayoutRes private val layoutResId: Int) : MvpAppCompatDialogFragment() { diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt index af4802030..246c32a9f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt @@ -139,7 +139,16 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView, if (chaptersCount > 5) { AlertDialog.Builder(this) .setTitle(R.string.save_manga) - .setMessage(getString(R.string.large_manga_save_confirm, chaptersCount)) + .setMessage( + getString( + R.string.large_manga_save_confirm, + resources.getQuantityString( + R.plurals.chapters, + chaptersCount, + chaptersCount + ) + ) + ) .setNegativeButton(android.R.string.cancel, null) .setPositiveButton(R.string.save) { _, _ -> DownloadService.start(this, it) @@ -174,7 +183,7 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView, } override fun onConfigureTab(tab: TabLayout.Tab, position: Int) { - tab.text = when(position) { + tab.text = when (position) { 0 -> getString(R.string.details) 1 -> getString(R.string.chapters) else -> null diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsFragment.kt index fd0f868fe..acd0cbb98 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsFragment.kt @@ -123,8 +123,8 @@ class MangaDetailsFragment : BaseFragment(R.layout.fragment_details), MangaDetai } override fun onLongClick(v: View): Boolean { - when { - v.id == R.id.button_read -> { + when (v.id) { + R.id.button_read -> { if (history == null) { return false } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/MainView.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/MainView.kt index 8d39aeb5e..45859cd12 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/MainView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/MainView.kt @@ -1,7 +1,6 @@ package org.koitharu.kotatsu.ui.main import moxy.viewstate.strategy.alias.OneExecution -import org.koitharu.kotatsu.core.model.MangaState import org.koitharu.kotatsu.ui.common.BaseMvpView import org.koitharu.kotatsu.ui.reader.ReaderState diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt index 14c41b905..944122404 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt @@ -212,7 +212,7 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh } } - override fun saveState(chapterId: Long, page: Int, scroll: Float) { + override fun saveState(chapterId: Long, page: Int, scroll: Int) { state = state.copy(chapterId = chapterId, page = page, scroll = scroll) ReaderPresenter.saveState(state) } @@ -311,7 +311,7 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh state = state.copy( chapterId = chapter.id, page = 0, - scroll = 0f + scroll = 0 ) reader?.updateState(chapterId = chapter.id) } @@ -395,7 +395,7 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh chapterId = if (chapterId == -1L) manga.chapters?.firstOrNull()?.id ?: -1 else chapterId, page = 0, - scroll = 0f + scroll = 0 ) ) diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderListener.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderListener.kt index fe21280f1..83d30a546 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderListener.kt @@ -7,5 +7,5 @@ interface ReaderListener : BaseMvpView { fun onPageChanged(chapter: MangaChapter, page: Int, total: Int) - fun saveState(chapterId: Long, page: Int, scroll: Float) + fun saveState(chapterId: Long, page: Int, scroll: Int) } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderState.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderState.kt index 4784f3507..fe7c1edaa 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderState.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderState.kt @@ -11,7 +11,7 @@ data class ReaderState( val manga: Manga, val chapterId: Long, val page: Int, - val scroll: Float + val scroll: Int ) : Parcelable { @IgnoredOnParcel diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/base/AbstractReader.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/base/AbstractReader.kt index 1404ed3b4..8050fc518 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/base/AbstractReader.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/base/AbstractReader.kt @@ -54,7 +54,7 @@ abstract class AbstractReader(contentLayoutId: Int) : BaseFragment(contentLayout pages.addLast(state.chapterId, it) adapter?.notifyDataSetChanged() setCurrentItem(state.page, false) - if (state.scroll != 0f) { + if (state.scroll != 0) { restorePageScroll(state.page, state.scroll) } } @@ -196,7 +196,7 @@ abstract class AbstractReader(contentLayoutId: Int) : BaseFragment(contentLayout if (pageId == 0L) { 0 } else { - it.indexOfFirst { it.id == pageId }.coerceAtLeast(0) + it.indexOfFirst { x -> x.id == pageId }.coerceAtLeast(0) }, false ) } @@ -217,9 +217,9 @@ abstract class AbstractReader(contentLayoutId: Int) : BaseFragment(contentLayout protected abstract fun getCurrentItem(): Int - protected abstract fun getCurrentPageScroll(): Float + protected abstract fun getCurrentPageScroll(): Int - protected abstract fun restorePageScroll(position: Int, scroll: Float) + protected abstract fun restorePageScroll(position: Int, scroll: Int) protected abstract fun setCurrentItem(position: Int, isSmooth: Boolean) diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/standard/PagerReaderFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/standard/PagerReaderFragment.kt index a0168839d..029178d02 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/standard/PagerReaderFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/standard/PagerReaderFragment.kt @@ -62,9 +62,9 @@ class PagerReaderFragment : AbstractReader(R.layout.fragment_reader_standard), pager.setCurrentItem(position, isSmooth) } - override fun getCurrentPageScroll() = 0f + override fun getCurrentPageScroll() = 0 - override fun restorePageScroll(position: Int, scroll: Float) = Unit + override fun restorePageScroll(position: Int, scroll: Int) = Unit override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { when (key) { diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonFrameLayout.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonFrameLayout.kt index 2ba743b90..a6f1ec906 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonFrameLayout.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonFrameLayout.kt @@ -13,5 +13,12 @@ class WebtoonFrameLayout @JvmOverloads constructor( findViewById(R.id.ssiv) } - fun dispatchVerticalScroll(dy: Int) = target.dispatchVerticalScroll(dy) + fun dispatchVerticalScroll(dy: Int): Int { + if (dy == 0) { + return 0 + } + val oldScroll = target.getScroll() + target.scrollBy(dy) + return target.getScroll() - oldScroll + } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonHolder.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonHolder.kt index 481940d17..81fbba487 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonHolder.kt @@ -1,6 +1,5 @@ package org.koitharu.kotatsu.ui.reader.wetoon -import android.graphics.PointF import android.view.ViewGroup import androidx.core.net.toUri import androidx.core.view.isVisible @@ -21,7 +20,7 @@ class WebtoonHolder(parent: ViewGroup, private val loader: PageLoader) : SubsamplingScaleImageView.OnImageEventListener, CoroutineScope by loader { private var job: Job? = null - private var scrollToRestore = 0f + private var scrollToRestore = 0 init { ssiv.setOnImageEventListener(this) @@ -36,7 +35,7 @@ class WebtoonHolder(parent: ViewGroup, private val loader: PageLoader) : private fun doLoad(data: MangaPage, force: Boolean) { job?.cancel() - scrollToRestore = 0f + scrollToRestore = 0 job = launch { layout_error.isVisible = false progressBar.isVisible = true @@ -60,17 +59,11 @@ class WebtoonHolder(parent: ViewGroup, private val loader: PageLoader) : ssiv.recycle() } - fun getScrollY() = ssiv.center?.y ?: 0f + fun getScrollY() = ssiv.getScroll() - fun restoreScroll(scroll: Float) { + fun restoreScroll(scroll: Int) { if (ssiv.isReady) { - ssiv.setScaleAndCenter( - ssiv.scale, - PointF( - ssiv.sWidth / 2f, - scroll - ) - ) + ssiv.scrollTo(scroll) } else { scrollToRestore = scroll } @@ -80,17 +73,11 @@ class WebtoonHolder(parent: ViewGroup, private val loader: PageLoader) : ssiv.maxScale = 2f * ssiv.width / ssiv.sWidth.toFloat() ssiv.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CUSTOM) ssiv.minScale = ssiv.width / ssiv.sWidth.toFloat() - ssiv.setScaleAndCenter( - ssiv.minScale, - PointF( - ssiv.sWidth / 2f, - when { - scrollToRestore != 0f -> scrollToRestore - itemView.top < 0 -> ssiv.sHeight.toFloat() - else -> 0f - } - ) - ) + ssiv.scrollTo(when { + scrollToRestore != 0 -> scrollToRestore + itemView.top < 0 -> ssiv.getScrollRange() + else -> 0 + }) } override fun onImageLoadError(e: Exception) = onError(e) diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonImageView.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonImageView.kt index 7749de6e5..9414818a6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonImageView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonImageView.kt @@ -2,42 +2,66 @@ package org.koitharu.kotatsu.ui.reader.wetoon import android.content.Context import android.graphics.PointF -import android.graphics.RectF import android.util.AttributeSet import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import org.koitharu.kotatsu.utils.ext.toIntUp -class WebtoonImageView : SubsamplingScaleImageView { +class WebtoonImageView @JvmOverloads constructor(context: Context, attr: AttributeSet? = null) : + SubsamplingScaleImageView(context, attr) { - constructor(context: Context?) : super(context) - constructor(context: Context?, attr: AttributeSet?) : super(context, attr) - - private val pan = RectF() private val ct = PointF() - fun dispatchVerticalScroll(dy: Int): Int { + private var scrollPos = 0 + private var scrollRange = SCROLL_UNKNOWN + + fun scrollBy(delta: Int) { + val maxScroll = getScrollRange() + if (maxScroll == 0) { + return + } + val newScroll = scrollPos + delta + scrollToInternal(newScroll.coerceIn(0, maxScroll)) + } + + fun scrollTo(y: Int) { + val maxScroll = getScrollRange() + if (maxScroll == 0) { + return + } + scrollToInternal(y.coerceIn(0, maxScroll)) + } + + fun getScroll() = scrollPos + + fun getScrollRange(): Int { + if (scrollRange == SCROLL_UNKNOWN) { + computeScrollRange() + } + return scrollRange.coerceAtLeast(0) + } + + override fun recycle() { + scrollRange = SCROLL_UNKNOWN + scrollPos = 0 + super.recycle() + } + + private fun scrollToInternal(pos: Int) { + scrollPos = pos + ct.set(sWidth / 2f, (height / 2f + pos.toFloat()) / minScale) + setScaleAndCenter(minScale, ct) + } + + private fun computeScrollRange() { if (!isReady) { - return 0 - } - getPanRemaining(pan) - // pan.offset(0f, -nonConsumedScroll.toFloat()) - ct.set(width / 2f, height / 2f) - viewToSourceCoord(ct.x, ct.y, ct) ?: return 0 - val s = scale - return when { - dy > 0 -> { - val delta = minOf(pan.bottom.toIntUp(), dy) - ct.offset(0f, delta.toFloat() / s) - setScaleAndCenter(s, ct) - delta - } - dy < 0 -> { - val delta = minOf(pan.top.toInt(), -dy) - ct.offset(0f, -delta.toFloat() / s) - setScaleAndCenter(s, ct) - -delta - } - else -> 0 + return } + val totalHeight = (sHeight * minScale).toIntUp() + scrollRange = (totalHeight - height).coerceAtLeast(0) + } + + private companion object { + + const val SCROLL_UNKNOWN = -1 } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonReaderFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonReaderFragment.kt index 0df208e4e..ed2fca011 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonReaderFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonReaderFragment.kt @@ -61,12 +61,12 @@ class WebtoonReaderFragment : AbstractReader(R.layout.fragment_reader_webtoon) { ) } - override fun getCurrentPageScroll(): Float { + override fun getCurrentPageScroll(): Int { return (recyclerView.findViewHolderForAdapterPosition(getCurrentItem()) as? WebtoonHolder) - ?.getScrollY() ?: 0f + ?.getScrollY() ?: 0 } - override fun restorePageScroll(position: Int, scroll: Float) { + override fun restorePageScroll(position: Int, scroll: Int) { recyclerView.post { val holder = recyclerView.findViewHolderForAdapterPosition(position) ?: return@post (holder as WebtoonHolder).restoreScroll(scroll) diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonRecyclerView.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonRecyclerView.kt index 68287403e..e898f7637 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonRecyclerView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonRecyclerView.kt @@ -3,7 +3,6 @@ package org.koitharu.kotatsu.ui.reader.wetoon import android.content.Context import android.util.AttributeSet import androidx.core.view.ViewCompat -import androidx.core.view.children import androidx.recyclerview.widget.RecyclerView class WebtoonRecyclerView @JvmOverloads constructor( @@ -39,13 +38,39 @@ class WebtoonRecyclerView @JvmOverloads constructor( } private fun consumeVerticalScroll(dy: Int): Int { - val child = when { - dy > 0 -> children.firstOrNull { it is WebtoonFrameLayout } - dy < 0 -> children.lastOrNull { it is WebtoonFrameLayout } - else -> null - } ?: return 0 - var scrollY = dy - scrollY -= (child as WebtoonFrameLayout).dispatchVerticalScroll(scrollY) - return dy - scrollY + if (childCount == 0) { + return 0 + } + when { + dy > 0 -> { + val child = getChildAt(0) as WebtoonFrameLayout + var consumedByChild = child.dispatchVerticalScroll(dy) + if (consumedByChild < dy) { + if (childCount > 1) { + val nextChild = getChildAt(1) as WebtoonFrameLayout + val unconsumed = dy - consumedByChild - nextChild.top //will be consumed by scroll + if (unconsumed > 0) { + consumedByChild += nextChild.dispatchVerticalScroll(unconsumed) + } + } + } + return consumedByChild + } + dy < 0 -> { + val child = getChildAt(childCount - 1) as WebtoonFrameLayout + var consumedByChild = child.dispatchVerticalScroll(dy) + if (consumedByChild > dy) { + if (childCount > 1) { + val nextChild = getChildAt(childCount - 2) as WebtoonFrameLayout + val unconsumed = dy - consumedByChild + (height - nextChild.bottom) //will be consumed by scroll + if (unconsumed < 0) { + consumedByChild += nextChild.dispatchVerticalScroll(unconsumed) + } + } + } + return consumedByChild + } + } + return 0 } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/settings/AppUpdateService.kt b/app/src/main/java/org/koitharu/kotatsu/ui/settings/AppUpdateService.kt index 2cec9ce62..94d0d97fb 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/settings/AppUpdateService.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/settings/AppUpdateService.kt @@ -164,7 +164,7 @@ class AppUpdateService : BaseService() { } return try { val md: MessageDigest = MessageDigest.getInstance("SHA1") - val publicKey: ByteArray = md.digest(c.getEncoded()) + val publicKey: ByteArray = md.digest(c.encoded) publicKey.byte2HexFormatted() } catch (e: NoSuchAlgorithmException) { e.printStackTrace() diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/DateExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/DateExt.kt index 830ff2fa7..51c1caf41 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/DateExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/DateExt.kt @@ -3,7 +3,6 @@ package org.koitharu.kotatsu.utils.ext import android.annotation.SuppressLint import java.text.SimpleDateFormat import java.util.* -import java.util.concurrent.TimeUnit @SuppressLint("SimpleDateFormat") fun Date.format(pattern: String): String = SimpleDateFormat(pattern).format(this) diff --git a/app/src/main/res/layout/item_page_webtoon.xml b/app/src/main/res/layout/item_page_webtoon.xml index 36fd63de9..51e72ea1d 100644 --- a/app/src/main/res/layout/item_page_webtoon.xml +++ b/app/src/main/res/layout/item_page_webtoon.xml @@ -10,6 +10,8 @@ android:id="@+id/ssiv" android:layout_width="match_parent" android:layout_height="match_parent" + app:zoomEnabled="false" + app:quickScaleEnabled="false" app:panEnabled="false" /> - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/values-ru/plurals.xml b/app/src/main/res/values-ru/plurals.xml index e429b244f..3c7479fe7 100644 --- a/app/src/main/res/values-ru/plurals.xml +++ b/app/src/main/res/values-ru/plurals.xml @@ -15,6 +15,11 @@ %1$d новых главы %1$d новых глав + + %1$d глава + %1$d главы + %1$d глав + %1$d глава из %2$d %1$d главы из %2$d diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 5e8e03390..0241cf46a 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -102,7 +102,7 @@ Доступно обновление приложения Показывать уведомление при наличии новой версии Открыть в браузере - В этой манге %d глав. Вы уверены, что хотите сохранить их все? + В этой манге %s. Вы уверены, что хотите сохранить их все? Сохранить мангу Уведомления Включено %1$d из %2$d diff --git a/app/src/main/res/values/plurals.xml b/app/src/main/res/values/plurals.xml index b8688fe55..713132a02 100644 --- a/app/src/main/res/values/plurals.xml +++ b/app/src/main/res/values/plurals.xml @@ -12,6 +12,10 @@ %1$d new chapter %1$d new chapters + + %1$d chapter + %1$d chapters + %1$d chapter from %2$d %1$d chapters from %2$d diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index af289b312..fe78a9a74 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,4 +1,4 @@ - + Kotatsu Close menu Open menu @@ -103,10 +103,10 @@ Application update is available Show notification if update is available Open in browser - This manga has %d chapters. Do you want to save all of it? + This manga has %s. Do you want to save all of it? Save manga Notifications - Enabled %1$d from %2$d + Enabled %1$d from %2$d New chapters Notify about updates of manga you are reading Download