This commit is contained in:
Horis
2025-03-08 11:40:35 +08:00
parent 19e5b74a5f
commit bbb6ac6815
3 changed files with 157 additions and 167 deletions

View File

@@ -85,7 +85,7 @@ object ReadBook : CoroutineScope by MainScope() {
var readStartTime: Long = System.currentTimeMillis()
/* 跳转进度前进度记录 */
var lastBookPress: BookProgress? = null
var lastBookProgress: BookProgress? = null
/* web端阅读进度记录 */
var webBookProgress: BookProgress? = null
@@ -98,20 +98,6 @@ object ReadBook : CoroutineScope by MainScope() {
val preDownloadSemaphore = Semaphore(2)
val executor = globalExecutor
//暂时保存跳转前进度
fun saveCurrentBookProcess() {
if (lastBookPress != null) return //避免进度条连续跳转不能覆盖最初的进度记录
lastBookPress = book?.let { BookProgress(it) }
}
//恢复跳转前进度
fun restoreLastBookProcess() {
lastBookPress?.let {
setProgress(it)
lastBookPress = null
}
}
fun resetData(book: Book) {
ReadBook.book = book
readRecord.bookName = book.name
@@ -131,7 +117,7 @@ object ReadBook : CoroutineScope by MainScope() {
callBack?.upMenuView()
callBack?.upPageAnim()
upWebBook(book)
lastBookPress = null
lastBookProgress = null
webBookProgress = null
TextFile.clear()
synchronized(this) {
@@ -219,6 +205,20 @@ object ReadBook : CoroutineScope by MainScope() {
}
}
//暂时保存跳转前进度
fun saveCurrentBookProgress() {
if (lastBookProgress != null) return //避免进度条连续跳转不能覆盖最初的进度记录
lastBookProgress = book?.let { BookProgress(it) }
}
//恢复跳转前进度
fun restoreLastBookProgress() {
lastBookProgress?.let {
setProgress(it)
lastBookProgress = null
}
}
fun clearTextChapter() {
prevTextChapter = null
curTextChapter = null
@@ -558,29 +558,27 @@ object ReadBook : CoroutineScope by MainScope() {
resetPageOffset: Boolean = false,
success: (() -> Unit)? = null
) {
if (addLoading(index)) {
Coroutine.async {
val book = book!!
appDb.bookChapterDao.getChapter(book.bookUrl, index)?.let { chapter ->
BookHelp.getContent(book, chapter)?.let {
contentLoadFinish(
book,
chapter,
it,
upContent,
resetPageOffset,
success = success
)
} ?: download(
downloadScope,
Coroutine.async {
val book = book!!
val chapter = appDb.bookChapterDao.getChapter(book.bookUrl, index) ?: return@async
if (addLoading(index)) {
BookHelp.getContent(book, chapter)?.let {
contentLoadFinish(
book,
chapter,
resetPageOffset
it,
upContent,
resetPageOffset,
success = success
)
} ?: removeLoading(index)
}.onError {
removeLoading(index)
AppLog.put("加载正文出错\n${it.localizedMessage}")
} ?: download(
downloadScope,
chapter,
resetPageOffset
)
}
}.onError {
AppLog.put("加载正文出错\n${it.localizedMessage}")
}
}
@@ -615,20 +613,13 @@ object ReadBook : CoroutineScope by MainScope() {
return
}
val book = book ?: return
if (addLoading(index)) {
try {
appDb.bookChapterDao.getChapter(book.bookUrl, index)?.let { chapter ->
if (BookHelp.hasContent(book, chapter)) {
removeLoading(chapter.index)
downloadedChapters.add(chapter.index)
} else {
delay(1000)
download(downloadScope, chapter, false, preDownloadSemaphore)
}
} ?: removeLoading(index)
} catch (_: Exception) {
removeLoading(index)
coroutineContext.ensureActive()
val chapter = appDb.bookChapterDao.getChapter(book.bookUrl, index) ?: return
if (BookHelp.hasContent(book, chapter)) {
addDownloadedChapter(chapter.index)
} else {
delay(1000)
if (addLoading(index)) {
download(downloadScope, chapter, false, preDownloadSemaphore)
}
}
}
@@ -670,18 +661,21 @@ object ReadBook : CoroutineScope by MainScope() {
}
}
@Synchronized
private fun addLoading(index: Int): Boolean {
synchronized(this) {
if (loadingChapters.contains(index)) return false
loadingChapters.add(index)
return true
}
if (loadingChapters.contains(index)) return false
loadingChapters.add(index)
return true
}
@Synchronized
fun removeLoading(index: Int) {
synchronized(this) {
loadingChapters.remove(index)
}
loadingChapters.remove(index)
}
@Synchronized
fun addDownloadedChapter(index: Int) {
downloadedChapters.add(index)
}
/**
@@ -901,7 +895,7 @@ object ReadBook : CoroutineScope by MainScope() {
launch {
val maxChapterIndex =
min(durChapterIndex + AppConfig.preDownloadNum, chapterSize)
for (i in durChapterIndex.plus(1)..maxChapterIndex) {
for (i in durChapterIndex.plus(2)..maxChapterIndex) {
if (downloadedChapters.contains(i)) continue
if ((downloadFailChapters[i] ?: 0) >= 3) continue
downloadIndex(i)
@@ -909,7 +903,7 @@ object ReadBook : CoroutineScope by MainScope() {
}
launch {
val minChapterIndex = durChapterIndex - min(5, AppConfig.preDownloadNum)
for (i in durChapterIndex.minus(1) downTo minChapterIndex) {
for (i in durChapterIndex.minus(2) downTo minChapterIndex) {
if (downloadedChapters.contains(i)) continue
if ((downloadFailChapters[i] ?: 0) >= 3) continue
downloadIndex(i)

View File

@@ -70,23 +70,24 @@ object ReadManga : CoroutineScope by MainScope() {
val mangaContents get() = buildContentList()
val hasNextChapter get() = durChapterIndex < simulatedChapterSize - 1
fun saveRead(pageChanged: Boolean = false) {
executor.execute {
val book = book ?: return@execute
book.lastCheckCount = 0
book.durChapterTime = System.currentTimeMillis()
val chapterChanged = book.durChapterIndex != durChapterIndex
book.durChapterIndex = durChapterIndex
book.durChapterPos = durChapterPos
if (!pageChanged || chapterChanged) {
appDb.bookChapterDao.getChapter(book.bookUrl, durChapterIndex)?.let {
book.durChapterTitle = it.getDisplayTitle(
ContentProcessor.get(book.name, book.origin).getTitleReplaceRules(),
book.getUseReplaceRule()
)
}
}
appDb.bookDao.update(book)
fun resetData(book: Book) {
ReadManga.book = book
readRecord.bookName = book.name
readRecord.readTime = appDb.readRecordDao.getReadTime(book.name) ?: 0
chapterSize = appDb.bookChapterDao.getChapterCount(book.bookUrl)
simulatedChapterSize = if (book.readSimulating()) {
book.simulatedTotalChapterNum()
} else {
chapterSize
}
durChapterIndex = book.durChapterIndex
durChapterPos = book.durChapterPos
clearMangaChapter()
upWebBook(book)
synchronized(this) {
loadingChapters.clear()
downloadedChapters.clear()
downloadFailChapters.clear()
}
}
@@ -110,27 +111,6 @@ object ReadManga : CoroutineScope by MainScope() {
}
}
fun resetData(book: Book) {
ReadManga.book = book
readRecord.bookName = book.name
readRecord.readTime = appDb.readRecordDao.getReadTime(book.name) ?: 0
chapterSize = appDb.bookChapterDao.getChapterCount(book.bookUrl)
simulatedChapterSize = if (book.readSimulating()) {
book.simulatedTotalChapterNum()
} else {
chapterSize
}
durChapterIndex = book.durChapterIndex
durChapterPos = book.durChapterPos
clearMangaChapter()
upWebBook(book)
synchronized(this) {
loadingChapters.clear()
downloadedChapters.clear()
downloadFailChapters.clear()
}
}
fun upWebBook(book: Book) {
appDb.bookSourceDao.getBookSource(book.origin)?.let {
bookSource = it
@@ -159,43 +139,21 @@ object ReadManga : CoroutineScope by MainScope() {
}
}
@Synchronized
private fun addLoading(index: Int): Boolean {
synchronized(this) {
if (loadingChapters.contains(index)) return false
loadingChapters.add(index)
return true
}
if (loadingChapters.contains(index)) return false
loadingChapters.add(index)
return true
}
@Synchronized
fun removeLoading(index: Int) {
synchronized(this) {
loadingChapters.remove(index)
}
loadingChapters.remove(index)
}
/**
* 获取正文
*/
private fun download(
scope: CoroutineScope,
chapter: BookChapter,
semaphore: Semaphore? = null,
) {
val book = book ?: return removeLoading(chapter.index)
val bookSource = bookSource
if (bookSource != null) {
downloadNetworkContent(bookSource, scope, chapter, book, semaphore, success = {
downloadedChapters.add(chapter.index)
downloadFailChapters.remove(chapter.index)
contentLoadFinish(chapter, it)
}, error = {
downloadFailChapters[chapter.index] =
(downloadFailChapters[chapter.index] ?: 0) + 1
contentLoadFinish(chapter, null)
}, cancel = {
contentLoadFinish(chapter, null, true)
})
}
@Synchronized
fun addDownloadedChapter(index: Int) {
downloadedChapters.add(index)
}
fun loadContent() {
@@ -220,21 +178,18 @@ object ReadManga : CoroutineScope by MainScope() {
}
private fun loadContent(index: Int) {
if (addLoading(index)) {
Coroutine.async {
val book = book!!
appDb.bookChapterDao.getChapter(book.bookUrl, index)?.let { chapter ->
BookHelp.getContent(book, chapter)?.let {
contentLoadFinish(chapter, it)
} ?: download(
downloadScope,
chapter,
)
} ?: removeLoading(index)
}.onError {
removeLoading(index)
AppLog.put("加载正文出错\n${it.localizedMessage}")
Coroutine.async {
val book = book!!
val chapter = appDb.bookChapterDao.getChapter(book.bookUrl, index) ?: return@async
if (addLoading(index)) {
BookHelp.getContent(book, chapter)?.let {
contentLoadFinish(chapter, it)
} ?: run {
download(downloadScope, chapter)
}
}
}.onError {
AppLog.put("加载正文出错\n${it.localizedMessage}")
}
}
@@ -244,6 +199,7 @@ object ReadManga : CoroutineScope by MainScope() {
suspend fun contentLoadFinish(
chapter: BookChapter,
content: String?,
errorMsg: String = "加载内容失败",
canceled: Boolean = false
) {
removeLoading(chapter.index)
@@ -253,7 +209,7 @@ object ReadManga : CoroutineScope by MainScope() {
when (val offset = chapter.index - durChapterIndex) {
0 -> {
if (content == null) {
mCallback?.loadFail("加载内容失败")
mCallback?.loadFail(errorMsg)
return
}
if (content.isEmpty()) {
@@ -354,6 +310,26 @@ object ReadManga : CoroutineScope by MainScope() {
preDownload()
}
fun saveRead(pageChanged: Boolean = false) {
executor.execute {
val book = book ?: return@execute
book.lastCheckCount = 0
book.durChapterTime = System.currentTimeMillis()
val chapterChanged = book.durChapterIndex != durChapterIndex
book.durChapterIndex = durChapterIndex
book.durChapterPos = durChapterPos
if (!pageChanged || chapterChanged) {
appDb.bookChapterDao.getChapter(book.bookUrl, durChapterIndex)?.let {
book.durChapterTitle = it.getDisplayTitle(
ContentProcessor.get(book.name, book.origin).getTitleReplaceRules(),
book.getUseReplaceRule()
)
}
}
appDb.bookDao.update(book)
}
}
private fun downloadNetworkContent(
bookSource: BookSource,
scope: CoroutineScope,
@@ -393,7 +369,7 @@ object ReadManga : CoroutineScope by MainScope() {
launch {
val maxChapterIndex =
min(durChapterIndex + AppConfig.preDownloadNum, chapterSize)
for (i in durChapterIndex.plus(1)..maxChapterIndex) {
for (i in durChapterIndex.plus(2)..maxChapterIndex) {
if (downloadedChapters.contains(i)) continue
if ((downloadFailChapters[i] ?: 0) >= 3) continue
downloadIndex(i)
@@ -401,7 +377,7 @@ object ReadManga : CoroutineScope by MainScope() {
}
launch {
val minChapterIndex = durChapterIndex - min(5, AppConfig.preDownloadNum)
for (i in durChapterIndex.minus(1) downTo minChapterIndex) {
for (i in durChapterIndex.minus(2) downTo minChapterIndex) {
if (downloadedChapters.contains(i)) continue
if ((downloadFailChapters[i] ?: 0) >= 3) continue
downloadIndex(i)
@@ -425,24 +401,44 @@ object ReadManga : CoroutineScope by MainScope() {
return
}
val book = book ?: return
if (addLoading(index)) {
try {
appDb.bookChapterDao.getChapter(book.bookUrl, index)?.let { chapter ->
if (BookHelp.hasContent(book, chapter)) {
removeLoading(chapter.index)
downloadedChapters.add(chapter.index)
} else {
delay(1000)
download(downloadScope, chapter, preDownloadSemaphore)
}
} ?: removeLoading(index)
} catch (_: Exception) {
removeLoading(index)
coroutineContext.ensureActive()
val chapter = appDb.bookChapterDao.getChapter(book.bookUrl, index) ?: return
if (BookHelp.hasContent(book, chapter)) {
addDownloadedChapter(chapter.index)
} else {
delay(1000)
if (addLoading(index)) {
download(downloadScope, chapter, preDownloadSemaphore)
}
}
}
/**
* 获取正文
*/
private suspend fun download(
scope: CoroutineScope,
chapter: BookChapter,
semaphore: Semaphore? = null,
) {
val book = book ?: return removeLoading(chapter.index)
val bookSource = bookSource
if (bookSource != null) {
downloadNetworkContent(bookSource, scope, chapter, book, semaphore, success = {
downloadedChapters.add(chapter.index)
downloadFailChapters.remove(chapter.index)
contentLoadFinish(chapter, it)
}, error = {
downloadFailChapters[chapter.index] =
(downloadFailChapters[chapter.index] ?: 0) + 1
contentLoadFinish(chapter, null)
}, cancel = {
contentLoadFinish(chapter, null, canceled = true)
})
} else {
contentLoadFinish(chapter, null, "加载内容失败 没有书源")
}
}
@Synchronized
fun upToc() {
val bookSource = bookSource ?: return

View File

@@ -186,7 +186,7 @@ class ReadBookActivity : BaseReadBookActivity(),
viewModel.searchResultIndex = index
binding.searchMenu.updateSearchResultIndex(index)
binding.searchMenu.selectedSearchResult?.let { currentResult ->
ReadBook.saveCurrentBookProcess() //退出全文搜索恢复此时进度
ReadBook.saveCurrentBookProgress() //退出全文搜索恢复此时进度
skipToSearch(currentResult)
showActionMenu()
}
@@ -269,7 +269,7 @@ class ReadBookActivity : BaseReadBookActivity(),
return@addCallback
}
//拦截返回供恢复阅读进度
if (ReadBook.lastBookPress != null && confirmRestoreProcess != false) {
if (ReadBook.lastBookProgress != null && confirmRestoreProcess != false) {
restoreLastBookProcess()
return@addCallback
}
@@ -1239,20 +1239,20 @@ class ReadBookActivity : BaseReadBookActivity(),
/* 恢复到 全文搜索/进度条跳转前的位置 */
private fun restoreLastBookProcess() {
if (confirmRestoreProcess == true) {
ReadBook.restoreLastBookProcess()
ReadBook.restoreLastBookProgress()
} else if (confirmRestoreProcess == null) {
alert(R.string.draw) {
setMessage(R.string.restore_last_book_process)
yesButton {
confirmRestoreProcess = true
ReadBook.restoreLastBookProcess() //恢复启动全文搜索前的进度
ReadBook.restoreLastBookProgress() //恢复启动全文搜索前的进度
}
noButton {
ReadBook.lastBookPress = null
ReadBook.lastBookProgress = null
confirmRestoreProcess = false
}
onCancelled {
ReadBook.lastBookPress = null
ReadBook.lastBookProgress = null
confirmRestoreProcess = false
}
}
@@ -1451,7 +1451,7 @@ class ReadBookActivity : BaseReadBookActivity(),
/* 进度条跳转到指定章节 */
override fun skipToChapter(index: Int) {
ReadBook.saveCurrentBookProcess() //退出章节跳转恢复此时进度
ReadBook.saveCurrentBookProgress() //退出章节跳转恢复此时进度
viewModel.openChapter(index)
}