mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
revert: Revert PagerPageHolder refactor
This commit is contained in:
parent
2a95f3d60d
commit
a2a36ca839
1 changed files with 207 additions and 74 deletions
|
@ -33,13 +33,11 @@ import eu.kanade.tachiyomi.util.system.ImageUtil.isPagePadded
|
||||||
import eu.kanade.tachiyomi.util.system.ThemeUtil
|
import eu.kanade.tachiyomi.util.system.ThemeUtil
|
||||||
import eu.kanade.tachiyomi.util.system.bottomCutoutInset
|
import eu.kanade.tachiyomi.util.system.bottomCutoutInset
|
||||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||||
import eu.kanade.tachiyomi.util.system.e
|
|
||||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||||
import eu.kanade.tachiyomi.util.system.isInNightMode
|
import eu.kanade.tachiyomi.util.system.isInNightMode
|
||||||
import eu.kanade.tachiyomi.util.system.launchIO
|
import eu.kanade.tachiyomi.util.system.launchIO
|
||||||
import eu.kanade.tachiyomi.util.system.launchUI
|
import eu.kanade.tachiyomi.util.system.launchUI
|
||||||
import eu.kanade.tachiyomi.util.system.topCutoutInset
|
import eu.kanade.tachiyomi.util.system.topCutoutInset
|
||||||
import eu.kanade.tachiyomi.util.system.withIOContext
|
|
||||||
import eu.kanade.tachiyomi.util.system.withUIContext
|
import eu.kanade.tachiyomi.util.system.withUIContext
|
||||||
import eu.kanade.tachiyomi.util.view.backgroundColor
|
import eu.kanade.tachiyomi.util.view.backgroundColor
|
||||||
import eu.kanade.tachiyomi.util.view.isVisibleOnScreen
|
import eu.kanade.tachiyomi.util.view.isVisibleOnScreen
|
||||||
|
@ -50,13 +48,13 @@ import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.supervisorScope
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import okio.Buffer
|
import okio.Buffer
|
||||||
import okio.BufferedSource
|
import okio.BufferedSource
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View of the ViewPager that contains a page of a chapter.
|
* View of the ViewPager that contains a page of a chapter.
|
||||||
|
@ -89,12 +87,41 @@ class PagerPageHolder(
|
||||||
*/
|
*/
|
||||||
private var loadJob: Job? = null
|
private var loadJob: Job? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Job for status changes of the page.
|
||||||
|
*/
|
||||||
|
private var statusJob: Job? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Job for progress changes of the page.
|
||||||
|
*/
|
||||||
|
private var progressJob: Job? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Job for loading the page.
|
* Job for loading the page.
|
||||||
*/
|
*/
|
||||||
private var extraLoadJob: Job? = null
|
private var extraLoadJob: Job? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Job for status changes of the page.
|
||||||
|
*/
|
||||||
|
private var extraStatusJob: Job? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Job for progress changes of the page.
|
||||||
|
*/
|
||||||
|
private var extraProgressJob: Job? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Job used to read the header of the image. This is needed in order to instantiate
|
||||||
|
* the appropriate image view depending if the image is animated (GIF).
|
||||||
|
*/
|
||||||
|
private var readImageHeaderJob: Job? = null
|
||||||
|
|
||||||
private var status = Page.State.READY
|
private var status = Page.State.READY
|
||||||
|
private var extraStatus = Page.State.READY
|
||||||
|
private var progress: Int = 0
|
||||||
|
private var extraProgress: Int = 0
|
||||||
|
|
||||||
private var scope = MainScope()
|
private var scope = MainScope()
|
||||||
|
|
||||||
|
@ -105,8 +132,7 @@ class PagerPageHolder(
|
||||||
marginStart = ((context.resources.displayMetrics.widthPixels) / 2 + viewer.config.hingeGapSize) / 2
|
marginStart = ((context.resources.displayMetrics.widthPixels) / 2 + viewer.config.hingeGapSize) / 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadJob = scope.launch { loadPageAndProcessStatus(1) }
|
launchLoadJob()
|
||||||
extraLoadJob = scope.launch { loadPageAndProcessStatus(2) }
|
|
||||||
setBackgroundColor(
|
setBackgroundColor(
|
||||||
when (val theme = viewer.config.readerTheme) {
|
when (val theme = viewer.config.readerTheme) {
|
||||||
ReaderBackgroundColor.SMART_THEME.prefValue -> Color.TRANSPARENT
|
ReaderBackgroundColor.SMART_THEME.prefValue -> Color.TRANSPARENT
|
||||||
|
@ -163,15 +189,64 @@ class PagerPageHolder(
|
||||||
*/
|
*/
|
||||||
override fun onDetachedFromWindow() {
|
override fun onDetachedFromWindow() {
|
||||||
super.onDetachedFromWindow()
|
super.onDetachedFromWindow()
|
||||||
|
cancelProgressJob(1)
|
||||||
loadJob?.cancel()
|
cancelLoadJob(1)
|
||||||
loadJob = null
|
cancelProgressJob(2)
|
||||||
extraLoadJob?.cancel()
|
cancelLoadJob(2)
|
||||||
extraLoadJob = null
|
cancelReadImageHeader()
|
||||||
|
|
||||||
(pageView as? SubsamplingScaleImageView)?.setOnImageEventListener(null)
|
(pageView as? SubsamplingScaleImageView)?.setOnImageEventListener(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts loading the page and processing changes to the page's status.
|
||||||
|
*
|
||||||
|
* @see processStatus
|
||||||
|
*/
|
||||||
|
private fun launchLoadJob() {
|
||||||
|
loadJob?.cancel()
|
||||||
|
statusJob?.cancel()
|
||||||
|
|
||||||
|
val loader = page.chapter.pageLoader ?: return
|
||||||
|
loadJob = scope.launch {
|
||||||
|
loader.loadPage(page)
|
||||||
|
}
|
||||||
|
statusJob = scope.launch {
|
||||||
|
page.statusFlow.collectLatest { processStatus(it) }
|
||||||
|
}
|
||||||
|
val extraPage = extraPage ?: return
|
||||||
|
extraLoadJob = scope.launch {
|
||||||
|
loader.loadPage(extraPage)
|
||||||
|
}
|
||||||
|
extraStatusJob = scope.launch {
|
||||||
|
extraPage.statusFlow.collectLatest { processStatus2(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun launchProgressJob() {
|
||||||
|
progressJob?.cancel()
|
||||||
|
progressJob = scope.launch {
|
||||||
|
page.progressFlow.collectLatest { value ->
|
||||||
|
progress = value
|
||||||
|
if (extraPage == null) {
|
||||||
|
progressBar.setProgress(progress)
|
||||||
|
} else {
|
||||||
|
progressBar.setProgress(((progress + extraProgress) / 2 * 0.95f).roundToInt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun launchProgressJob2() {
|
||||||
|
val extraPage = extraPage ?: return
|
||||||
|
extraProgressJob?.cancel()
|
||||||
|
extraProgressJob = scope.launch {
|
||||||
|
extraPage.progressFlow.collectLatest { value ->
|
||||||
|
extraProgress = value
|
||||||
|
progressBar.setProgress(((progress + extraProgress) / 2 * 0.95f).roundToInt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun onPageSelected(forward: Boolean?) {
|
fun onPageSelected(forward: Boolean?) {
|
||||||
(pageView as? SubsamplingScaleImageView)?.apply {
|
(pageView as? SubsamplingScaleImageView)?.apply {
|
||||||
if (isReady) {
|
if (isReady) {
|
||||||
|
@ -282,29 +357,90 @@ class PagerPageHolder(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun loadPageAndProcessStatus(index: Int) {
|
/**
|
||||||
val page = (if (index == 1) page else extraPage) ?: return
|
* Called when the status of the page changes.
|
||||||
|
*
|
||||||
val loader = page.chapter.pageLoader ?: return
|
* @param status the new status of the page.
|
||||||
supervisorScope {
|
*/
|
||||||
launchIO {
|
private fun processStatus(status: Page.State) {
|
||||||
loader.loadPage(page)
|
|
||||||
}
|
|
||||||
page.statusFlow.collectLatest {
|
|
||||||
when (status) {
|
when (status) {
|
||||||
Page.State.QUEUE -> setQueued()
|
Page.State.QUEUE -> setQueued()
|
||||||
Page.State.LOAD_PAGE -> setLoading()
|
Page.State.LOAD_PAGE -> setLoading()
|
||||||
Page.State.DOWNLOAD_IMAGE -> {
|
Page.State.DOWNLOAD_IMAGE -> {
|
||||||
|
launchProgressJob()
|
||||||
setDownloading()
|
setDownloading()
|
||||||
page.progressFlow.collectLatest { value ->
|
|
||||||
progressBar.setProgress(value)
|
|
||||||
}
|
}
|
||||||
|
Page.State.READY -> {
|
||||||
|
if (extraStatus == Page.State.READY || extraPage == null) {
|
||||||
|
setImage()
|
||||||
}
|
}
|
||||||
Page.State.READY -> setImage()
|
cancelProgressJob(1)
|
||||||
Page.State.ERROR -> setError()
|
}
|
||||||
|
Page.State.ERROR -> {
|
||||||
|
setError()
|
||||||
|
cancelProgressJob(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the status of the page changes.
|
||||||
|
*
|
||||||
|
* @param status the new status of the page.
|
||||||
|
*/
|
||||||
|
private fun processStatus2(status: Page.State) {
|
||||||
|
when (status) {
|
||||||
|
Page.State.QUEUE -> setQueued()
|
||||||
|
Page.State.LOAD_PAGE -> setLoading()
|
||||||
|
Page.State.DOWNLOAD_IMAGE -> {
|
||||||
|
launchProgressJob2()
|
||||||
|
setDownloading()
|
||||||
|
}
|
||||||
|
Page.State.READY -> {
|
||||||
|
if (this.status == Page.State.READY) {
|
||||||
|
setImage()
|
||||||
|
}
|
||||||
|
cancelProgressJob(2)
|
||||||
|
}
|
||||||
|
Page.State.ERROR -> {
|
||||||
|
setError()
|
||||||
|
cancelProgressJob(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels loading the page and processing changes to the page's status.
|
||||||
|
*/
|
||||||
|
private fun cancelLoadJob(page: Int) {
|
||||||
|
if (page == 1) {
|
||||||
|
loadJob?.cancel()
|
||||||
|
loadJob = null
|
||||||
|
statusJob?.cancel()
|
||||||
|
statusJob = null
|
||||||
|
} else {
|
||||||
|
extraLoadJob?.cancel()
|
||||||
|
extraLoadJob = null
|
||||||
|
extraStatusJob?.cancel()
|
||||||
|
extraStatusJob = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun cancelProgressJob(page: Int) {
|
||||||
|
(if (page == 1) progressJob else extraProgressJob)?.cancel()
|
||||||
|
if (page == 1) {
|
||||||
|
progressJob = null
|
||||||
|
} else {
|
||||||
|
extraProgressJob = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsubscribes from the read image header subscription.
|
||||||
|
*/
|
||||||
|
private fun cancelReadImageHeader() {
|
||||||
|
readImageHeaderJob?.cancel()
|
||||||
|
readImageHeaderJob = null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -334,71 +470,68 @@ class PagerPageHolder(
|
||||||
/**
|
/**
|
||||||
* Called when the page is ready.
|
* Called when the page is ready.
|
||||||
*/
|
*/
|
||||||
private suspend fun setImage() {
|
private fun setImage() {
|
||||||
progressBar.isVisible = true
|
progressBar.isVisible = true
|
||||||
if (extraPage == null) {
|
if (extraPage == null) {
|
||||||
progressBar.setProgress(0)
|
progressBar.completeAndFadeOut()
|
||||||
} else {
|
} else {
|
||||||
progressBar.setProgress(95)
|
progressBar.setProgress(95)
|
||||||
}
|
}
|
||||||
errorLayout?.isVisible = false
|
errorLayout?.isVisible = false
|
||||||
|
|
||||||
val streamFn = page.stream ?: return
|
cancelReadImageHeader()
|
||||||
|
|
||||||
|
readImageHeaderJob = scope.launchIO {
|
||||||
|
val streamFn = page.stream ?: return@launchIO
|
||||||
val streamFn2 = extraPage?.stream
|
val streamFn2 = extraPage?.stream
|
||||||
|
|
||||||
|
var actualSource: BufferedSource? = null
|
||||||
try {
|
try {
|
||||||
val (source, isAnimated, _bg) = withIOContext {
|
val source1 = streamFn().buffered(16).use { Buffer().readFrom(it) }
|
||||||
streamFn().buffered(16).use { source1 ->
|
val source2 = streamFn2?.invoke()?.buffered(16)?.use { Buffer().readFrom(it) }
|
||||||
if (extraPage != null) {
|
|
||||||
streamFn2?.invoke()
|
|
||||||
?.buffered(16)
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}.use { source2 ->
|
|
||||||
val actualSource = this@PagerPageHolder.mergeOrSplitPages(
|
|
||||||
Buffer().readFrom(source1),
|
|
||||||
source2?.let { Buffer().readFrom(it) },
|
|
||||||
)
|
|
||||||
|
|
||||||
val isAnimated = ImageUtil.isAnimatedAndSupported(actualSource)
|
actualSource = this@PagerPageHolder.mergeOrSplitPages(source1, source2)
|
||||||
|
val isAnimated = ImageUtil.isAnimatedAndSupported(source1) ||
|
||||||
|
(source2?.let { ImageUtil.isAnimatedAndSupported(source2) } ?: false)
|
||||||
|
withUIContext {
|
||||||
val bgColor = ReaderBackgroundColor.fromPreference(viewer.config.readerTheme)
|
val bgColor = ReaderBackgroundColor.fromPreference(viewer.config.readerTheme)
|
||||||
val bgType = getBGType(viewer.config.readerTheme, context)
|
|
||||||
val background = if (bgColor.isSmartColor) {
|
|
||||||
if (!isAnimated) {
|
if (!isAnimated) {
|
||||||
if (page.bg != null && page.bgType == bgType) page.bg
|
if (bgColor.isSmartColor) {
|
||||||
|
val bgType = getBGType(viewer.config.readerTheme, context)
|
||||||
|
if (page.bg != null && page.bgType == bgType) {
|
||||||
|
setImage(actualSource, false, imageConfig)
|
||||||
|
pageView?.background = page.bg
|
||||||
|
}
|
||||||
|
// if the user switches to automatic when pages are already cached, the bg needs to be loaded
|
||||||
else {
|
else {
|
||||||
|
val background =
|
||||||
try {
|
try {
|
||||||
setBG(actualSource.peek().inputStream())
|
setBG(actualSource.peek().inputStream())
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Logger.e(e) { e.localizedMessage?.toString() ?: "" }
|
Logger.e(e) { e.localizedMessage?.toString() ?: "" }
|
||||||
ColorDrawable(Color.WHITE)
|
ColorDrawable(Color.WHITE)
|
||||||
}
|
}
|
||||||
}
|
setImage(actualSource, false, imageConfig)
|
||||||
} else {
|
|
||||||
page.bg
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
Triple(actualSource, isAnimated, Pair(background, bgType))
|
pageView?.background = background
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
withUIContext {
|
|
||||||
val (bg, bgType) = _bg
|
|
||||||
if (bg != null) {
|
|
||||||
pageView?.background = bg
|
|
||||||
page.bg = pageView?.background
|
page.bg = pageView?.background
|
||||||
if (!isAnimated) page.bgType = bgType
|
page.bgType = bgType
|
||||||
}
|
}
|
||||||
setImage(source, isAnimated, imageConfig)
|
} else {
|
||||||
|
setImage(actualSource, false, imageConfig)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setImage(actualSource, true, imageConfig)
|
||||||
|
if (bgColor.isSmartColor && page.bg != null) {
|
||||||
|
pageView?.background = page.bg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (_: Exception) {
|
||||||
|
try {
|
||||||
|
actualSource?.let { closeSources(it) }
|
||||||
|
} catch (_: Exception) {
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
Logger.e(e)
|
|
||||||
withUIContext {
|
|
||||||
setError()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue