|
|
|
@ -7,8 +7,8 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|
|
|
import androidx.recyclerview.widget.RecyclerView
|
|
|
|
import androidx.recyclerview.widget.RecyclerView
|
|
|
|
import com.google.android.material.snackbar.Snackbar
|
|
|
|
import com.google.android.material.snackbar.Snackbar
|
|
|
|
import dagger.hilt.android.AndroidEntryPoint
|
|
|
|
import dagger.hilt.android.AndroidEntryPoint
|
|
|
|
import kotlinx.coroutines.async
|
|
|
|
|
|
|
|
import kotlinx.coroutines.coroutineScope
|
|
|
|
import kotlinx.coroutines.coroutineScope
|
|
|
|
|
|
|
|
import kotlinx.coroutines.launch
|
|
|
|
import kotlinx.coroutines.yield
|
|
|
|
import kotlinx.coroutines.yield
|
|
|
|
import org.koitharu.kotatsu.R
|
|
|
|
import org.koitharu.kotatsu.R
|
|
|
|
import org.koitharu.kotatsu.core.os.NetworkState
|
|
|
|
import org.koitharu.kotatsu.core.os.NetworkState
|
|
|
|
@ -17,14 +17,16 @@ import org.koitharu.kotatsu.databinding.FragmentReaderDoubleBinding
|
|
|
|
import org.koitharu.kotatsu.parsers.util.toIntUp
|
|
|
|
import org.koitharu.kotatsu.parsers.util.toIntUp
|
|
|
|
import org.koitharu.kotatsu.reader.domain.PageLoader
|
|
|
|
import org.koitharu.kotatsu.reader.domain.PageLoader
|
|
|
|
import org.koitharu.kotatsu.reader.ui.ReaderState
|
|
|
|
import org.koitharu.kotatsu.reader.ui.ReaderState
|
|
|
|
|
|
|
|
import org.koitharu.kotatsu.reader.ui.ReaderViewModel
|
|
|
|
import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter
|
|
|
|
import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter
|
|
|
|
import org.koitharu.kotatsu.reader.ui.pager.BaseReaderFragment
|
|
|
|
import org.koitharu.kotatsu.reader.ui.pager.BaseReaderFragment
|
|
|
|
import org.koitharu.kotatsu.reader.ui.pager.ReaderPage
|
|
|
|
import org.koitharu.kotatsu.reader.ui.pager.ReaderPage
|
|
|
|
|
|
|
|
import org.koitharu.kotatsu.reader.ui.pager.standard.PageHolder
|
|
|
|
import javax.inject.Inject
|
|
|
|
import javax.inject.Inject
|
|
|
|
import kotlin.math.absoluteValue
|
|
|
|
import kotlin.math.absoluteValue
|
|
|
|
|
|
|
|
|
|
|
|
@AndroidEntryPoint
|
|
|
|
@AndroidEntryPoint
|
|
|
|
class DoublePageReaderFragment : BaseReaderFragment<FragmentReaderDoubleBinding>() {
|
|
|
|
class DoubleReaderFragment : BaseReaderFragment<FragmentReaderDoubleBinding>() {
|
|
|
|
|
|
|
|
|
|
|
|
@Inject
|
|
|
|
@Inject
|
|
|
|
lateinit var networkState: NetworkState
|
|
|
|
lateinit var networkState: NetworkState
|
|
|
|
@ -44,7 +46,7 @@ class DoublePageReaderFragment : BaseReaderFragment<FragmentReaderDoubleBinding>
|
|
|
|
super.onViewBindingCreated(binding, savedInstanceState)
|
|
|
|
super.onViewBindingCreated(binding, savedInstanceState)
|
|
|
|
with(binding.recyclerView) {
|
|
|
|
with(binding.recyclerView) {
|
|
|
|
adapter = readerAdapter
|
|
|
|
adapter = readerAdapter
|
|
|
|
addOnScrollListener(PageScrollListener())
|
|
|
|
addOnScrollListener(PageScrollListener(viewModel))
|
|
|
|
DoublePageSnapHelper().attachToRecyclerView(this)
|
|
|
|
DoublePageSnapHelper().attachToRecyclerView(this)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -54,26 +56,26 @@ class DoublePageReaderFragment : BaseReaderFragment<FragmentReaderDoubleBinding>
|
|
|
|
super.onDestroyView()
|
|
|
|
super.onDestroyView()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override suspend fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?) =
|
|
|
|
override suspend fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?) = coroutineScope {
|
|
|
|
coroutineScope {
|
|
|
|
val items = launch {
|
|
|
|
val items = async {
|
|
|
|
|
|
|
|
requireAdapter().setItems(pages)
|
|
|
|
requireAdapter().setItems(pages)
|
|
|
|
yield()
|
|
|
|
yield()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pendingState != null) {
|
|
|
|
if (pendingState != null) {
|
|
|
|
val position = pages.indexOfFirst {
|
|
|
|
var position = pages.indexOfFirst {
|
|
|
|
it.chapterId == pendingState.chapterId && it.index == pendingState.page
|
|
|
|
it.chapterId == pendingState.chapterId && it.index == pendingState.page
|
|
|
|
}
|
|
|
|
}
|
|
|
|
items.await()
|
|
|
|
items.join()
|
|
|
|
if (position != -1) {
|
|
|
|
if (position != -1) {
|
|
|
|
requireViewBinding().recyclerView.firstVisibleItemPosition = position or 1
|
|
|
|
position = position or 1
|
|
|
|
notifyPageChanged(position)
|
|
|
|
requireViewBinding().recyclerView.firstVisibleItemPosition = position
|
|
|
|
|
|
|
|
viewModel.onCurrentPageChanged(position, position + 1)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
Snackbar.make(requireView(), R.string.not_found_404, Snackbar.LENGTH_SHORT)
|
|
|
|
Snackbar.make(requireView(), R.string.not_found_404, Snackbar.LENGTH_SHORT)
|
|
|
|
.show()
|
|
|
|
.show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
items.await()
|
|
|
|
items.join()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -85,6 +87,16 @@ class DoublePageReaderFragment : BaseReaderFragment<FragmentReaderDoubleBinding>
|
|
|
|
exceptionResolver = exceptionResolver,
|
|
|
|
exceptionResolver = exceptionResolver,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override fun onZoomIn() {
|
|
|
|
|
|
|
|
(viewBinding ?: return).recyclerView.pageHolders()
|
|
|
|
|
|
|
|
.forEach { it.onZoomIn() }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override fun onZoomOut() {
|
|
|
|
|
|
|
|
(viewBinding ?: return).recyclerView.pageHolders()
|
|
|
|
|
|
|
|
.forEach { it.onZoomOut() }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override fun switchPageBy(delta: Int) {
|
|
|
|
override fun switchPageBy(delta: Int) {
|
|
|
|
switchPageTo((requireViewBinding().recyclerView.currentItem() + delta) or 1, delta.absoluteValue > 1)
|
|
|
|
switchPageTo((requireViewBinding().recyclerView.currentItem() + delta) or 1, delta.absoluteValue > 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -103,25 +115,38 @@ class DoublePageReaderFragment : BaseReaderFragment<FragmentReaderDoubleBinding>
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private fun notifyPageChanged(page: Int) {
|
|
|
|
|
|
|
|
viewModel.onCurrentPageChanged(page)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun RecyclerView.currentItem(): Int {
|
|
|
|
private fun RecyclerView.currentItem(): Int {
|
|
|
|
val lm = layoutManager as LinearLayoutManager
|
|
|
|
val lm = layoutManager as LinearLayoutManager
|
|
|
|
return ((lm.findFirstVisibleItemPosition() + lm.findLastVisibleItemPosition()) / 2f).toIntUp()
|
|
|
|
return ((lm.findFirstVisibleItemPosition() + lm.findLastVisibleItemPosition()) / 2f).toIntUp()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private inner class PageScrollListener : RecyclerView.OnScrollListener() {
|
|
|
|
private fun RecyclerView.pageHolders(): Sequence<PageHolder> {
|
|
|
|
|
|
|
|
val lm = layoutManager as? LinearLayoutManager ?: return emptySequence()
|
|
|
|
|
|
|
|
return (lm.findFirstVisibleItemPosition()..lm.findLastVisibleItemPosition()).asSequence()
|
|
|
|
|
|
|
|
.mapNotNull { findViewHolderForAdapterPosition(it) as? PageHolder }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private class PageScrollListener(
|
|
|
|
|
|
|
|
private val viewModel: ReaderViewModel,
|
|
|
|
|
|
|
|
) : RecyclerView.OnScrollListener() {
|
|
|
|
|
|
|
|
|
|
|
|
private var lastPage = RecyclerView.NO_POSITION
|
|
|
|
private var firstPos = RecyclerView.NO_POSITION
|
|
|
|
|
|
|
|
private var lastPos = RecyclerView.NO_POSITION
|
|
|
|
|
|
|
|
|
|
|
|
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
|
|
|
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
|
|
|
super.onScrolled(recyclerView, dx, dy)
|
|
|
|
super.onScrolled(recyclerView, dx, dy)
|
|
|
|
val page = recyclerView.currentItem()
|
|
|
|
val lm = recyclerView.layoutManager as? LinearLayoutManager
|
|
|
|
if (page != lastPage) {
|
|
|
|
if (lm == null) {
|
|
|
|
lastPage = page
|
|
|
|
firstPos = RecyclerView.NO_POSITION
|
|
|
|
notifyPageChanged(page)
|
|
|
|
lastPos = RecyclerView.NO_POSITION
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
val newFirstPos = lm.findFirstVisibleItemPosition()
|
|
|
|
|
|
|
|
val newLastPos = lm.findLastVisibleItemPosition()
|
|
|
|
|
|
|
|
if (newFirstPos != firstPos || newLastPos != lastPos) {
|
|
|
|
|
|
|
|
firstPos = newFirstPos
|
|
|
|
|
|
|
|
lastPos = newLastPos
|
|
|
|
|
|
|
|
viewModel.onCurrentPageChanged(newFirstPos, newLastPos)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|