This commit is contained in:
Horis
2025-03-06 22:59:37 +08:00
parent 5e3d8d8911
commit f7644dba6d
9 changed files with 278 additions and 204 deletions
@@ -136,6 +136,8 @@ object ReadBook : CoroutineScope by MainScope() {
TextFile.clear()
synchronized(this) {
loadingChapters.clear()
downloadedChapters.clear()
downloadFailChapters.clear()
}
}
@@ -954,8 +956,6 @@ object ReadBook : CoroutineScope by MainScope() {
preDownloadTask?.cancel()
downloadScope.coroutineContext.cancelChildren()
coroutineContext.cancelChildren()
downloadedChapters.clear()
downloadFailChapters.clear()
ImageProvider.clear()
if (!CacheBookService.isRun) {
CacheBook.close()
+169 -113
View File
@@ -20,6 +20,7 @@ import io.legado.app.help.config.AppConfig
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.help.globalExecutor
import io.legado.app.model.webBook.WebBook
import io.legado.app.ui.book.manga.entities.MangaChapter
import io.legado.app.ui.book.manga.entities.MangaContent
import io.legado.app.ui.book.manga.entities.ReaderLoading
import io.legado.app.utils.NetworkUtils
@@ -50,19 +51,23 @@ object ReadManga : CoroutineScope by MainScope() {
var chapterSize = 0//总章节
var durChapterImageCount = 0
var durChapterPos = 0
var prevMangaChapter: MangaChapter? = null
var curMangaChapter: MangaChapter? = null
var nextMangaChapter: MangaChapter? = null
var bookSource: BookSource? = null
var chapterTitle: String = ""
var readStartTime: Long = System.currentTimeMillis()
private val readRecord = ReadRecord()
private val loadingChapters = arrayListOf<Int>()
var simulatedChapterSize = 0
var mCallback: Callback? = null
var gameOver = false
var preDownloadTask: Job? = null
val downloadedChapters = hashSetOf<Int>()
val downloadFailChapters = hashMapOf<Int, Int>()
val downloadScope = CoroutineScope(SupervisorJob() + IO)
var rateLimiter = ConcurrentRateLimiter(null)
val durChapterAbsPos get() = (prevMangaChapter?.contents?.size ?: 0) + durChapterPos + 1
val mangaContents get() = buildContentList()
val hasNextChapter get() = durChapterIndex < simulatedChapterSize - 1
fun saveRead(pageChanged: Boolean = false) {
executor.execute {
@@ -115,9 +120,12 @@ object ReadManga : CoroutineScope by MainScope() {
}
durChapterIndex = book.durChapterIndex
durChapterPos = book.durChapterPos
clearMangaChapter()
upWebBook(book)
synchronized(this) {
loadingChapters.clear()
downloadedChapters.clear()
downloadFailChapters.clear()
}
}
@@ -130,6 +138,11 @@ object ReadManga : CoroutineScope by MainScope() {
}
}
fun clearMangaChapter() {
prevMangaChapter = null
curMangaChapter = null
nextMangaChapter = null
}
//每次切换章节更新阅读记录
fun upReadTime() {
@@ -158,12 +171,6 @@ object ReadManga : CoroutineScope by MainScope() {
}
}
fun loading(index: Int): Boolean {
synchronized(this) {
return loadingChapters.contains(index)
}
}
/**
* 获取正文
*/
@@ -188,11 +195,25 @@ object ReadManga : CoroutineScope by MainScope() {
fun loadContent() {
loadContent(durChapterIndex)
loadContent(durChapterIndex - 1)
loadContent(durChapterIndex + 1)
}
fun loadContent(
index: Int,
) {
fun loadOrUpContent() {
if (curMangaChapter == null) {
loadContent(durChapterIndex)
} else {
mCallback?.upContent(true)
}
if (nextMangaChapter == null) {
loadContent(durChapterIndex + 1)
}
if (prevMangaChapter == null) {
loadContent(durChapterIndex - 1)
}
}
fun loadContent(index: Int) {
if (chapterChanged) {
removeLoading(index)
}
@@ -225,25 +246,20 @@ object ReadManga : CoroutineScope by MainScope() {
/**
* 取消注册回调
*/
fun unregister() {
fun unregister(cb: Callback) {
if (mCallback === cb) {
mCallback = null
}
inBookshelf = false
tocChanged = false
chapterChanged = false
book = null
durChapterIndex = 0
chapterSize = 0
durChapterPos = 0
durChapterImageCount = 0
bookSource = null
chapterTitle = ""
loadingChapters.clear()
simulatedChapterSize = 0
mCallback = null
gameOver = false
preDownloadTask?.cancel()
preDownloadTask = null
downloadedChapters.clear()
downloadFailChapters.clear()
downloadScope.coroutineContext.cancelChildren()
coroutineContext.cancelChildren()
}
@@ -256,122 +272,119 @@ object ReadManga : CoroutineScope by MainScope() {
content: String?,
book: Book,
) {
chapterTitle = chapter.title
removeLoading(chapter.index)
if (chapter.index !in durChapterIndex - 1..durChapterIndex + 1) {
return
}
if (content == null) {
mCallback?.loadFail("加载内容失败")
return
}
if (content.isNotEmpty()) {
val list = flow {
val matcher = AppPattern.imgPattern.matcher(content)
while (matcher.find()) {
val src = matcher.group(1) ?: continue
val mSrc = NetworkUtils.getAbsoluteURL(chapter.url, src)
emit(mSrc)
when (chapter.index - durChapterIndex) {
0 -> {
if (content == null) {
mCallback?.loadFail("加载内容失败")
return
}
}.distinctUntilChanged().mapIndexed { index, src ->
MangaContent(
chapterSize = chapterSize,
mChapterIndex = durChapterIndex,
nextChapterIndex = durChapterIndex.plus(1),
mImageUrl = src,
mDurChapterPos = index,
mChapterName = chapterTitle
)
}.toList().apply {
this.forEach {
it.mDurChapterCount = this.size
if (content.isEmpty()) {
mCallback?.loadFail("正文内容为空")
return
}
durChapterImageCount = this.size
val mangaChapter = getManageChapter(chapter, content)
if (mangaChapter.imageCount == 0) {
mCallback?.loadFail("正文没有图片")
return
}
durChapterImageCount = mangaChapter.imageCount
curMangaChapter = mangaChapter
mCallback?.upContent(true)
mCallback?.contentLoadFinish()
}
-1 -> {
if (content == null || content.isEmpty()) {
return
}
val mangaChapter = getManageChapter(chapter, content)
if (mangaChapter.imageCount == 0) {
return
}
prevMangaChapter = mangaChapter
mCallback?.upContent()
}
1 -> {
if (content == null || content.isEmpty()) {
return
}
val mangaChapter = getManageChapter(chapter, content)
if (mangaChapter.imageCount == 0) {
return
}
nextMangaChapter = mangaChapter
mCallback?.upContent()
}
val contentList = mutableListOf<Any>()
contentList.add(
ReaderLoading(
durChapterIndex,
"阅读 ${chapter.title}",
mNextChapterIndex = durChapterIndex.plus(1)
)
)
contentList.addAll(list)
contentList.add(
ReaderLoading(
durChapterIndex,
"已读完 ${chapter.title}",
mNextChapterIndex = durChapterIndex.plus(1)
)
)
mCallback?.loadContentFinish(contentList)
}
mCallback?.loadComplete()
}
private fun buildContentList(): List<Any> {
val list = arrayListOf<Any>()
prevMangaChapter?.let {
list.addAll(it.contents)
}
curMangaChapter?.let {
list.addAll(it.contents)
}
nextMangaChapter?.let {
list.addAll(it.contents)
}
return list
}
/**
* 加载下一章
*/
fun moveToNextChapter(index: Int) {
if (loading(index)) {
return
}
if (index > chapterSize - 1) {
upToc(index)
return
}
fun moveToNextChapter(): Boolean {
if (durChapterIndex < simulatedChapterSize - 1) {
durChapterPos = 0
durChapterIndex = index
durChapterIndex++
prevMangaChapter = curMangaChapter
curMangaChapter = nextMangaChapter
nextMangaChapter = null
if (curMangaChapter == null) {
loadContent(durChapterIndex)
} else {
mCallback?.upContent(true)
}
loadContent(durChapterIndex + 1)
saveRead()
loadContent(durChapterIndex)
AppLog.putDebug("moveToNextChapter-curPageChanged()")
curPageChanged()
return true
} else {
AppLog.putDebug("跳转下一章失败,没有下一章")
return false
}
}
fun moveToPrevChapter(): Boolean {
if (durChapterIndex > 0) {
durChapterIndex--
nextMangaChapter = curMangaChapter
curMangaChapter = prevMangaChapter
prevMangaChapter = null
if (curMangaChapter == null) {
loadContent(durChapterIndex)
} else {
mCallback?.upContent(true)
}
loadContent(durChapterIndex - 1)
saveRead()
return true
}
return false
}
fun curPageChanged() {
upReadTime()
preDownload()
}
@Synchronized
fun upToc(index: Int) {
val bookSource = bookSource ?: return
val book = book ?: return
if (!book.canUpdate) return
if (System.currentTimeMillis() - book.lastCheckTime < 600000) {
mCallback?.noData()
return
}
book.lastCheckTime = System.currentTimeMillis()
WebBook.getChapterList(this, bookSource, book).onSuccess(IO) { cList ->
if (book.bookUrl == ReadManga.book?.bookUrl
&& cList.size > chapterSize
) {
appDb.bookChapterDao.delByBook(book.bookUrl)
appDb.bookChapterDao.insert(*cList.toTypedArray())
saveRead()
durChapterPos = 0
durChapterIndex = index
chapterSize = cList.size
simulatedChapterSize = book.simulatedTotalChapterNum()
loadContent(durChapterIndex)
} else {
durChapterIndex = durChapterIndex.minus(1)
saveRead()
gameOver = true
mCallback?.noData()
}
}.onError {
mCallback?.noData()
}
}
private fun downloadNetworkContent(
bookSource: BookSource,
scope: CoroutineScope,
@@ -480,7 +493,6 @@ object ReadManga : CoroutineScope by MainScope() {
}
}
/**
* 同步阅读进度
* 如果当前进度快于服务器进度或者没有进度进行上传,如果慢与服务器进度则执行传入动作
@@ -536,11 +548,55 @@ object ReadManga : CoroutineScope by MainScope() {
}
}
private suspend fun getManageChapter(chapter: BookChapter, content: String): MangaChapter {
val list = flow {
val matcher = AppPattern.imgPattern.matcher(content)
while (matcher.find()) {
val src = matcher.group(1) ?: continue
val mSrc = NetworkUtils.getAbsoluteURL(chapter.url, src)
emit(mSrc)
}
}.distinctUntilChanged().mapIndexed { index, src ->
MangaContent(
chapterSize = chapterSize,
mChapterIndex = chapter.index,
nextChapterIndex = chapter.index.plus(1),
mImageUrl = src,
mDurChapterPos = index,
mChapterName = chapter.title
)
}.toList()
val imageCount = list.size
list.forEach {
it.mDurChapterImageCount = imageCount
}
val contentList = mutableListOf<Any>()
contentList.add(
ReaderLoading(
chapter.index,
"阅读 ${chapter.title}",
mNextChapterIndex = chapter.index.plus(1)
)
)
contentList.addAll(list)
contentList.add(
ReaderLoading(
chapter.index,
"已读完 ${chapter.title}",
mNextChapterIndex = chapter.index.plus(1)
)
)
return MangaChapter(chapter, contentList, imageCount)
}
interface Callback {
fun loadContentFinish(list: MutableList<Any>)
fun loadComplete()
fun upContent(finish: Boolean = false)
fun contentLoadFinish()
fun loadFail(msg: String)
fun noData()
fun adjustProgress()
fun sureNewProgress(progress: BookProgress)
}
@@ -39,13 +39,12 @@ import io.legado.app.help.config.AppConfig
import io.legado.app.help.storage.Backup
import io.legado.app.lib.dialogs.alert
import io.legado.app.model.ReadManga
import io.legado.app.ui.book.manga.entities.MangaContent
import io.legado.app.ui.book.manga.entities.ReaderLoading
import io.legado.app.receiver.NetworkChangedListener
import io.legado.app.ui.book.changesource.ChangeBookSourceDialog
import io.legado.app.ui.book.info.BookInfoActivity
import io.legado.app.ui.book.manga.config.MangaFooterConfig
import io.legado.app.ui.book.manga.config.MangaFooterSettingDialog
import io.legado.app.ui.book.manga.entities.MangaContent
import io.legado.app.ui.book.manga.recyclerview.MangaAdapter
import io.legado.app.ui.book.read.MangaMenu
import io.legado.app.ui.book.read.ReadBookActivity.Companion.RESULT_DELETED
@@ -64,9 +63,12 @@ import io.legado.app.utils.toastOnUi
import io.legado.app.utils.toggleStatusBar
import io.legado.app.utils.viewbindingdelegate.viewBinding
import io.legado.app.utils.visible
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.text.DecimalFormat
class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, MangaViewModel>(),
class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewModel>(),
ReadManga.Callback, ChangeBookSourceDialog.CallBack, MangaMenu.CallBack {
private val mLayoutManager by lazy {
@@ -140,7 +142,11 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, MangaViewModel>()
}
}
override val binding by viewBinding(ActivityMangaBinding::inflate)
override val viewModel by viewModels<MangaViewModel>()
override val viewModel by viewModels<ReadMangaViewModel>()
private val loadingViewVisible get() = binding.flLoading.isVisible
private val df by lazy {
DecimalFormat("0.0%")
}
override fun onCreate(savedInstanceState: Bundle?) {
upLayoutInDisplayCutoutMode()
@@ -154,15 +160,15 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, MangaViewModel>()
binding.tvRetry.setOnClickListener {
binding.llLoading.isVisible = true
binding.llRetry.isGone = true
ReadManga.loadContent()
ReadManga.loadOrUpContent()
}
mAdapter.addFooterView {
ViewLoadMoreBinding.bind(loadMoreView)
}
loadMoreView.setOnClickListener {
if (!loadMoreView.isLoading && !ReadManga.gameOver) {
scrollToBottom(true, ReadManga.durChapterIndex)
if (!loadMoreView.isLoading && ReadManga.hasNextChapter) {
loadMoreView.startLoad()
ReadManga.loadOrUpContent()
}
}
loadMoreView.gone()
@@ -175,11 +181,11 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, MangaViewModel>()
observeEvent<MangaFooterConfig>(EventBus.UP_MANGA_CONFIG) {
mMangaFooterConfig = it
upInfoBar(
ReadManga.durChapterIndex.plus(1),
ReadManga.durChapterIndex,
ReadManga.chapterSize,
ReadManga.durChapterPos.plus(1),
ReadManga.durChapterPos,
ReadManga.durChapterImageCount,
ReadManga.chapterTitle
ReadManga.curMangaChapter?.chapter?.title ?: ""
)
}
}
@@ -197,28 +203,28 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, MangaViewModel>()
singlePagerScroller(AppConfig.enableMangaHorizontalScroll)
disabledClickScroller(AppConfig.disableClickScroll)
disableMangaScaling(AppConfig.disableMangaScale)
setPreScrollListener { _, dx, dy, position ->
if ((dy > 0 || dx > 0) && position + 2 > mAdapter.getCurrentList().size - 3) {
if (mAdapter.getCurrentList().last() is ReaderLoading) {
val nextIndex =
(mAdapter.getCurrentList().last() as ReaderLoading).mNextChapterIndex
if (nextIndex != -1) {
scrollToBottom(false, nextIndex)
}
}
}
}
setNestedPreScrollListener { _, _, _, position ->
setPreScrollListener { _, _, _, position ->
if (mAdapter.isNotEmpty()) {
val content = mAdapter.getItem(position)
if (content is MangaContent) {
ReadManga.durChapterIndex = content.mChapterIndex
ReadManga.durChapterPos = content.mDurChapterPos
if (ReadManga.durChapterIndex < content.mChapterIndex) {
ReadManga.moveToNextChapter()
if (ReadManga.hasNextChapter) {
loadMoreView.startLoad()
} else {
loadMoreView.noMore("暂无章节了!")
}
} else if (ReadManga.durChapterIndex > content.mChapterIndex) {
ReadManga.moveToPrevChapter()
} else {
ReadManga.durChapterPos = content.mDurChapterPos
ReadManga.curPageChanged()
}
upInfoBar(
content.mChapterIndex + 1,
content.mChapterIndex,
content.chapterSize,
content.mDurChapterPos + 1,
content.mDurChapterCount,
content.mDurChapterPos,
content.mDurChapterImageCount,
content.mChapterName
)
}
@@ -244,13 +250,6 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, MangaViewModel>()
viewModel.initData(intent)
}
private fun scrollToBottom(forceLoad: Boolean = false, index: Int) {
if ((loadMoreView.hasMore && !loadMoreView.isLoading) && !ReadManga.gameOver || forceLoad) {
loadMoreView.hasMore()
ReadManga.moveToNextChapter(index)
}
}
override fun onPostCreate(savedInstanceState: Bundle?) {
super.onPostCreate(savedInstanceState)
Looper.myQueue().addIdleHandler {
@@ -260,41 +259,47 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, MangaViewModel>()
justInitData = true
}
override fun loadContentFinish(list: MutableList<Any>) {
override fun upContent(finish: Boolean) {
lifecycleScope.launch {
setTitle(ReadManga.book?.name)
val isEmpty = mAdapter.isEmpty()
val list = withContext(IO) { ReadManga.mangaContents }
mAdapter.submitList(list) {
if (isEmpty) {
if (loadingViewVisible && finish) {
binding.infobar.isVisible = true
upInfoBar(
ReadManga.durChapterIndex.plus(1),
ReadManga.durChapterIndex,
ReadManga.chapterSize,
ReadManga.durChapterPos.plus(1),
ReadManga.durChapterPos,
ReadManga.durChapterImageCount,
ReadManga.chapterTitle
ReadManga.curMangaChapter!!.chapter.title
)
binding.mRecyclerManga.scrollToPosition(ReadManga.durChapterAbsPos)
binding.flLoading.isGone = true
loadMoreView.visible()
}
if (ReadManga.durChapterPos + 2 > mAdapter.getCurrentList().size - 3) {
val nextIndex =
(mAdapter.getCurrentList().last() as ReaderLoading).mNextChapterIndex
scrollToBottom(index = nextIndex)
} else {
binding.mRecyclerManga.scrollToPosition(ReadManga.durChapterPos)
if (finish) {
loadMoreView.stopLoad()
if (!ReadManga.hasNextChapter) {
loadMoreView.noMore("暂无章节了!")
}
}
if (ReadManga.chapterChanged) {
binding.mRecyclerManga.scrollToPosition(ReadManga.durChapterPos)
binding.mRecyclerManga.scrollToPosition(ReadManga.durChapterAbsPos)
}
ReadManga.chapterChanged = false
loadMoreView.visible()
loadMoreView.stopLoad()
}
}
}
override fun contentLoadFinish() {
lifecycleScope.launch {
loadMoreView.stopLoad()
}
}
private fun upInfoBar(
chapterIndex: Int,
chapterSize: Int,
@@ -315,21 +320,35 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, MangaViewModel>()
if (!hidePageNumberLabel) {
mLabelBuilder.append(getString(R.string.manga_check_page_number))
}
mLabelBuilder.append("${chapterPos}/${chapterImageCount}").append(" ")
mLabelBuilder.append("${chapterPos + 1}/${chapterImageCount}").append(" ")
}
if (!hideChapter) {
if (!hideChapterLabel) {
mLabelBuilder.append(getString(R.string.manga_check_chapter))
}
mLabelBuilder.append("${chapterIndex}/${chapterSize}").append(" ")
mLabelBuilder.append("${chapterIndex + 1}/${chapterSize}").append(" ")
}
if (!hideProgressRatio) {
if (!hideProgressRatioLabel) {
mLabelBuilder.append(getString(R.string.manga_check_progress))
}
mLabelBuilder.append("${chapterIndex.div(chapterSize).times(100)}%")
val percent = if (chapterSize == 0 || chapterImageCount == 0 && chapterIndex == 0) {
"0.0%"
} else if (chapterImageCount == 0) {
df.format((chapterIndex + 1.0f) / chapterSize.toDouble())
} else {
var percent =
df.format(
chapterIndex * 1.0f / chapterSize + 1.0f / chapterSize * (chapterPos + 1) / chapterImageCount.toDouble()
)
if (percent == "100.0%" && (chapterIndex + 1 != chapterSize || chapterPos + 1 != chapterImageCount)) {
percent = "99.9%"
}
percent
}
mLabelBuilder.append(percent)
}
}
binding.infobar.update(
@@ -366,15 +385,9 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, MangaViewModel>()
stopAutoPage()
}
override fun loadComplete() {
lifecycleScope.launch {
binding.flLoading.isGone = true
}
}
override fun loadFail(msg: String) {
lifecycleScope.launch {
if (mAdapter.isEmpty() || ReadManga.chapterChanged) {
if (loadingViewVisible) {
binding.llLoading.isGone = true
binding.llRetry.isVisible = true
binding.tvMsg.text = msg
@@ -384,12 +397,6 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, MangaViewModel>()
}
}
override fun noData() {
lifecycleScope.launch {
loadMoreView.noMore("暂无章节了!")
}
}
override fun adjustProgress() {
if (ReadManga.chapterChanged) {
binding.mRecyclerManga.scrollToPosition(ReadManga.durChapterPos)
@@ -398,7 +405,7 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, MangaViewModel>()
}
override fun onDestroy() {
ReadManga.unregister()
ReadManga.unregister(this)
super.onDestroy()
}
@@ -33,7 +33,7 @@ import kotlinx.coroutines.flow.onEmpty
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.take
class MangaViewModel(application: Application) : BaseViewModel(application) {
class ReadMangaViewModel(application: Application) : BaseViewModel(application) {
private var changeSourceCoroutine: Coroutine<*>? = null
@@ -84,7 +84,12 @@ class MangaViewModel(application: Application) : BaseViewModel(application) {
ensureChapterExist()
//开始加载内容
ReadManga.loadContent()
if (!isSameBook) {
ReadManga.loadContent()
} else {
ReadManga.loadOrUpContent()
}
//自动换源
if (!book.isLocal && ReadManga.bookSource == null) {
@@ -224,7 +229,7 @@ class MangaViewModel(application: Application) : BaseViewModel(application) {
ReadManga.durChapterIndex = index
ReadManga.durChapterPos = durChapterPos
ReadManga.saveRead()
ReadManga.loadContent(index)
ReadManga.loadContent()
}
}
@@ -0,0 +1,9 @@
package io.legado.app.ui.book.manga.entities
import io.legado.app.data.entities.BookChapter
data class MangaChapter(
val chapter: BookChapter,
val contents: List<Any>,
val imageCount: Int
)
@@ -6,6 +6,6 @@ data class MangaContent(
var nextChapterIndex: Int = 0,//下一章
val mImageUrl: String = "",//当前URL
var mDurChapterPos: Int = 0,//当前章节位置
var mDurChapterCount: Int = 0,//当前章节内容总数
var mDurChapterImageCount: Int = 0,//当前章节内容总数
var mChapterName: String = "",//章节名称
)
@@ -67,17 +67,8 @@ class MangaAdapter(private val context: Context) :
fun isNotEmpty() = !isEmpty()
//全部替换数据
fun submitList(contents: MutableList<Any>, runnable: Runnable) {
val list = if (ReadManga.chapterChanged) {
contents
} else {
val currentList = mDiffer.currentList.toMutableList()
currentList.addAll(contents)
currentList
}
mDiffer.submitList(list) {
runnable.run()
}
fun submitList(contents: List<Any>, runnable: Runnable? = null) {
mDiffer.submitList(contents, runnable)
}
inner class PageViewHolder(binding: BookComicRvBinding) :
@@ -94,13 +85,13 @@ class MangaAdapter(private val context: Context) :
binding.retry.setOnClickListener {
val item = mDiffer.currentList[layoutPosition]
if (item is MangaContent) {
loadImageWithRetry(item.mImageUrl, isHorizontal)
loadImageWithRetry(item.mImageUrl, isHorizontal, mDiffer.currentList.size == 3)
}
}
}
fun onBind(item: MangaContent) {
loadImageWithRetry(item.mImageUrl, isHorizontal)
loadImageWithRetry(item.mImageUrl, isHorizontal, mDiffer.currentList.size == 3)
}
}
@@ -50,7 +50,7 @@ open class MangaVH<VB : ViewBinding>(val binding: VB, private val context: Conte
}
@SuppressLint("CheckResult")
fun loadImageWithRetry(imageUrl: String, isHorizontal: Boolean) {
fun loadImageWithRetry(imageUrl: String, isHorizontal: Boolean, singleImage: Boolean) {
mFlProgress.isVisible = true
mLoading.isVisible = true
mRetry?.isGone = true
@@ -95,7 +95,11 @@ open class MangaVH<VB : ViewBinding>(val binding: VB, private val context: Conte
mFlProgress.isGone = true
if (!isHorizontal) {
itemView.updateLayoutParams<ViewGroup.LayoutParams> {
height = ViewGroup.LayoutParams.WRAP_CONTENT
height = if (singleImage) {
ViewGroup.LayoutParams.MATCH_PARENT
} else {
ViewGroup.LayoutParams.WRAP_CONTENT
}
}
} else {
mImage.updateLayoutParams<FrameLayout.LayoutParams> {
@@ -4,11 +4,13 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
fun RecyclerView.findCenterViewPosition(): Int {
return getChildAdapterPosition(findChildViewUnder(width / 2f, height / 2f) ?: return RecyclerView.NO_POSITION)
return getChildAdapterPosition(
findChildViewUnder(width / 2f, height / 2f) ?: return RecyclerView.NO_POSITION
)
}
fun RecyclerView.findViewPosition(x: Float, y: Float): Int {
return getChildAdapterPosition(findChildViewUnder(x, y) ?: return RecyclerView.NO_POSITION)
return getChildAdapterPosition(findChildViewUnder(x, y) ?: return RecyclerView.NO_POSITION)
}
fun RecyclerView.findFirstVisibleViewPosition(): Int {
@@ -21,7 +23,7 @@ fun RecyclerView.findFirstVisibleViewPosition(): Int {
fun RecyclerView.findLastVisibleViewPosition(): Int {
var pos = -1
if ( layoutManager is LinearLayoutManager) {
if (layoutManager is LinearLayoutManager) {
pos = (layoutManager as LinearLayoutManager).findLastVisibleItemPosition()
}
return pos