mirror of
https://github.com/gedoor/legado.git
synced 2025-08-10 00:52:30 +00:00
优化
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user