Horis 1 год назад
Родитель
Сommit
aa5d479138

+ 2 - 1
app/src/main/java/io/legado/app/model/rss/Rss.kt

@@ -45,7 +45,7 @@ object Rss {
         )
         )
         val res = analyzeUrl.getStrResponseAwait()
         val res = analyzeUrl.getStrResponseAwait()
         checkRedirect(rssSource, res)
         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(
     fun getContent(
@@ -79,6 +79,7 @@ object Rss {
         val analyzeRule = AnalyzeRule(rssArticle, rssSource)
         val analyzeRule = AnalyzeRule(rssArticle, rssSource)
         analyzeRule.setContent(res.body)
         analyzeRule.setContent(res.body)
             .setBaseUrl(NetworkUtils.getAbsoluteURL(rssArticle.origin, rssArticle.link))
             .setBaseUrl(NetworkUtils.getAbsoluteURL(rssArticle.origin, rssArticle.link))
+            .setRedirectUrl(res.url)
         return analyzeRule.getString(ruleContent)
         return analyzeRule.getString(ruleContent)
     }
     }
 
 

+ 3 - 2
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.model.analyzeRule.RuleData
 import io.legado.app.utils.NetworkUtils
 import io.legado.app.utils.NetworkUtils
 import splitties.init.appCtx
 import splitties.init.appCtx
-import java.util.*
+import java.util.Locale
 
 
 @Keep
 @Keep
 object RssParserByRule {
 object RssParserByRule {
@@ -19,6 +19,7 @@ object RssParserByRule {
     fun parseXML(
     fun parseXML(
         sortName: String,
         sortName: String,
         sortUrl: String,
         sortUrl: String,
+        redirectUrl: String,
         body: String?,
         body: String?,
         rssSource: RssSource,
         rssSource: RssSource,
         ruleData: RuleData
         ruleData: RuleData
@@ -40,7 +41,7 @@ object RssParserByRule {
             val articleList = mutableListOf<RssArticle>()
             val articleList = mutableListOf<RssArticle>()
             val analyzeRule = AnalyzeRule(ruleData, rssSource)
             val analyzeRule = AnalyzeRule(ruleData, rssSource)
             analyzeRule.setContent(body).setBaseUrl(sortUrl)
             analyzeRule.setContent(body).setBaseUrl(sortUrl)
-            analyzeRule.setRedirectUrl(sortUrl)
+            analyzeRule.setRedirectUrl(redirectUrl)
             var reverse = false
             var reverse = false
             if (ruleArticles.startsWith("-")) {
             if (ruleArticles.startsWith("-")) {
                 reverse = true
                 reverse = true

+ 1 - 1
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(
 data class ImportBook(
     val file: FileDoc,
     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 name get() = file.name
     val isDir get() = file.isDir
     val isDir get() = file.isDir

+ 3 - 4
app/src/main/java/io/legado/app/ui/book/import/local/ImportBookActivity.kt

@@ -253,10 +253,9 @@ class ImportBookActivity : BaseImportBookActivity<ImportBookViewModel>(),
             binding.refreshProgressBar.isAutoLoading = true
             binding.refreshProgressBar.isAutoLoading = true
             scanDocJob?.cancel()
             scanDocJob?.cancel()
             scanDocJob = lifecycleScope.launch(IO) {
             scanDocJob = lifecycleScope.launch(IO) {
-                viewModel.scanDoc(lastDoc, true) {
-                    withContext(Main) {
-                        binding.refreshProgressBar.isAutoLoading = false
-                    }
+                viewModel.scanDoc(lastDoc)
+                withContext(Main) {
+                    binding.refreshProgressBar.isAutoLoading = false
                 }
                 }
             }
             }
         }
         }

+ 34 - 42
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.delete
 import io.legado.app.utils.getPrefInt
 import io.legado.app.utils.getPrefInt
 import io.legado.app.utils.list
 import io.legado.app.utils.list
+import io.legado.app.utils.mapParallel
 import io.legado.app.utils.toastOnUi
 import io.legado.app.utils.toastOnUi
 import kotlinx.coroutines.Dispatchers.IO
 import kotlinx.coroutines.Dispatchers.IO
 import kotlinx.coroutines.Dispatchers.Main
 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.channels.awaitClose
 import kotlinx.coroutines.flow.callbackFlow
 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.flowOn
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.isActive
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.takeWhile
 import kotlinx.coroutines.withContext
 import kotlinx.coroutines.withContext
 import java.util.Collections
 import java.util.Collections
-import kotlin.coroutines.coroutineContext
 
 
 class ImportBookViewModel(application: Application) : BaseViewModel(application) {
 class ImportBookViewModel(application: Application) : BaseViewModel(application) {
     var rootDoc: FileDoc? = null
     var rootDoc: FileDoc? = null
@@ -98,6 +103,8 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application)
         }.onError {
         }.onError {
             context.toastOnUi("添加书架失败,请尝试重新选择文件夹")
             context.toastOnUi("添加书架失败,请尝试重新选择文件夹")
             AppLog.put("添加书架失败\n${it.localizedMessage}", it)
             AppLog.put("添加书架失败\n${it.localizedMessage}", it)
+        }.onSuccess {
+            context.toastOnUi("添加书架成功")
         }.onFinally {
         }.onFinally {
             finally.invoke()
             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>()
-            fileDoc.list()!!.forEach { docItem ->
-                if (!coroutineContext.isActive) {
-                    finally?.invoke()
-                    return
-                }
-                if (docItem.isDir) {
-                    scanDoc(docItem, false)
-                } else if (docItem.name.matches(bookFileRegex) || docItem.name.matches(
-                        archiveFileRegex
-                    )
-                ) {
-                    list.add(docItem)
+    suspend fun scanDoc(fileDoc: FileDoc) {
+        dataCallback?.clear()
+        val channel = Channel<FileDoc>(UNLIMITED)
+        var n = 1
+        channel.trySend(fileDoc)
+        val list = arrayListOf<FileDoc>()
+        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 (!coroutineContext.isActive) {
-                finally?.invoke()
-                return
-            }
-            if (list.isNotEmpty()) {
                 dataCallback?.addItems(list)
                 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?) {
     fun updateCallBackFlow(filterKey: String?) {