diff --git a/app/src/main/java/io/legado/app/model/rss/Rss.kt b/app/src/main/java/io/legado/app/model/rss/Rss.kt index cc81f3953..444cb2cd7 100644 --- a/app/src/main/java/io/legado/app/model/rss/Rss.kt +++ b/app/src/main/java/io/legado/app/model/rss/Rss.kt @@ -45,7 +45,7 @@ object Rss { ) val res = analyzeUrl.getStrResponseAwait() checkRedirect(rssSource, res) - return RssParserByRule.parseXML(sortName, sortUrl, res.body, rssSource, ruleData) + return RssParserByRule.parseXML(sortName, sortUrl, res.url, res.body, rssSource, ruleData) } fun getContent( @@ -79,6 +79,7 @@ object Rss { val analyzeRule = AnalyzeRule(rssArticle, rssSource) analyzeRule.setContent(res.body) .setBaseUrl(NetworkUtils.getAbsoluteURL(rssArticle.origin, rssArticle.link)) + .setRedirectUrl(res.url) return analyzeRule.getString(ruleContent) } diff --git a/app/src/main/java/io/legado/app/model/rss/RssParserByRule.kt b/app/src/main/java/io/legado/app/model/rss/RssParserByRule.kt index 8f3621be6..0f4c41b20 100644 --- a/app/src/main/java/io/legado/app/model/rss/RssParserByRule.kt +++ b/app/src/main/java/io/legado/app/model/rss/RssParserByRule.kt @@ -10,7 +10,7 @@ import io.legado.app.model.analyzeRule.AnalyzeRule import io.legado.app.model.analyzeRule.RuleData import io.legado.app.utils.NetworkUtils import splitties.init.appCtx -import java.util.* +import java.util.Locale @Keep object RssParserByRule { @@ -19,6 +19,7 @@ object RssParserByRule { fun parseXML( sortName: String, sortUrl: String, + redirectUrl: String, body: String?, rssSource: RssSource, ruleData: RuleData @@ -40,7 +41,7 @@ object RssParserByRule { val articleList = mutableListOf() val analyzeRule = AnalyzeRule(ruleData, rssSource) analyzeRule.setContent(body).setBaseUrl(sortUrl) - analyzeRule.setRedirectUrl(sortUrl) + analyzeRule.setRedirectUrl(redirectUrl) var reverse = false if (ruleArticles.startsWith("-")) { reverse = true diff --git a/app/src/main/java/io/legado/app/ui/book/import/local/ImportBook.kt b/app/src/main/java/io/legado/app/ui/book/import/local/ImportBook.kt index 0ffa129e7..3fa74d5ab 100644 --- a/app/src/main/java/io/legado/app/ui/book/import/local/ImportBook.kt +++ b/app/src/main/java/io/legado/app/ui/book/import/local/ImportBook.kt @@ -5,7 +5,7 @@ import io.legado.app.utils.FileDoc data class ImportBook( val file: FileDoc, - var isOnBookShelf: Boolean = LocalBook.isOnBookShelf(file.name) + var isOnBookShelf: Boolean = !file.isDir && LocalBook.isOnBookShelf(file.name) ) { val name get() = file.name val isDir get() = file.isDir diff --git a/app/src/main/java/io/legado/app/ui/book/import/local/ImportBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/import/local/ImportBookActivity.kt index b02d9280c..5eb7c58cd 100644 --- a/app/src/main/java/io/legado/app/ui/book/import/local/ImportBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/import/local/ImportBookActivity.kt @@ -253,10 +253,9 @@ class ImportBookActivity : BaseImportBookActivity(), binding.refreshProgressBar.isAutoLoading = true scanDocJob?.cancel() scanDocJob = lifecycleScope.launch(IO) { - viewModel.scanDoc(lastDoc, true) { - withContext(Main) { - binding.refreshProgressBar.isAutoLoading = false - } + viewModel.scanDoc(lastDoc) + withContext(Main) { + binding.refreshProgressBar.isAutoLoading = false } } } diff --git a/app/src/main/java/io/legado/app/ui/book/import/local/ImportBookViewModel.kt b/app/src/main/java/io/legado/app/ui/book/import/local/ImportBookViewModel.kt index 33d148b81..0736d1b61 100644 --- a/app/src/main/java/io/legado/app/ui/book/import/local/ImportBookViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/import/local/ImportBookViewModel.kt @@ -12,18 +12,23 @@ import io.legado.app.utils.FileDoc import io.legado.app.utils.delete import io.legado.app.utils.getPrefInt import io.legado.app.utils.list +import io.legado.app.utils.mapParallel import io.legado.app.utils.toastOnUi import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main -import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.consumeAsFlow import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map -import kotlinx.coroutines.isActive +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.takeWhile import kotlinx.coroutines.withContext import java.util.Collections -import kotlin.coroutines.coroutineContext class ImportBookViewModel(application: Application) : BaseViewModel(application) { var rootDoc: FileDoc? = null @@ -98,6 +103,8 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application) }.onError { context.toastOnUi("添加书架失败,请尝试重新选择文件夹") AppLog.put("添加书架失败\n${it.localizedMessage}", it) + }.onSuccess { + context.toastOnUi("添加书架成功") }.onFinally { finally.invoke() } @@ -128,47 +135,32 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application) } } - suspend fun scanDoc( - fileDoc: FileDoc, - isRoot: Boolean, - finally: (suspend () -> Unit)? = null - ) { - if (isRoot) { - dataCallback?.clear() - } - if (!coroutineContext.isActive) { - finally?.invoke() - return - } - kotlin.runCatching { - val list = ArrayList() - fileDoc.list()!!.forEach { docItem -> - if (!coroutineContext.isActive) { - finally?.invoke() - return + suspend fun scanDoc(fileDoc: FileDoc) { + dataCallback?.clear() + val channel = Channel(UNLIMITED) + var n = 1 + channel.trySend(fileDoc) + val list = arrayListOf() + channel.consumeAsFlow() + .mapParallel(64) { fileDoc -> + fileDoc.list()!! + }.onEach { fileDocs -> + n-- + list.clear() + fileDocs.forEach { + if (it.isDir) { + n++ + channel.trySend(it) + } else { + list.add(it) + } } - if (docItem.isDir) { - scanDoc(docItem, false) - } else if (docItem.name.matches(bookFileRegex) || docItem.name.matches( - archiveFileRegex - ) - ) { - list.add(docItem) - } - } - if (!coroutineContext.isActive) { - finally?.invoke() - return - } - if (list.isNotEmpty()) { dataCallback?.addItems(list) - } - }.onFailure { - context.toastOnUi("扫描文件夹出错\n${it.localizedMessage}") - } - if (isRoot) { - finally?.invoke() - } + }.takeWhile { + n > 0 + }.catch { + context.toastOnUi("扫描文件夹出错\n${it.localizedMessage}") + }.collect() } fun updateCallBackFlow(filterKey: String?) {