This commit is contained in:
Horis
2026-03-03 15:58:56 +08:00
parent 0de75c4ef7
commit 847d268db0
6 changed files with 60 additions and 31 deletions
@@ -96,6 +96,7 @@ object ReadBook : CoroutineScope by MainScope() {
val executor = globalExecutor val executor = globalExecutor
fun resetData(book: Book) { fun resetData(book: Book) {
releaseAndCancel()
ReadBook.book = book ReadBook.book = book
readRecord.bookName = book.name readRecord.bookName = book.name
readRecord.readTime = appDb.readRecordDao.getReadTime(book.name) ?: 0 readRecord.readTime = appDb.readRecordDao.getReadTime(book.name) ?: 0
@@ -125,6 +126,7 @@ object ReadBook : CoroutineScope by MainScope() {
} }
fun upData(book: Book) { fun upData(book: Book) {
releaseAndCancel()
ReadBook.book = book ReadBook.book = book
chapterSize = appDb.bookChapterDao.getChapterCount(book.bookUrl) chapterSize = appDb.bookChapterDao.getChapterCount(book.bookUrl)
simulatedChapterSize = if (book.readSimulating()) { simulatedChapterSize = if (book.readSimulating()) {
@@ -863,17 +865,22 @@ object ReadBook : CoroutineScope by MainScope() {
val bookSource = bookSource ?: return val bookSource = bookSource ?: return
val book = book ?: return val book = book ?: return
if (!book.canUpdate) return if (!book.canUpdate) return
if (chapterSize - durChapterIndex - 1 >= 3) return
if (System.currentTimeMillis() - book.lastCheckTime < 600000) return if (System.currentTimeMillis() - book.lastCheckTime < 600000) return
book.lastCheckTime = System.currentTimeMillis() book.lastCheckTime = System.currentTimeMillis()
val oldBook = book.copy()
WebBook.getChapterList(this, bookSource, book).onSuccess(IO) { cList -> WebBook.getChapterList(this, bookSource, book).onSuccess(IO) { cList ->
if (book.bookUrl == ReadBook.book?.bookUrl ensureActive()
&& cList.size > chapterSize if (cList.size > chapterSize) {
) { if (oldBook.bookUrl == book.bookUrl) {
appDb.bookChapterDao.delByBook(book.bookUrl) appDb.bookDao.update(book)
} else {
appDb.bookDao.replace(oldBook, book)
BookHelp.updateCacheFolder(oldBook, book)
}
appDb.bookChapterDao.delByBook(oldBook.bookUrl)
appDb.bookChapterDao.insert(*cList.toTypedArray()) appDb.bookChapterDao.insert(*cList.toTypedArray())
saveRead() onChapterListUpdated(book, false)
chapterSize = cList.size
simulatedChapterSize = book.simulatedTotalChapterNum()
nextTextChapter ?: loadContent(durChapterIndex + 1) nextTextChapter ?: loadContent(durChapterIndex + 1)
} }
} }
@@ -922,6 +929,7 @@ object ReadBook : CoroutineScope by MainScope() {
if (book?.isLocal == true) return if (book?.isLocal == true) return
executor.execute { executor.execute {
if (AppConfig.preDownloadNum < 2) { if (AppConfig.preDownloadNum < 2) {
upToc()
return@execute return@execute
} }
preDownloadTask?.cancel() preDownloadTask?.cancel()
@@ -955,7 +963,7 @@ object ReadBook : CoroutineScope by MainScope() {
} }
} }
fun onChapterListUpdated(newBook: Book) { fun onChapterListUpdated(newBook: Book, loadContent: Boolean = true) {
if (newBook.isSameNameAuthor(book)) { if (newBook.isSameNameAuthor(book)) {
book = newBook book = newBook
chapterSize = newBook.totalChapterNum chapterSize = newBook.totalChapterNum
@@ -963,9 +971,10 @@ object ReadBook : CoroutineScope by MainScope() {
if (simulatedChapterSize > 0 && durChapterIndex > simulatedChapterSize - 1) { if (simulatedChapterSize > 0 && durChapterIndex > simulatedChapterSize - 1) {
durChapterIndex = simulatedChapterSize - 1 durChapterIndex = simulatedChapterSize - 1
} }
callBack?.upMenuView()
if (callBack == null) { if (callBack == null) {
clearTextChapter() clearTextChapter()
} else { } else if (loadContent) {
loadContent(true) loadContent(true)
} }
} }
@@ -997,6 +1006,10 @@ object ReadBook : CoroutineScope by MainScope() {
if (callBack === cb) { if (callBack === cb) {
callBack = null callBack = null
} }
releaseAndCancel()
}
private fun releaseAndCancel() {
msg = null msg = null
preDownloadTask?.cancel() preDownloadTask?.cancel()
downloadScope.coroutineContext.cancelChildren() downloadScope.coroutineContext.cancelChildren()
@@ -380,6 +380,7 @@ object ReadManga : CoroutineScope by MainScope() {
if (book?.isLocal == true) return if (book?.isLocal == true) return
executor.execute { executor.execute {
if (AppConfig.preDownloadNum < 2) { if (AppConfig.preDownloadNum < 2) {
upToc()
return@execute return@execute
} }
preDownloadTask?.cancel() preDownloadTask?.cancel()
@@ -463,17 +464,22 @@ object ReadManga : CoroutineScope by MainScope() {
val bookSource = bookSource ?: return val bookSource = bookSource ?: return
val book = book ?: return val book = book ?: return
if (!book.canUpdate) return if (!book.canUpdate) return
if (chapterSize - durChapterIndex - 1 >= 3) return
if (System.currentTimeMillis() - book.lastCheckTime < 600000) return if (System.currentTimeMillis() - book.lastCheckTime < 600000) return
book.lastCheckTime = System.currentTimeMillis() book.lastCheckTime = System.currentTimeMillis()
val oldBook = book.copy()
WebBook.getChapterList(this, bookSource, book).onSuccess(IO) { cList -> WebBook.getChapterList(this, bookSource, book).onSuccess(IO) { cList ->
if (book.bookUrl == ReadManga.book?.bookUrl ensureActive()
&& cList.size > chapterSize if (cList.size > chapterSize) {
) { if (oldBook.bookUrl == book.bookUrl) {
appDb.bookChapterDao.delByBook(book.bookUrl) appDb.bookDao.update(book)
} else {
appDb.bookDao.replace(oldBook, book)
BookHelp.updateCacheFolder(oldBook, book)
}
appDb.bookChapterDao.delByBook(oldBook.bookUrl)
appDb.bookChapterDao.insert(*cList.toTypedArray()) appDb.bookChapterDao.insert(*cList.toTypedArray())
saveRead() onChapterListUpdated(book, false)
chapterSize = cList.size
simulatedChapterSize = book.simulatedTotalChapterNum()
nextMangaChapter ?: loadContent(durChapterIndex + 1) nextMangaChapter ?: loadContent(durChapterIndex + 1)
} }
} }
@@ -553,7 +559,7 @@ object ReadManga : CoroutineScope by MainScope() {
mCallback?.loadFail(msg, retry) mCallback?.loadFail(msg, retry)
} }
fun onChapterListUpdated(newBook: Book) { fun onChapterListUpdated(newBook: Book, loadContent: Boolean = true) {
if (newBook.isSameNameAuthor(book)) { if (newBook.isSameNameAuthor(book)) {
book = newBook book = newBook
chapterSize = newBook.totalChapterNum chapterSize = newBook.totalChapterNum
@@ -563,7 +569,7 @@ object ReadManga : CoroutineScope by MainScope() {
} }
if (mCallback == null) { if (mCallback == null) {
clearMangaChapter() clearMangaChapter()
} else { } else if (loadContent) {
loadContent() loadContent()
} }
} }
@@ -36,6 +36,7 @@ import io.legado.app.help.book.removeType
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
import io.legado.app.help.storage.Backup import io.legado.app.help.storage.Backup
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.model.ReadBook
import io.legado.app.model.ReadManga import io.legado.app.model.ReadManga
import io.legado.app.receiver.NetworkChangedListener import io.legado.app.receiver.NetworkChangedListener
import io.legado.app.ui.book.changesource.ChangeBookSourceDialog import io.legado.app.ui.book.changesource.ChangeBookSourceDialog
@@ -348,7 +349,7 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
networkChangedListener.register() networkChangedListener.register()
networkChangedListener.onNetworkChanged = { networkChangedListener.onNetworkChanged = {
// 当网络是可用状态且无需初始化时同步进度(初始化中已有同步进度逻辑) // 当网络是可用状态且无需初始化时同步进度(初始化中已有同步进度逻辑)
if (AppConfig.syncBookProgressPlus && NetworkUtils.isAvailable() && !justInitData) { if (AppConfig.syncBookProgressPlus && NetworkUtils.isAvailable() && !justInitData && ReadBook.inBookshelf) {
ReadManga.syncProgress({ progress -> sureNewProgress(progress) }) ReadManga.syncProgress({ progress -> sureNewProgress(progress) })
} }
} }
@@ -370,9 +371,11 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
} else { } else {
ReadManga.uploadProgress() ReadManga.uploadProgress()
} }
Backup.autoBack(this)
} }
} }
if (!BuildConfig.DEBUG) {
Backup.autoBack(this)
}
ReadManga.cancelPreDownloadTask() ReadManga.cancelPreDownloadTask()
networkChangedListener.unRegister() networkChangedListener.unRegister()
mScrollTimer.isEnabledPage = false mScrollTimer.isEnabledPage = false
@@ -26,6 +26,8 @@ import io.legado.app.model.webBook.WebBook
import io.legado.app.utils.mapParallelSafe import io.legado.app.utils.mapParallelSafe
import io.legado.app.utils.postEvent import io.legado.app.utils.postEvent
import io.legado.app.utils.toastOnUi import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
@@ -98,7 +100,7 @@ class ReadMangaViewModel(application: Application) : BaseViewModel(application)
if (ReadManga.chapterChanged) { if (ReadManga.chapterChanged) {
// 有章节跳转不同步阅读进度 // 有章节跳转不同步阅读进度
ReadManga.chapterChanged = false ReadManga.chapterChanged = false
} else { } else if (ReadManga.inBookshelf) {
if (AppConfig.syncBookProgressPlus) { if (AppConfig.syncBookProgressPlus) {
ReadManga.syncProgress( ReadManga.syncProgress(
{ progress -> ReadManga.mCallback?.sureNewProgress(progress) }) { progress -> ReadManga.mCallback?.sureNewProgress(progress) })
@@ -129,6 +131,7 @@ class ReadMangaViewModel(application: Application) : BaseViewModel(application)
ReadManga.onChapterListUpdated(book) ReadManga.onChapterListUpdated(book)
return true return true
}.onFailure { }.onFailure {
currentCoroutineContext().ensureActive()
//加载章节出错 //加载章节出错
ReadManga.mCallback?.loadFail(appCtx.getString(R.string.error_load_toc)) ReadManga.mCallback?.loadFail(appCtx.getString(R.string.error_load_toc))
return false return false
@@ -145,6 +148,7 @@ class ReadMangaViewModel(application: Application) : BaseViewModel(application)
WebBook.getBookInfoAwait(source, book, canReName = false) WebBook.getBookInfoAwait(source, book, canReName = false)
return true return true
} catch (e: Throwable) { } catch (e: Throwable) {
currentCoroutineContext().ensureActive()
ReadManga.mCallback?.loadFail("详情页出错: ${e.localizedMessage}") ReadManga.mCallback?.loadFail("详情页出错: ${e.localizedMessage}")
return false return false
} }
@@ -220,6 +224,7 @@ class ReadMangaViewModel(application: Application) : BaseViewModel(application)
} else if (progress.durChapterIndex < book.simulatedTotalChapterNum()) { } else if (progress.durChapterIndex < book.simulatedTotalChapterNum()) {
ReadManga.setProgress(progress) ReadManga.setProgress(progress)
AppLog.put("自动同步阅读进度成功《${book.name}》 ${progress.durChapterTitle}") AppLog.put("自动同步阅读进度成功《${book.name}》 ${progress.durChapterTitle}")
context.toastOnUi("已同步最新漫画阅读进度")
} }
} }
} }
@@ -353,7 +353,7 @@ class ReadBookActivity : BaseReadBookActivity(),
networkChangedListener.register() networkChangedListener.register()
networkChangedListener.onNetworkChanged = { networkChangedListener.onNetworkChanged = {
// 当网络是可用状态且无需初始化时同步进度(初始化中已有同步进度逻辑) // 当网络是可用状态且无需初始化时同步进度(初始化中已有同步进度逻辑)
if (AppConfig.syncBookProgressPlus && NetworkUtils.isAvailable() && !justInitData) { if (AppConfig.syncBookProgressPlus && NetworkUtils.isAvailable() && !justInitData && ReadBook.inBookshelf) {
ReadBook.syncProgress({ progress -> sureNewProgress(progress) }) ReadBook.syncProgress({ progress -> sureNewProgress(progress) })
} }
} }
@@ -367,12 +367,14 @@ class ReadBookActivity : BaseReadBookActivity(),
ReadBook.cancelPreDownloadTask() ReadBook.cancelPreDownloadTask()
unregisterReceiver(timeBatteryReceiver) unregisterReceiver(timeBatteryReceiver)
upSystemUiVisibility() upSystemUiVisibility()
if (!BuildConfig.DEBUG) { if (!BuildConfig.DEBUG && ReadBook.inBookshelf) {
if (AppConfig.syncBookProgressPlus) { if (AppConfig.syncBookProgressPlus) {
ReadBook.syncProgress() ReadBook.syncProgress()
} else { } else {
ReadBook.uploadProgress() ReadBook.uploadProgress()
} }
}
if (!BuildConfig.DEBUG) {
Backup.autoBack(this) Backup.autoBack(this)
} }
justInitData = false justInitData = false
@@ -440,12 +442,11 @@ class ReadBookActivity : BaseReadBookActivity(),
} }
} }
lifecycleScope.launch { lifecycleScope.launch {
menu.findItem(R.id.menu_get_progress)?.isVisible = withContext(IO) { val show = ReadBook.inBookshelf && withContext(IO) {
AppWebDav.isOk
}
menu.findItem(R.id.menu_cover_progress)?.isVisible = withContext(IO) {
AppWebDav.isOk AppWebDav.isOk
} }
menu.findItem(R.id.menu_get_progress)?.isVisible = show
menu.findItem(R.id.menu_cover_progress)?.isVisible = show
} }
} }
@@ -39,6 +39,7 @@ import io.legado.app.utils.mapParallelSafe
import io.legado.app.utils.postEvent import io.legado.app.utils.postEvent
import io.legado.app.utils.toStringArray import io.legado.app.utils.toStringArray
import io.legado.app.utils.toastOnUi import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.ensureActive import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
@@ -52,7 +53,6 @@ import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import java.io.FileNotFoundException import java.io.FileNotFoundException
import java.io.FileOutputStream import java.io.FileOutputStream
import kotlin.coroutines.coroutineContext
/** /**
* 阅读界面数据处理 * 阅读界面数据处理
@@ -134,7 +134,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
if (ReadBook.chapterChanged) { if (ReadBook.chapterChanged) {
// 有章节跳转不同步阅读进度 // 有章节跳转不同步阅读进度
ReadBook.chapterChanged = false ReadBook.chapterChanged = false
} else if (!isSameBook || !BaseReadAloudService.isRun) { } else if (!(isSameBook && BaseReadAloudService.isRun) && ReadBook.inBookshelf) {
if (AppConfig.syncBookProgressPlus) { if (AppConfig.syncBookProgressPlus) {
ReadBook.syncProgress({ progress -> ReadBook.callBack?.sureNewProgress(progress) }) ReadBook.syncProgress({ progress -> ReadBook.callBack?.sureNewProgress(progress) })
} else { } else {
@@ -169,7 +169,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
WebBook.getBookInfoAwait(source, book, canReName = false) WebBook.getBookInfoAwait(source, book, canReName = false)
return true return true
} catch (e: Throwable) { } catch (e: Throwable) {
coroutineContext.ensureActive() currentCoroutineContext().ensureActive()
ReadBook.upMsg("详情页出错: ${e.localizedMessage}") ReadBook.upMsg("详情页出错: ${e.localizedMessage}")
return false return false
} }
@@ -225,7 +225,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
ReadBook.onChapterListUpdated(book) ReadBook.onChapterListUpdated(book)
return true return true
}.onFailure { }.onFailure {
coroutineContext.ensureActive() currentCoroutineContext().ensureActive()
ReadBook.upMsg(context.getString(R.string.error_load_toc)) ReadBook.upMsg(context.getString(R.string.error_load_toc))
return false return false
} }
@@ -256,6 +256,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
} else if (progress.durChapterIndex < book.simulatedTotalChapterNum()) { } else if (progress.durChapterIndex < book.simulatedTotalChapterNum()) {
ReadBook.setProgress(progress) ReadBook.setProgress(progress)
AppLog.put("自动同步阅读进度成功《${book.name}》 ${progress.durChapterTitle}") AppLog.put("自动同步阅读进度成功《${book.name}》 ${progress.durChapterTitle}")
context.toastOnUi("已同步最新阅读进度")
} }
} }
} }