From f7644dba6d3a25a5bdcf9d28994a0f794a44ce59 Mon Sep 17 00:00:00 2001 From: Horis <8674809+821938089@users.noreply.github.com> Date: Thu, 6 Mar 2025 22:59:37 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/legado/app/model/ReadBook.kt | 4 +- .../java/io/legado/app/model/ReadManga.kt | 282 +++++++++++------- .../app/ui/book/manga/ReadMangaActivity.kt | 141 ++++----- ...angaViewModel.kt => ReadMangaViewModel.kt} | 11 +- .../ui/book/manga/entities/MangaChapter.kt | 9 + .../ui/book/manga/entities/MangaContent.kt | 2 +- .../book/manga/recyclerview/MangaAdapter.kt | 17 +- .../app/ui/book/manga/recyclerview/MangaVH.kt | 8 +- .../app/utils/RecyclerViewExtensions.kt | 8 +- 9 files changed, 278 insertions(+), 204 deletions(-) rename app/src/main/java/io/legado/app/ui/book/manga/{MangaViewModel.kt => ReadMangaViewModel.kt} (97%) create mode 100644 app/src/main/java/io/legado/app/ui/book/manga/entities/MangaChapter.kt diff --git a/app/src/main/java/io/legado/app/model/ReadBook.kt b/app/src/main/java/io/legado/app/model/ReadBook.kt index 6962c0c64..0ef483dbf 100644 --- a/app/src/main/java/io/legado/app/model/ReadBook.kt +++ b/app/src/main/java/io/legado/app/model/ReadBook.kt @@ -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() diff --git a/app/src/main/java/io/legado/app/model/ReadManga.kt b/app/src/main/java/io/legado/app/model/ReadManga.kt index 0743c39de..b126cd643 100644 --- a/app/src/main/java/io/legado/app/model/ReadManga.kt +++ b/app/src/main/java/io/legado/app/model/ReadManga.kt @@ -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() var simulatedChapterSize = 0 var mCallback: Callback? = null - var gameOver = false var preDownloadTask: Job? = null val downloadedChapters = hashSetOf() val downloadFailChapters = hashMapOf() 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() - 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 { + val list = arrayListOf() + 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() + 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) - fun loadComplete() + fun upContent(finish: Boolean = false) + fun contentLoadFinish() fun loadFail(msg: String) - fun noData() fun adjustProgress() fun sureNewProgress(progress: BookProgress) } diff --git a/app/src/main/java/io/legado/app/ui/book/manga/ReadMangaActivity.kt b/app/src/main/java/io/legado/app/ui/book/manga/ReadMangaActivity.kt index 0f95e6778..c9dd4a741 100644 --- a/app/src/main/java/io/legado/app/ui/book/manga/ReadMangaActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/manga/ReadMangaActivity.kt @@ -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(), +class ReadMangaActivity : VMBaseActivity(), ReadManga.Callback, ChangeBookSourceDialog.CallBack, MangaMenu.CallBack { private val mLayoutManager by lazy { @@ -140,7 +142,11 @@ class ReadMangaActivity : VMBaseActivity() } } override val binding by viewBinding(ActivityMangaBinding::inflate) - override val viewModel by viewModels() + override val viewModel by viewModels() + 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() 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() observeEvent(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() 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() 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() justInitData = true } - override fun loadContentFinish(list: MutableList) { + 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() 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() 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() } } - 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() } override fun onDestroy() { - ReadManga.unregister() + ReadManga.unregister(this) super.onDestroy() } diff --git a/app/src/main/java/io/legado/app/ui/book/manga/MangaViewModel.kt b/app/src/main/java/io/legado/app/ui/book/manga/ReadMangaViewModel.kt similarity index 97% rename from app/src/main/java/io/legado/app/ui/book/manga/MangaViewModel.kt rename to app/src/main/java/io/legado/app/ui/book/manga/ReadMangaViewModel.kt index 4a96783d6..484a43ef4 100644 --- a/app/src/main/java/io/legado/app/ui/book/manga/MangaViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/manga/ReadMangaViewModel.kt @@ -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() } } diff --git a/app/src/main/java/io/legado/app/ui/book/manga/entities/MangaChapter.kt b/app/src/main/java/io/legado/app/ui/book/manga/entities/MangaChapter.kt new file mode 100644 index 000000000..7a2a84330 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/book/manga/entities/MangaChapter.kt @@ -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, + val imageCount: Int +) diff --git a/app/src/main/java/io/legado/app/ui/book/manga/entities/MangaContent.kt b/app/src/main/java/io/legado/app/ui/book/manga/entities/MangaContent.kt index 9ab23d87a..909f7ba23 100644 --- a/app/src/main/java/io/legado/app/ui/book/manga/entities/MangaContent.kt +++ b/app/src/main/java/io/legado/app/ui/book/manga/entities/MangaContent.kt @@ -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 = "",//章节名称 ) \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/manga/recyclerview/MangaAdapter.kt b/app/src/main/java/io/legado/app/ui/book/manga/recyclerview/MangaAdapter.kt index 3a67e97af..2531c98cc 100644 --- a/app/src/main/java/io/legado/app/ui/book/manga/recyclerview/MangaAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/manga/recyclerview/MangaAdapter.kt @@ -67,17 +67,8 @@ class MangaAdapter(private val context: Context) : fun isNotEmpty() = !isEmpty() //全部替换数据 - fun submitList(contents: MutableList, 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, 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) } } diff --git a/app/src/main/java/io/legado/app/ui/book/manga/recyclerview/MangaVH.kt b/app/src/main/java/io/legado/app/ui/book/manga/recyclerview/MangaVH.kt index 067830aea..0e67b865c 100644 --- a/app/src/main/java/io/legado/app/ui/book/manga/recyclerview/MangaVH.kt +++ b/app/src/main/java/io/legado/app/ui/book/manga/recyclerview/MangaVH.kt @@ -50,7 +50,7 @@ open class MangaVH(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(val binding: VB, private val context: Conte mFlProgress.isGone = true if (!isHorizontal) { itemView.updateLayoutParams { - height = ViewGroup.LayoutParams.WRAP_CONTENT + height = if (singleImage) { + ViewGroup.LayoutParams.MATCH_PARENT + } else { + ViewGroup.LayoutParams.WRAP_CONTENT + } } } else { mImage.updateLayoutParams { diff --git a/app/src/main/java/io/legado/app/utils/RecyclerViewExtensions.kt b/app/src/main/java/io/legado/app/utils/RecyclerViewExtensions.kt index 5a364992c..f8c308a26 100644 --- a/app/src/main/java/io/legado/app/utils/RecyclerViewExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/RecyclerViewExtensions.kt @@ -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