This commit is contained in:
Horis
2025-11-05 22:01:32 +08:00
parent 4e7f21d245
commit 147db05c19
3 changed files with 42 additions and 18 deletions
@@ -33,8 +33,11 @@ import io.legado.app.ui.book.read.page.provider.LayoutProgressListener
import io.legado.app.utils.postEvent import io.legado.app.utils.postEvent
import io.legado.app.utils.stackTraceStr import io.legado.app.utils.stackTraceStr
import io.legado.app.utils.toastOnUi import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
@@ -681,11 +684,11 @@ object ReadBook : CoroutineScope by MainScope() {
canceled: Boolean = false, canceled: Boolean = false,
success: (() -> Unit)? = null success: (() -> Unit)? = null
) { ) {
removeLoading(chapter.index)
if (canceled || chapter.index !in durChapterIndex - 1..durChapterIndex + 1) { if (canceled || chapter.index !in durChapterIndex - 1..durChapterIndex + 1) {
removeLoading(chapter.index)
return return
} }
Coroutine.async { Coroutine.async(start = CoroutineStart.LAZY) {
val contentProcessor = ContentProcessor.get(book.name, book.origin) val contentProcessor = ContentProcessor.get(book.name, book.origin)
val displayTitle = chapter.getDisplayTitle( val displayTitle = chapter.getDisplayTitle(
contentProcessor.getTitleReplaceRules(), contentProcessor.getTitleReplaceRules(),
@@ -699,7 +702,9 @@ object ReadBook : CoroutineScope by MainScope() {
when (val offset = chapter.index - durChapterIndex) { when (val offset = chapter.index - durChapterIndex) {
0 -> { 0 -> {
curTextChapter?.cancelLayout() curTextChapter?.cancelLayout()
curTextChapter = textChapter withContext(Main) {
curTextChapter = textChapter
}
callBack?.upMenuView() callBack?.upMenuView()
var available = false var available = false
for (page in textChapter.layoutChannel) { for (page in textChapter.layoutChannel) {
@@ -724,14 +729,18 @@ object ReadBook : CoroutineScope by MainScope() {
-1 -> { -1 -> {
prevTextChapter?.cancelLayout() prevTextChapter?.cancelLayout()
prevTextChapter = textChapter withContext(Main) {
prevTextChapter = textChapter
}
textChapter.layoutChannel.receiveAsFlow().collect() textChapter.layoutChannel.receiveAsFlow().collect()
if (upContent) callBack?.upContent(offset, resetPageOffset) if (upContent) callBack?.upContent(offset, resetPageOffset)
} }
1 -> { 1 -> {
nextTextChapter?.cancelLayout() nextTextChapter?.cancelLayout()
nextTextChapter = textChapter withContext(Main) {
nextTextChapter = textChapter
}
for (page in textChapter.layoutChannel) { for (page in textChapter.layoutChannel) {
if (page.index > 1) { if (page.index > 1) {
continue continue
@@ -743,11 +752,16 @@ object ReadBook : CoroutineScope by MainScope() {
return@async return@async
}.onError { }.onError {
if (it is CancellationException) {
return@onError
}
AppLog.put("ChapterProvider ERROR", it) AppLog.put("ChapterProvider ERROR", it)
appCtx.toastOnUi("ChapterProvider ERROR:\n${it.stackTraceStr}") appCtx.toastOnUi("ChapterProvider ERROR:\n${it.stackTraceStr}")
}.onSuccess { }.onSuccess {
success?.invoke() success?.invoke()
} }.onFinally {
removeLoading(chapter.index)
}.start()
} }
suspend fun contentLoadFinishAwait( suspend fun contentLoadFinishAwait(
@@ -757,8 +771,8 @@ object ReadBook : CoroutineScope by MainScope() {
upContent: Boolean = true, upContent: Boolean = true,
resetPageOffset: Boolean resetPageOffset: Boolean
) { ) {
removeLoading(chapter.index)
if (chapter.index !in durChapterIndex - 1..durChapterIndex + 1) { if (chapter.index !in durChapterIndex - 1..durChapterIndex + 1) {
removeLoading(chapter.index)
return return
} }
kotlin.runCatching { kotlin.runCatching {
@@ -775,7 +789,9 @@ object ReadBook : CoroutineScope by MainScope() {
when (val offset = chapter.index - durChapterIndex) { when (val offset = chapter.index - durChapterIndex) {
0 -> { 0 -> {
curTextChapter?.cancelLayout() curTextChapter?.cancelLayout()
curTextChapter = textChapter withContext(Main) {
curTextChapter = textChapter
}
callBack?.upMenuView() callBack?.upMenuView()
var available = false var available = false
for (page in textChapter.layoutChannel) { for (page in textChapter.layoutChannel) {
@@ -800,14 +816,18 @@ object ReadBook : CoroutineScope by MainScope() {
-1 -> { -1 -> {
prevTextChapter?.cancelLayout() prevTextChapter?.cancelLayout()
prevTextChapter = textChapter withContext(Main) {
prevTextChapter = textChapter
}
textChapter.layoutChannel.receiveAsFlow().collect() textChapter.layoutChannel.receiveAsFlow().collect()
if (upContent) callBack?.upContent(offset, resetPageOffset) if (upContent) callBack?.upContent(offset, resetPageOffset)
} }
1 -> { 1 -> {
nextTextChapter?.cancelLayout() nextTextChapter?.cancelLayout()
nextTextChapter = textChapter withContext(Main) {
nextTextChapter = textChapter
}
for (page in textChapter.layoutChannel) { for (page in textChapter.layoutChannel) {
if (page.index > 1) { if (page.index > 1) {
continue continue
@@ -816,12 +836,14 @@ object ReadBook : CoroutineScope by MainScope() {
} }
} }
} }
return
}.onFailure { }.onFailure {
if (it is CancellationException) {
return@onFailure
}
AppLog.put("ChapterProvider ERROR", it) AppLog.put("ChapterProvider ERROR", it)
appCtx.toastOnUi("ChapterProvider ERROR:\n${it.stackTraceStr}") appCtx.toastOnUi("ChapterProvider ERROR:\n${it.stackTraceStr}")
} }
removeLoading(chapter.index)
} }
@Synchronized @Synchronized
@@ -19,7 +19,7 @@ import java.security.MessageDigest
* 仅当applyBinarization为true时有效。 * 仅当applyBinarization为true时有效。
*/ */
class EpaperTransformation( class EpaperTransformation(
@IntRange(0, 255) private val threshold: Int = 128, @param:IntRange(0, 255) private val threshold: Int = 128,
) : BitmapTransformation() { ) : BitmapTransformation() {
private val ID = private val ID =
@@ -30,10 +30,10 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.ensureActive import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.LinkedList import java.util.LinkedList
import kotlin.coroutines.coroutineContext
import kotlin.math.roundToInt import kotlin.math.roundToInt
class TextChapterLayout( class TextChapterLayout(
@@ -109,6 +109,8 @@ class TextChapterLayout(
}.onError { }.onError {
exception = it exception = it
onException(it) onException(it)
}.onCancel {
channel.cancel()
}.onFinally { }.onFinally {
isCompleted = true isCompleted = true
} }
@@ -227,7 +229,7 @@ class TextChapterLayout(
val sb = StringBuffer() val sb = StringBuffer()
var isSetTypedImage = false var isSetTypedImage = false
contents.forEach { content -> contents.forEach { content ->
coroutineContext.ensureActive() currentCoroutineContext().ensureActive()
if (isTextImageStyle) { if (isTextImageStyle) {
//图片样式为文字嵌入类型 //图片样式为文字嵌入类型
var text = content.replace(ChapterProvider.srcReplaceChar, "▣") var text = content.replace(ChapterProvider.srcReplaceChar, "▣")
@@ -260,7 +262,7 @@ class TextChapterLayout(
if (content.contains("<img")) { if (content.contains("<img")) {
val matcher = AppPattern.imgPattern.matcher(content) val matcher = AppPattern.imgPattern.matcher(content)
while (matcher.find()) { while (matcher.find()) {
coroutineContext.ensureActive() currentCoroutineContext().ensureActive()
val text = content.substring(start, matcher.start()) val text = content.substring(start, matcher.start())
if (text.isNotBlank()) { if (text.isNotBlank()) {
setTypeText( setTypeText(
@@ -314,7 +316,7 @@ class TextChapterLayout(
textPage.height += endPadding textPage.height += endPadding
} }
textPage.text = stringBuilder.toString() textPage.text = stringBuilder.toString()
coroutineContext.ensureActive() currentCoroutineContext().ensureActive()
onPageCompleted() onPageCompleted()
onCompleted() onCompleted()
} }
@@ -773,7 +775,7 @@ class TextChapterLayout(
textPage.leftLineSize = textPage.lineSize textPage.leftLineSize = textPage.lineSize
} }
textPage.text = stringBuilder.toString() textPage.text = stringBuilder.toString()
coroutineContext.ensureActive() currentCoroutineContext().ensureActive()
onPageCompleted() onPageCompleted()
//新建页面 //新建页面
pendingTextPage = TextPage() pendingTextPage = TextPage()