mirror of
https://github.com/gedoor/legado.git
synced 2025-08-10 00:52:30 +00:00
优化
This commit is contained in:
@@ -110,9 +110,9 @@ object BookController {
|
||||
?: return returnData.setErrorMsg("未找到对应书源,请换源")
|
||||
val toc = runBlocking {
|
||||
if (book.tocUrl.isBlank()) {
|
||||
WebBook.getBookInfoAwait(this, bookSource, book)
|
||||
WebBook.getBookInfoAwait(bookSource, book)
|
||||
}
|
||||
WebBook.getChapterListAwait(this, bookSource, book).getOrThrow()
|
||||
WebBook.getChapterListAwait(bookSource, book).getOrThrow()
|
||||
}
|
||||
appDb.bookChapterDao.delByBook(book.bookUrl)
|
||||
appDb.bookChapterDao.insert(*toc.toTypedArray())
|
||||
|
||||
@@ -68,14 +68,13 @@ object BookHelp {
|
||||
}
|
||||
|
||||
suspend fun saveContent(
|
||||
scope: CoroutineScope,
|
||||
bookSource: BookSource,
|
||||
book: Book,
|
||||
bookChapter: BookChapter,
|
||||
content: String
|
||||
) {
|
||||
saveText(book, bookChapter, content)
|
||||
saveImages(scope, bookSource, book, bookChapter, content)
|
||||
saveImages(bookSource, book, bookChapter, content)
|
||||
postEvent(EventBus.SAVE_CONTENT, bookChapter)
|
||||
}
|
||||
|
||||
@@ -95,7 +94,6 @@ object BookHelp {
|
||||
}
|
||||
|
||||
private suspend fun saveImages(
|
||||
scope: CoroutineScope,
|
||||
bookSource: BookSource,
|
||||
book: Book,
|
||||
bookChapter: BookChapter,
|
||||
@@ -107,8 +105,10 @@ object BookHelp {
|
||||
if (matcher.find()) {
|
||||
matcher.group(1)?.let { src ->
|
||||
val mSrc = NetworkUtils.getAbsoluteURL(bookChapter.url, src)
|
||||
awaitList.add(scope.async {
|
||||
saveImage(bookSource, book, mSrc)
|
||||
awaitList.add(coroutineScope {
|
||||
async {
|
||||
saveImage(bookSource, book, mSrc)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ object CacheBook {
|
||||
val chapterCount = appDb.bookChapterDao.getChapterCount(book.bookUrl)
|
||||
if (chapterCount == 0) {
|
||||
runBlocking {
|
||||
WebBook.getChapterListAwait(this, bookSource, book)
|
||||
WebBook.getChapterListAwait(bookSource, book)
|
||||
.onFailure {
|
||||
AppLog.put("缓存书籍没有目录且加载目录失败\n${it.localizedMessage}", it)
|
||||
appCtx.toastOnUi("缓存书籍没有目录且加载目录失败\n${it.localizedMessage}")
|
||||
|
||||
@@ -700,7 +700,7 @@ class AnalyzeRule(
|
||||
book.putVariable(entry.key, entry.value)
|
||||
}
|
||||
}
|
||||
WebBook.getBookInfoAwait(this, bookSource, book, false)
|
||||
WebBook.getBookInfoAwait(bookSource, book, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -714,7 +714,7 @@ class AnalyzeRule(
|
||||
if (bookSource == null || book == null) return
|
||||
runBlocking {
|
||||
withTimeout(1800000) {
|
||||
WebBook.getBookInfoAwait(this, bookSource, book)
|
||||
WebBook.getBookInfoAwait(bookSource, book)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -728,7 +728,7 @@ class AnalyzeRule(
|
||||
if (bookSource == null || book == null) return
|
||||
runBlocking {
|
||||
withTimeout(1800000) {
|
||||
WebBook.getBookInfoAwait(this, bookSource, book)
|
||||
WebBook.getBookInfoAwait(bookSource, book)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,12 @@ import io.legado.app.model.Debug
|
||||
import io.legado.app.model.analyzeRule.AnalyzeRule
|
||||
import io.legado.app.model.analyzeRule.AnalyzeUrl
|
||||
import io.legado.app.utils.isTrue
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.withContext
|
||||
import splitties.init.appCtx
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
/**
|
||||
* 获取目录
|
||||
@@ -26,7 +26,6 @@ import splitties.init.appCtx
|
||||
object BookChapterList {
|
||||
|
||||
suspend fun analyzeChapterList(
|
||||
scope: CoroutineScope,
|
||||
bookSource: BookSource,
|
||||
book: Book,
|
||||
baseUrl: String,
|
||||
@@ -52,7 +51,7 @@ object BookChapterList {
|
||||
}
|
||||
var chapterData =
|
||||
analyzeChapterList(
|
||||
scope, book, baseUrl, redirectUrl, body,
|
||||
book, baseUrl, redirectUrl, body,
|
||||
tocRule, listRule, bookSource, log = true
|
||||
)
|
||||
chapterList.addAll(chapterData.first)
|
||||
@@ -69,7 +68,7 @@ object BookChapterList {
|
||||
headerMapF = bookSource.getHeaderMap()
|
||||
).getStrResponseAwait().body?.let { nextBody ->
|
||||
chapterData = analyzeChapterList(
|
||||
scope, book, nextUrl, nextUrl,
|
||||
book, nextUrl, nextUrl,
|
||||
nextBody, tocRule, listRule, bookSource
|
||||
)
|
||||
nextUrl = chapterData.second.firstOrNull() ?: ""
|
||||
@@ -92,7 +91,7 @@ object BookChapterList {
|
||||
)
|
||||
val res = analyzeUrl.getStrResponseAwait()
|
||||
analyzeChapterList(
|
||||
this, book, urlStr, res.url,
|
||||
book, urlStr, res.url,
|
||||
res.body!!, tocRule, listRule, bookSource, false
|
||||
).first
|
||||
}
|
||||
@@ -110,14 +109,14 @@ object BookChapterList {
|
||||
if (!reverse) {
|
||||
chapterList.reverse()
|
||||
}
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
val lh = LinkedHashSet(chapterList)
|
||||
val list = ArrayList(lh)
|
||||
if (!book.getReverseToc()) {
|
||||
list.reverse()
|
||||
}
|
||||
Debug.log(book.origin, "◇目录总数:${list.size}")
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
list.forEachIndexed { index, bookChapter ->
|
||||
bookChapter.index = index
|
||||
}
|
||||
@@ -131,12 +130,11 @@ object BookChapterList {
|
||||
}
|
||||
book.lastCheckTime = System.currentTimeMillis()
|
||||
book.totalChapterNum = list.size
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
return list
|
||||
}
|
||||
|
||||
private fun analyzeChapterList(
|
||||
scope: CoroutineScope,
|
||||
private suspend fun analyzeChapterList(
|
||||
book: Book,
|
||||
baseUrl: String,
|
||||
redirectUrl: String,
|
||||
@@ -173,7 +171,7 @@ object BookChapterList {
|
||||
log
|
||||
)
|
||||
}
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
if (elements.isNotEmpty()) {
|
||||
Debug.log(bookSource.bookSourceUrl, "┌解析目录列表", log)
|
||||
val nameRule = analyzeRule.splitSourceRule(tocRule.chapterName)
|
||||
@@ -183,7 +181,7 @@ object BookChapterList {
|
||||
val upTimeRule = analyzeRule.splitSourceRule(tocRule.updateTime)
|
||||
val isVolumeRule = analyzeRule.splitSourceRule(tocRule.isVolume)
|
||||
elements.forEachIndexed { index, item ->
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
analyzeRule.setContent(item)
|
||||
val bookChapter = BookChapter(bookUrl = book.bookUrl, baseUrl = redirectUrl)
|
||||
analyzeRule.chapter = bookChapter
|
||||
|
||||
@@ -14,12 +14,12 @@ import io.legado.app.model.analyzeRule.AnalyzeRule
|
||||
import io.legado.app.model.analyzeRule.AnalyzeUrl
|
||||
import io.legado.app.utils.HtmlFormatter
|
||||
import io.legado.app.utils.NetworkUtils
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.withContext
|
||||
import splitties.init.appCtx
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
/**
|
||||
* 获取正文
|
||||
@@ -28,7 +28,6 @@ object BookContent {
|
||||
|
||||
@Throws(Exception::class)
|
||||
suspend fun analyzeContent(
|
||||
scope: CoroutineScope,
|
||||
bookSource: BookSource,
|
||||
book: Book,
|
||||
bookChapter: BookChapter,
|
||||
@@ -55,7 +54,7 @@ object BookContent {
|
||||
val analyzeRule = AnalyzeRule(book, bookSource).setContent(body, baseUrl)
|
||||
analyzeRule.setRedirectUrl(redirectUrl)
|
||||
analyzeRule.nextChapterUrl = mNextChapterUrl
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
var contentData = analyzeContent(
|
||||
book, baseUrl, redirectUrl, body, contentRule, bookChapter, bookSource, mNextChapterUrl
|
||||
)
|
||||
@@ -68,7 +67,7 @@ object BookContent {
|
||||
== NetworkUtils.getAbsoluteURL(redirectUrl, mNextChapterUrl)
|
||||
) break
|
||||
nextUrlList.add(nextUrl)
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
val res = AnalyzeUrl(
|
||||
mUrl = nextUrl,
|
||||
source = bookSource,
|
||||
@@ -106,7 +105,7 @@ object BookContent {
|
||||
}
|
||||
}
|
||||
asyncArray.forEach { coroutine ->
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
content.append("\n").append(coroutine.await())
|
||||
}
|
||||
}
|
||||
@@ -124,7 +123,7 @@ object BookContent {
|
||||
throw ContentEmptyException("内容为空")
|
||||
}
|
||||
if (needSave) {
|
||||
BookHelp.saveContent(scope, bookSource, book, bookChapter, contentStr)
|
||||
BookHelp.saveContent(bookSource, book, bookChapter, contentStr)
|
||||
}
|
||||
return contentStr
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ import io.legado.app.utils.DebugLog
|
||||
import io.legado.app.utils.HtmlFormatter
|
||||
import io.legado.app.utils.NetworkUtils
|
||||
import io.legado.app.utils.StringUtils.wordCountFormat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import splitties.init.appCtx
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
|
||||
/**
|
||||
@@ -24,8 +24,7 @@ import splitties.init.appCtx
|
||||
object BookInfo {
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun analyzeBookInfo(
|
||||
scope: CoroutineScope,
|
||||
suspend fun analyzeBookInfo(
|
||||
bookSource: BookSource,
|
||||
book: Book,
|
||||
baseUrl: String,
|
||||
@@ -41,11 +40,10 @@ object BookInfo {
|
||||
val analyzeRule = AnalyzeRule(book, bookSource)
|
||||
analyzeRule.setContent(body).setBaseUrl(baseUrl)
|
||||
analyzeRule.setRedirectUrl(redirectUrl)
|
||||
analyzeBookInfo(scope, book, body, analyzeRule, bookSource, baseUrl, redirectUrl, canReName)
|
||||
analyzeBookInfo(book, body, analyzeRule, bookSource, baseUrl, redirectUrl, canReName)
|
||||
}
|
||||
|
||||
fun analyzeBookInfo(
|
||||
scope: CoroutineScope,
|
||||
suspend fun analyzeBookInfo(
|
||||
book: Book,
|
||||
body: String,
|
||||
analyzeRule: AnalyzeRule,
|
||||
@@ -57,13 +55,13 @@ object BookInfo {
|
||||
val infoRule = bookSource.getBookInfoRule()
|
||||
infoRule.init?.let {
|
||||
if (it.isNotBlank()) {
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "≡执行详情页初始化规则")
|
||||
analyzeRule.setContent(analyzeRule.getElement(it))
|
||||
}
|
||||
}
|
||||
val mCanReName = canReName && !infoRule.canReName.isNullOrBlank()
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取书名")
|
||||
BookHelp.formatBookName(analyzeRule.getString(infoRule.name)).let {
|
||||
if (it.isNotEmpty() && (mCanReName || book.name.isEmpty())) {
|
||||
@@ -71,7 +69,7 @@ object BookInfo {
|
||||
}
|
||||
Debug.log(bookSource.bookSourceUrl, "└${it}")
|
||||
}
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取作者")
|
||||
BookHelp.formatBookAuthor(analyzeRule.getString(infoRule.author)).let {
|
||||
if (it.isNotEmpty() && (mCanReName || book.author.isEmpty())) {
|
||||
@@ -79,7 +77,7 @@ object BookInfo {
|
||||
}
|
||||
Debug.log(bookSource.bookSourceUrl, "└${it}")
|
||||
}
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取分类")
|
||||
try {
|
||||
analyzeRule.getStringList(infoRule.kind)
|
||||
@@ -92,7 +90,7 @@ object BookInfo {
|
||||
Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}")
|
||||
DebugLog.e("获取分类出错", e)
|
||||
}
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取字数")
|
||||
try {
|
||||
wordCountFormat(analyzeRule.getString(infoRule.wordCount)).let {
|
||||
@@ -103,7 +101,7 @@ object BookInfo {
|
||||
Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}")
|
||||
DebugLog.e("获取字数出错", e)
|
||||
}
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取最新章节")
|
||||
try {
|
||||
analyzeRule.getString(infoRule.lastChapter).let {
|
||||
@@ -114,7 +112,7 @@ object BookInfo {
|
||||
Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}")
|
||||
DebugLog.e("获取最新章节出错", e)
|
||||
}
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取简介")
|
||||
try {
|
||||
HtmlFormatter.format(analyzeRule.getString(infoRule.intro)).let {
|
||||
@@ -125,7 +123,7 @@ object BookInfo {
|
||||
Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}")
|
||||
DebugLog.e("获取简介出错", e)
|
||||
}
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取封面链接")
|
||||
try {
|
||||
analyzeRule.getString(infoRule.coverUrl).let {
|
||||
@@ -140,7 +138,7 @@ object BookInfo {
|
||||
DebugLog.e("获取封面出错", e)
|
||||
}
|
||||
if (book.type != BookType.file) {
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取目录链接")
|
||||
book.tocUrl = analyzeRule.getString(infoRule.tocUrl, isUrl = true)
|
||||
if (book.tocUrl.isEmpty()) book.tocUrl = baseUrl
|
||||
@@ -149,7 +147,7 @@ object BookInfo {
|
||||
}
|
||||
Debug.log(bookSource.bookSourceUrl, "└${book.tocUrl}")
|
||||
} else {
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取文件下载链接")
|
||||
book.downloadUrls = analyzeRule.getStringList(infoRule.downloadUrls, isUrl = true)
|
||||
if (book.downloadUrls == null) {
|
||||
|
||||
@@ -14,9 +14,9 @@ import io.legado.app.model.analyzeRule.RuleData
|
||||
import io.legado.app.utils.HtmlFormatter
|
||||
import io.legado.app.utils.NetworkUtils
|
||||
import io.legado.app.utils.StringUtils.wordCountFormat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import splitties.init.appCtx
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
/**
|
||||
* 获取书籍列表
|
||||
@@ -24,8 +24,7 @@ import splitties.init.appCtx
|
||||
object BookList {
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun analyzeBookList(
|
||||
scope: CoroutineScope,
|
||||
suspend fun analyzeBookList(
|
||||
bookSource: BookSource,
|
||||
ruleData: RuleData,
|
||||
analyzeUrl: AnalyzeUrl,
|
||||
@@ -46,11 +45,10 @@ object BookList {
|
||||
analyzeRule.setContent(body).setBaseUrl(baseUrl)
|
||||
analyzeRule.setRedirectUrl(baseUrl)
|
||||
bookSource.bookUrlPattern?.let {
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
if (baseUrl.matches(it.toRegex())) {
|
||||
Debug.log(bookSource.bookSourceUrl, "≡链接为详情页")
|
||||
getInfoItem(
|
||||
scope,
|
||||
bookSource,
|
||||
analyzeRule,
|
||||
analyzeUrl,
|
||||
@@ -81,11 +79,11 @@ object BookList {
|
||||
}
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取书籍列表")
|
||||
collections = analyzeRule.getElements(ruleList)
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
if (collections.isEmpty() && bookSource.bookUrlPattern.isNullOrEmpty()) {
|
||||
Debug.log(bookSource.bookSourceUrl, "└列表为空,按详情页解析")
|
||||
getInfoItem(
|
||||
scope, bookSource, analyzeRule, analyzeUrl, body, baseUrl, ruleData.getVariable()
|
||||
bookSource, analyzeRule, analyzeUrl, body, baseUrl, ruleData.getVariable()
|
||||
)?.let { searchBook ->
|
||||
searchBook.infoHtml = body
|
||||
bookList.add(searchBook)
|
||||
@@ -102,7 +100,7 @@ object BookList {
|
||||
Debug.log(bookSource.bookSourceUrl, "└列表大小:${collections.size}")
|
||||
for ((index, item) in collections.withIndex()) {
|
||||
getSearchItem(
|
||||
scope, bookSource, analyzeRule, item, baseUrl, ruleData.getVariable(),
|
||||
bookSource, analyzeRule, item, baseUrl, ruleData.getVariable(),
|
||||
index == 0,
|
||||
ruleName = ruleName,
|
||||
ruleBookUrl = ruleBookUrl,
|
||||
@@ -127,8 +125,7 @@ object BookList {
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
private fun getInfoItem(
|
||||
scope: CoroutineScope,
|
||||
private suspend fun getInfoItem(
|
||||
bookSource: BookSource,
|
||||
analyzeRule: AnalyzeRule,
|
||||
analyzeUrl: AnalyzeUrl,
|
||||
@@ -144,7 +141,6 @@ object BookList {
|
||||
book.type = bookSource.bookSourceType
|
||||
analyzeRule.ruleData = book
|
||||
BookInfo.analyzeBookInfo(
|
||||
scope,
|
||||
book,
|
||||
body,
|
||||
analyzeRule,
|
||||
@@ -160,8 +156,7 @@ object BookList {
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
private fun getSearchItem(
|
||||
scope: CoroutineScope,
|
||||
private suspend fun getSearchItem(
|
||||
bookSource: BookSource,
|
||||
analyzeRule: AnalyzeRule,
|
||||
item: Any,
|
||||
@@ -184,16 +179,16 @@ object BookList {
|
||||
searchBook.originOrder = bookSource.customOrder
|
||||
analyzeRule.ruleData = searchBook
|
||||
analyzeRule.setContent(item)
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取书名", log)
|
||||
searchBook.name = BookHelp.formatBookName(analyzeRule.getString(ruleName))
|
||||
Debug.log(bookSource.bookSourceUrl, "└${searchBook.name}", log)
|
||||
if (searchBook.name.isNotEmpty()) {
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取作者", log)
|
||||
searchBook.author = BookHelp.formatBookAuthor(analyzeRule.getString(ruleAuthor))
|
||||
Debug.log(bookSource.bookSourceUrl, "└${searchBook.author}", log)
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取分类", log)
|
||||
try {
|
||||
searchBook.kind = analyzeRule.getStringList(ruleKind)?.joinToString(",")
|
||||
@@ -201,7 +196,7 @@ object BookList {
|
||||
} catch (e: Exception) {
|
||||
Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}", log)
|
||||
}
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取字数", log)
|
||||
try {
|
||||
searchBook.wordCount = wordCountFormat(analyzeRule.getString(ruleWordCount))
|
||||
@@ -209,7 +204,7 @@ object BookList {
|
||||
} catch (e: java.lang.Exception) {
|
||||
Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}", log)
|
||||
}
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取最新章节", log)
|
||||
try {
|
||||
searchBook.latestChapterTitle = analyzeRule.getString(ruleLastChapter)
|
||||
@@ -217,7 +212,7 @@ object BookList {
|
||||
} catch (e: java.lang.Exception) {
|
||||
Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}", log)
|
||||
}
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取简介", log)
|
||||
try {
|
||||
searchBook.intro = HtmlFormatter.format(analyzeRule.getString(ruleIntro))
|
||||
@@ -225,7 +220,7 @@ object BookList {
|
||||
} catch (e: java.lang.Exception) {
|
||||
Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}", log)
|
||||
}
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取封面链接", log)
|
||||
try {
|
||||
analyzeRule.getString(ruleCoverUrl).let {
|
||||
@@ -237,7 +232,7 @@ object BookList {
|
||||
} catch (e: java.lang.Exception) {
|
||||
Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}", log)
|
||||
}
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
Debug.log(bookSource.bookSourceUrl, "┌获取详情页链接", log)
|
||||
searchBook.bookUrl = analyzeRule.getString(ruleBookUrl, isUrl = true)
|
||||
if (searchBook.bookUrl.isEmpty()) {
|
||||
|
||||
@@ -29,12 +29,11 @@ object WebBook {
|
||||
context: CoroutineContext = Dispatchers.IO,
|
||||
): Coroutine<ArrayList<SearchBook>> {
|
||||
return Coroutine.async(scope, context) {
|
||||
searchBookAwait(scope, bookSource, key, page)
|
||||
searchBookAwait(bookSource, key, page)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun searchBookAwait(
|
||||
scope: CoroutineScope,
|
||||
bookSource: BookSource,
|
||||
key: String,
|
||||
page: Int? = 1,
|
||||
@@ -58,7 +57,6 @@ object WebBook {
|
||||
}
|
||||
}
|
||||
return BookList.analyzeBookList(
|
||||
scope = scope,
|
||||
bookSource = bookSource,
|
||||
ruleData = ruleData,
|
||||
analyzeUrl = analyzeUrl,
|
||||
@@ -81,12 +79,11 @@ object WebBook {
|
||||
context: CoroutineContext = Dispatchers.IO,
|
||||
): Coroutine<List<SearchBook>> {
|
||||
return Coroutine.async(scope, context) {
|
||||
exploreBookAwait(scope, bookSource, url, page)
|
||||
exploreBookAwait(bookSource, url, page)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun exploreBookAwait(
|
||||
scope: CoroutineScope,
|
||||
bookSource: BookSource,
|
||||
url: String,
|
||||
page: Int? = 1,
|
||||
@@ -108,7 +105,6 @@ object WebBook {
|
||||
}
|
||||
}
|
||||
return BookList.analyzeBookList(
|
||||
scope = scope,
|
||||
bookSource = bookSource,
|
||||
ruleData = ruleData,
|
||||
analyzeUrl = analyzeUrl,
|
||||
@@ -129,12 +125,11 @@ object WebBook {
|
||||
canReName: Boolean = true,
|
||||
): Coroutine<Book> {
|
||||
return Coroutine.async(scope, context) {
|
||||
getBookInfoAwait(scope, bookSource, book, canReName)
|
||||
getBookInfoAwait(bookSource, book, canReName)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getBookInfoAwait(
|
||||
scope: CoroutineScope,
|
||||
bookSource: BookSource,
|
||||
book: Book,
|
||||
canReName: Boolean = true,
|
||||
@@ -142,7 +137,6 @@ object WebBook {
|
||||
book.type = bookSource.bookSourceType
|
||||
if (!book.infoHtml.isNullOrEmpty()) {
|
||||
BookInfo.analyzeBookInfo(
|
||||
scope = scope,
|
||||
bookSource = bookSource,
|
||||
book = book,
|
||||
baseUrl = book.bookUrl,
|
||||
@@ -166,7 +160,6 @@ object WebBook {
|
||||
}
|
||||
}
|
||||
BookInfo.analyzeBookInfo(
|
||||
scope = scope,
|
||||
bookSource = bookSource,
|
||||
book = book,
|
||||
baseUrl = book.bookUrl,
|
||||
@@ -188,12 +181,11 @@ object WebBook {
|
||||
context: CoroutineContext = Dispatchers.IO
|
||||
): Coroutine<List<BookChapter>> {
|
||||
return Coroutine.async(scope, context) {
|
||||
getChapterListAwait(scope, bookSource, book).getOrThrow()
|
||||
getChapterListAwait(bookSource, book).getOrThrow()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getChapterListAwait(
|
||||
scope: CoroutineScope,
|
||||
bookSource: BookSource,
|
||||
book: Book,
|
||||
): Result<List<BookChapter>> {
|
||||
@@ -201,7 +193,6 @@ object WebBook {
|
||||
return kotlin.runCatching {
|
||||
if (book.bookUrl == book.tocUrl && !book.tocHtml.isNullOrEmpty()) {
|
||||
BookChapterList.analyzeChapterList(
|
||||
scope = scope,
|
||||
bookSource = bookSource,
|
||||
book = book,
|
||||
baseUrl = book.tocUrl,
|
||||
@@ -224,7 +215,6 @@ object WebBook {
|
||||
}
|
||||
}
|
||||
BookChapterList.analyzeChapterList(
|
||||
scope = scope,
|
||||
bookSource = bookSource,
|
||||
book = book,
|
||||
baseUrl = book.tocUrl,
|
||||
@@ -270,7 +260,6 @@ object WebBook {
|
||||
}
|
||||
return if (bookChapter.url == book.bookUrl && !book.tocHtml.isNullOrEmpty()) {
|
||||
BookContent.analyzeContent(
|
||||
scope = scope,
|
||||
bookSource = bookSource,
|
||||
book = book,
|
||||
bookChapter = bookChapter,
|
||||
@@ -300,7 +289,6 @@ object WebBook {
|
||||
}
|
||||
}
|
||||
BookContent.analyzeContent(
|
||||
scope = scope,
|
||||
bookSource = bookSource,
|
||||
book = book,
|
||||
bookChapter = bookChapter,
|
||||
@@ -342,13 +330,13 @@ object WebBook {
|
||||
): Result<Book> {
|
||||
return kotlin.runCatching {
|
||||
scope.isActive
|
||||
searchBookAwait(scope, bookSource, name).firstOrNull {
|
||||
searchBookAwait(bookSource, name).firstOrNull {
|
||||
it.name == name && it.author == author
|
||||
}?.let { searchBook ->
|
||||
scope.isActive
|
||||
var book = searchBook.toBook()
|
||||
if (book.tocUrl.isBlank()) {
|
||||
book = getBookInfoAwait(scope, bookSource, book)
|
||||
book = getBookInfoAwait(bookSource, book)
|
||||
}
|
||||
return@runCatching book
|
||||
}
|
||||
|
||||
@@ -24,8 +24,11 @@ import io.legado.app.utils.activityPendingIntent
|
||||
import io.legado.app.utils.postEvent
|
||||
import io.legado.app.utils.servicePendingIntent
|
||||
import io.legado.app.utils.toastOnUi
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.CoroutineStart
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import kotlinx.coroutines.asCoroutineDispatcher
|
||||
import kotlinx.coroutines.launch
|
||||
import org.mozilla.javascript.WrappedException
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.math.min
|
||||
@@ -139,7 +142,7 @@ class CheckSourceService : BaseService() {
|
||||
if (CheckSource.checkSearch) {
|
||||
if (!source.searchUrl.isNullOrBlank()) {
|
||||
source.removeGroup("搜索链接规则为空")
|
||||
val searchBooks = WebBook.searchBookAwait(this, source, searchWord)
|
||||
val searchBooks = WebBook.searchBookAwait(source, searchWord)
|
||||
if (searchBooks.isEmpty()) {
|
||||
source.addGroup("搜索失效")
|
||||
} else {
|
||||
@@ -164,7 +167,7 @@ class CheckSourceService : BaseService() {
|
||||
source.addGroup("发现规则为空")
|
||||
} else {
|
||||
source.removeGroup("发现规则为空")
|
||||
val exploreBooks = WebBook.exploreBookAwait(this, source, url)
|
||||
val exploreBooks = WebBook.exploreBookAwait(source, url)
|
||||
if (exploreBooks.isEmpty()) {
|
||||
source.addGroup("发现失效")
|
||||
} else {
|
||||
@@ -205,13 +208,13 @@ class CheckSourceService : BaseService() {
|
||||
//校验详情
|
||||
if (CheckSource.checkInfo) {
|
||||
if (mBook.tocUrl.isBlank()) {
|
||||
mBook = WebBook.getBookInfoAwait(this, source, mBook)
|
||||
mBook = WebBook.getBookInfoAwait(source, mBook)
|
||||
}
|
||||
//校验目录
|
||||
if (CheckSource.checkCategory &&
|
||||
source.bookSourceType != BookType.file
|
||||
) {
|
||||
val toc = WebBook.getChapterListAwait(this, source, mBook).getOrThrow()
|
||||
val toc = WebBook.getChapterListAwait(source, mBook).getOrThrow()
|
||||
val nextChapterUrl = toc.getOrNull(1)?.url ?: toc.first().url
|
||||
//校验正文
|
||||
if (CheckSource.checkContent) {
|
||||
|
||||
@@ -23,7 +23,6 @@ import io.legado.app.help.BookHelp
|
||||
import io.legado.app.help.ContentProcessor
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.utils.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
@@ -37,6 +36,7 @@ import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.nio.charset.Charset
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
|
||||
class CacheViewModel(application: Application) : BaseViewModel(application) {
|
||||
@@ -79,9 +79,9 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
||||
val uri = Uri.parse(path)
|
||||
val doc = DocumentFile.fromTreeUri(context, uri)
|
||||
?: throw NoStackTraceException("获取导出文档失败")
|
||||
export(this, doc, book)
|
||||
export(doc, book)
|
||||
} else {
|
||||
export(this, FileUtils.createFolderIfNotExist(path), book)
|
||||
export(FileUtils.createFolderIfNotExist(path), book)
|
||||
}
|
||||
}.onError {
|
||||
exportProgress.remove(book.bookUrl)
|
||||
@@ -98,14 +98,14 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
||||
}
|
||||
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
private suspend fun export(scope: CoroutineScope, doc: DocumentFile, book: Book) {
|
||||
private suspend fun export(doc: DocumentFile, book: Book) {
|
||||
val filename = "${getExportFileName(book)}.txt"
|
||||
DocumentUtils.delete(doc, filename)
|
||||
val bookDoc = DocumentUtils.createFileIfNotExist(doc, filename)
|
||||
?: throw NoStackTraceException("创建文档失败,请尝试重新设置导出文件夹")
|
||||
val stringBuilder = StringBuilder()
|
||||
context.contentResolver.openOutputStream(bookDoc.uri, "wa")?.use { bookOs ->
|
||||
getAllContents(scope, book) { text, srcList ->
|
||||
getAllContents(book) { text, srcList ->
|
||||
bookOs.write(text.toByteArray(Charset.forName(AppConfig.exportCharset)))
|
||||
stringBuilder.append(text)
|
||||
srcList?.forEach {
|
||||
@@ -128,12 +128,12 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun export(scope: CoroutineScope, file: File, book: Book) {
|
||||
private suspend fun export(file: File, book: Book) {
|
||||
val filename = "${getExportFileName(book)}.txt"
|
||||
val bookPath = FileUtils.getPath(file, filename)
|
||||
val bookFile = FileUtils.createFileWithReplace(bookPath)
|
||||
val stringBuilder = StringBuilder()
|
||||
getAllContents(scope, book) { text, srcList ->
|
||||
getAllContents(book) { text, srcList ->
|
||||
bookFile.appendText(text, Charset.forName(AppConfig.exportCharset))
|
||||
stringBuilder.append(text)
|
||||
srcList?.forEach {
|
||||
@@ -157,7 +157,6 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
||||
}
|
||||
|
||||
private suspend fun getAllContents(
|
||||
scope: CoroutineScope,
|
||||
book: Book,
|
||||
append: (text: String, srcList: ArrayList<Triple<String, Int, String>>?) -> Unit
|
||||
) {
|
||||
@@ -173,7 +172,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
||||
}"
|
||||
append(qy, null)
|
||||
appDb.bookChapterDao.getChapterList(book.bookUrl).forEachIndexed { index, chapter ->
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
upAdapterLiveData.postValue(book.bookUrl)
|
||||
exportProgress[book.bookUrl] = index
|
||||
BookHelp.getContent(book, chapter).let { content ->
|
||||
@@ -227,9 +226,9 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
||||
val uri = Uri.parse(path)
|
||||
val doc = DocumentFile.fromTreeUri(context, uri)
|
||||
?: throw NoStackTraceException("获取导出文档失败")
|
||||
exportEpub(this, doc, book)
|
||||
exportEpub(doc, book)
|
||||
} else {
|
||||
exportEpub(this, FileUtils.createFolderIfNotExist(path), book)
|
||||
exportEpub(FileUtils.createFolderIfNotExist(path), book)
|
||||
}
|
||||
}.onError {
|
||||
exportProgress.remove(book.bookUrl)
|
||||
@@ -246,7 +245,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
||||
}
|
||||
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
private suspend fun exportEpub(scope: CoroutineScope, doc: DocumentFile, book: Book) {
|
||||
private suspend fun exportEpub(doc: DocumentFile, book: Book) {
|
||||
val filename = "${getExportFileName(book)}.epub"
|
||||
DocumentUtils.delete(doc, filename)
|
||||
val epubBook = EpubBook()
|
||||
@@ -259,7 +258,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
||||
val contentModel = setAssets(doc, book, epubBook)
|
||||
|
||||
//设置正文
|
||||
setEpubContent(scope, contentModel, book, epubBook)
|
||||
setEpubContent(contentModel, book, epubBook)
|
||||
DocumentUtils.createFileIfNotExist(doc, filename)?.let { bookDoc ->
|
||||
context.contentResolver.openOutputStream(bookDoc.uri, "wa")?.use { bookOs ->
|
||||
EpubWriter().write(epubBook, bookOs)
|
||||
@@ -269,7 +268,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
||||
}
|
||||
|
||||
|
||||
private suspend fun exportEpub(scope: CoroutineScope, file: File, book: Book) {
|
||||
private suspend fun exportEpub(file: File, book: Book) {
|
||||
val filename = "${getExportFileName(book)}.epub"
|
||||
val epubBook = EpubBook()
|
||||
epubBook.version = "2.0"
|
||||
@@ -283,7 +282,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
||||
val bookPath = FileUtils.getPath(file, filename)
|
||||
val bookFile = FileUtils.createFileWithReplace(bookPath)
|
||||
//设置正文
|
||||
setEpubContent(scope, contentModel, book, epubBook)
|
||||
setEpubContent(contentModel, book, epubBook)
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
EpubWriter().write(epubBook, FileOutputStream(bookFile))
|
||||
}
|
||||
@@ -438,7 +437,6 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
||||
}
|
||||
|
||||
private suspend fun setEpubContent(
|
||||
scope: CoroutineScope,
|
||||
contentModel: String,
|
||||
book: Book,
|
||||
epubBook: EpubBook
|
||||
@@ -447,7 +445,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
|
||||
val useReplace = AppConfig.exportUseReplace && book.getUseReplaceRule()
|
||||
val contentProcessor = ContentProcessor.get(book.name, book.origin)
|
||||
appDb.bookChapterDao.getChapterList(book.bookUrl).forEachIndexed { index, chapter ->
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
upAdapterLiveData.postValue(book.bookUrl)
|
||||
exportProgress[book.bookUrl] = index
|
||||
BookHelp.getContent(book, chapter).let { content ->
|
||||
|
||||
@@ -21,7 +21,6 @@ import io.legado.app.help.coroutine.Coroutine
|
||||
import io.legado.app.model.webBook.WebBook
|
||||
import io.legado.app.utils.getPrefBoolean
|
||||
import io.legado.app.utils.toastOnUi
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.ExecutorCoroutineDispatcher
|
||||
import kotlinx.coroutines.asCoroutineDispatcher
|
||||
@@ -155,7 +154,7 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
|
||||
}
|
||||
val source = bookSourceList[searchIndex]
|
||||
val task = Coroutine.async(scope = viewModelScope, context = searchPool!!) {
|
||||
val resultBooks = WebBook.searchBookAwait(this, source, name)
|
||||
val resultBooks = WebBook.searchBookAwait(source, name)
|
||||
resultBooks.forEach { searchBook ->
|
||||
if (searchBook.name == name) {
|
||||
if ((AppConfig.changeSourceCheckAuthor && searchBook.author.contains(author))
|
||||
@@ -163,7 +162,7 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
|
||||
) {
|
||||
if (searchBook.latestChapterTitle.isNullOrEmpty()) {
|
||||
if (AppConfig.changeSourceLoadInfo || AppConfig.changeSourceLoadToc) {
|
||||
loadBookInfo(this, source, searchBook.toBook())
|
||||
loadBookInfo(source, searchBook.toBook())
|
||||
} else {
|
||||
searchCallback?.searchSuccess(searchBook)
|
||||
}
|
||||
@@ -183,10 +182,10 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
|
||||
tasks.add(task)
|
||||
}
|
||||
|
||||
private suspend fun loadBookInfo(scope: CoroutineScope, source: BookSource, book: Book) {
|
||||
WebBook.getBookInfoAwait(scope, source, book)
|
||||
private suspend fun loadBookInfo(source: BookSource, book: Book) {
|
||||
WebBook.getBookInfoAwait(source, book)
|
||||
if (context.getPrefBoolean(PreferKey.changeSourceLoadToc)) {
|
||||
loadBookToc(scope, source, book)
|
||||
loadBookToc(source, book)
|
||||
} else {
|
||||
//从详情页里获取最新章节
|
||||
val searchBook = book.toSearchBook()
|
||||
@@ -194,8 +193,8 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadBookToc(scope: CoroutineScope, source: BookSource, book: Book) {
|
||||
val chapters = WebBook.getChapterListAwait(scope, source, book).getOrThrow()
|
||||
private suspend fun loadBookToc(source: BookSource, book: Book) {
|
||||
val chapters = WebBook.getChapterListAwait(source, book).getOrThrow()
|
||||
tocMap[book.bookUrl] = chapters
|
||||
book.latestChapterTitle = chapters.last().title
|
||||
val searchBook: SearchBook = book.toSearchBook()
|
||||
@@ -298,9 +297,9 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
|
||||
val source = appDb.bookSourceDao.getBookSource(book.origin)
|
||||
?: throw NoStackTraceException("书源不存在")
|
||||
if (book.tocUrl.isEmpty()) {
|
||||
WebBook.getBookInfoAwait(this, source, book)
|
||||
WebBook.getBookInfoAwait(source, book)
|
||||
}
|
||||
val toc = WebBook.getChapterListAwait(this, source, book).getOrThrow()
|
||||
val toc = WebBook.getChapterListAwait(source, book).getOrThrow()
|
||||
Pair(toc, source)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ class BookshelfManageViewModel(application: Application) : BaseViewModel(applica
|
||||
.onFailure {
|
||||
context.toastOnUi("获取书籍出错\n${it.localizedMessage}")
|
||||
}.getOrNull()?.let { newBook ->
|
||||
WebBook.getChapterListAwait(this, source, newBook)
|
||||
WebBook.getChapterListAwait(source, newBook)
|
||||
.onFailure {
|
||||
context.toastOnUi("获取目录出错\n${it.localizedMessage}")
|
||||
}.getOrNull()?.let { toc ->
|
||||
|
||||
@@ -245,9 +245,9 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
|
||||
sources.forEach { source ->
|
||||
WebBook.preciseSearchAwait(this, source, name, author).getOrNull()?.let { book ->
|
||||
if (book.tocUrl.isEmpty()) {
|
||||
WebBook.getBookInfoAwait(this, source, book)
|
||||
WebBook.getBookInfoAwait(source, book)
|
||||
}
|
||||
val toc = WebBook.getChapterListAwait(this, source, book).getOrThrow()
|
||||
val toc = WebBook.getChapterListAwait(source, book).getOrThrow()
|
||||
changeTo(source, book, toc)
|
||||
return@execute
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ class SearchContentActivity :
|
||||
binding.fbStop.visible()
|
||||
val searchResults = withContext(IO) {
|
||||
if (isLocalBook || viewModel.cacheChapterNames.contains(bookChapter.getFileName())) {
|
||||
viewModel.searchChapter(this, query, bookChapter)
|
||||
viewModel.searchChapter(query, bookChapter)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ import io.legado.app.data.entities.BookChapter
|
||||
import io.legado.app.help.BookHelp
|
||||
import io.legado.app.help.ContentProcessor
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
class SearchContentViewModel(application: Application) : BaseViewModel(application) {
|
||||
var bookUrl: String = ""
|
||||
@@ -38,7 +38,6 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati
|
||||
}
|
||||
|
||||
suspend fun searchChapter(
|
||||
scope: CoroutineScope,
|
||||
query: String,
|
||||
chapter: BookChapter?
|
||||
): List<SearchResult> {
|
||||
@@ -46,7 +45,7 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati
|
||||
if (chapter != null) {
|
||||
book?.let { book ->
|
||||
val chapterContent = BookHelp.getContent(book, chapter)
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
if (chapterContent != null) {
|
||||
//先搜索没有启用净化的正文
|
||||
withContext(Dispatchers.IO) {
|
||||
@@ -55,7 +54,7 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati
|
||||
2 -> ChineseUtils.s2t(chapter.title)
|
||||
else -> chapter.title
|
||||
}
|
||||
scope.ensureActive()
|
||||
kotlin.coroutines.coroutineContext.ensureActive()
|
||||
mContent = contentProcessor!!.getContent(
|
||||
book, chapter, chapterContent,
|
||||
chineseConvert = true,
|
||||
@@ -63,9 +62,9 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati
|
||||
useReplace = false
|
||||
).joinToString("")
|
||||
}
|
||||
val positions = searchPosition(scope, query)
|
||||
val positions = searchPosition(query)
|
||||
positions.forEachIndexed { index, position ->
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
val construct = getResultAndQueryIndex(mContent, position, query)
|
||||
val result = SearchResult(
|
||||
resultCountWithinChapter = index,
|
||||
@@ -85,7 +84,7 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati
|
||||
return searchResultsWithinChapter
|
||||
}
|
||||
|
||||
private suspend fun searchPosition(scope: CoroutineScope, pattern: String): List<Int> {
|
||||
private suspend fun searchPosition(pattern: String): List<Int> {
|
||||
val position: MutableList<Int> = mutableListOf()
|
||||
var index = mContent.indexOf(pattern)
|
||||
if (index >= 0) {
|
||||
@@ -95,7 +94,7 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati
|
||||
index = mContent.indexOf(pattern)
|
||||
}
|
||||
while (index >= 0) {
|
||||
scope.ensureActive()
|
||||
coroutineContext.ensureActive()
|
||||
position.add(index)
|
||||
index = mContent.indexOf(pattern, index + pattern.length)
|
||||
}
|
||||
|
||||
@@ -123,9 +123,9 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
|
||||
AnalyzeRule(book, source).evalJS(preUpdateJs)
|
||||
}
|
||||
if (book.tocUrl.isBlank()) {
|
||||
WebBook.getBookInfoAwait(this, source, book)
|
||||
WebBook.getBookInfoAwait(source, book)
|
||||
}
|
||||
val toc = WebBook.getChapterListAwait(this, source, book).getOrThrow()
|
||||
val toc = WebBook.getChapterListAwait(source, book).getOrThrow()
|
||||
if (book.bookUrl == bookUrl) {
|
||||
appDb.bookDao.update(book)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user