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

+ 63 - 65
app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt

@@ -64,6 +64,7 @@ class AnalyzeRule(
     private var analyzeByJSonPath: AnalyzeByJSonPath? = null
 
     private val stringRuleCache = hashMapOf<String, List<SourceRule>>()
+    private val regexCache = hashMapOf<String, Regex?>()
 
     private var coroutineContext: CoroutineContext = EmptyCoroutineContext
 
@@ -189,37 +190,37 @@ class AnalyzeRule(
                 for (sourceRule in ruleList) {
                     putRule(sourceRule.putMap)
                     sourceRule.makeUpRule(result)
-                    result?.let {
-                        if (sourceRule.rule.isNotEmpty()) {
-                            result = when (sourceRule.mode) {
-                                Mode.Js -> evalJS(sourceRule.rule, result)
-                                Mode.Json -> getAnalyzeByJSonPath(it).getStringList(sourceRule.rule)
-                                Mode.XPath -> getAnalyzeByXPath(it).getStringList(sourceRule.rule)
-                                Mode.Default -> getAnalyzeByJSoup(it).getStringList(sourceRule.rule)
-                                else -> sourceRule.rule
-                            }
+                    result ?: continue
+                    val rule = sourceRule.rule
+                    if (rule.isNotEmpty()) {
+                        result = when (sourceRule.mode) {
+                            Mode.Js -> evalJS(rule, result)
+                            Mode.Json -> getAnalyzeByJSonPath(result).getStringList(rule)
+                            Mode.XPath -> getAnalyzeByXPath(result).getStringList(rule)
+                            Mode.Default -> getAnalyzeByJSoup(result).getStringList(rule)
+                            else -> rule
                         }
-                        if (sourceRule.replaceRegex.isNotEmpty() && result is List<*>) {
-                            val newList = ArrayList<String>()
-                            for (item in result as List<*>) {
-                                newList.add(replaceRegex(item.toString(), sourceRule))
-                            }
-                            result = newList
-                        } else if (sourceRule.replaceRegex.isNotEmpty()) {
-                            result = replaceRegex(result.toString(), sourceRule)
+                    }
+                    if (sourceRule.replaceRegex.isNotEmpty() && result is List<*>) {
+                        val newList = ArrayList<String>()
+                        for (item in result) {
+                            newList.add(replaceRegex(item.toString(), sourceRule))
                         }
+                        result = newList
+                    } else if (sourceRule.replaceRegex.isNotEmpty()) {
+                        result = replaceRegex(result.toString(), sourceRule)
                     }
                 }
             }
         }
         if (result == null) return null
         if (result is String) {
-            result = (result as String).split("\n")
+            result = result.split("\n")
         }
         if (isUrl) {
             val urlList = ArrayList<String>()
             if (result is List<*>) {
-                for (url in result as List<*>) {
+                for (url in result) {
                     val absoluteURL = NetworkUtils.getAbsoluteURL(redirectUrl, url.toString())
                     if (absoluteURL.isNotEmpty() && !urlList.contains(absoluteURL)) {
                         urlList.add(absoluteURL)
@@ -276,25 +277,25 @@ class AnalyzeRule(
                 for (sourceRule in ruleList) {
                     putRule(sourceRule.putMap)
                     sourceRule.makeUpRule(result)
-                    result?.let {
-                        if (sourceRule.rule.isNotBlank() || sourceRule.replaceRegex.isEmpty()) {
-                            result = when (sourceRule.mode) {
-                                Mode.Js -> evalJS(sourceRule.rule, it)
-                                Mode.Json -> getAnalyzeByJSonPath(it).getString(sourceRule.rule)
-                                Mode.XPath -> getAnalyzeByXPath(it).getString(sourceRule.rule)
-                                Mode.Default -> if (isUrl) {
-                                    getAnalyzeByJSoup(it).getString0(sourceRule.rule)
-                                } else {
-                                    getAnalyzeByJSoup(it).getString(sourceRule.rule)
-                                }
-
-                                else -> sourceRule.rule
+                    result ?: continue
+                    val rule = sourceRule.rule
+                    if (rule.isNotBlank() || sourceRule.replaceRegex.isEmpty()) {
+                        result = when (sourceRule.mode) {
+                            Mode.Js -> evalJS(rule, result)
+                            Mode.Json -> getAnalyzeByJSonPath(result).getString(rule)
+                            Mode.XPath -> getAnalyzeByXPath(result).getString(rule)
+                            Mode.Default -> if (isUrl) {
+                                getAnalyzeByJSoup(result).getString0(rule)
+                            } else {
+                                getAnalyzeByJSoup(result).getString(rule)
                             }
-                        }
-                        if ((result != null) && sourceRule.replaceRegex.isNotEmpty()) {
-                            result = replaceRegex(result.toString(), sourceRule)
+
+                            else -> rule
                         }
                     }
+                    if (result != null && sourceRule.replaceRegex.isNotEmpty()) {
+                        result = replaceRegex(result.toString(), sourceRule)
+                    }
                 }
             }
         }
@@ -328,21 +329,21 @@ class AnalyzeRule(
             for (sourceRule in ruleList) {
                 putRule(sourceRule.putMap)
                 sourceRule.makeUpRule(result)
-                result?.let {
-                    result = when (sourceRule.mode) {
-                        Mode.Regex -> AnalyzeByRegex.getElement(
-                            result.toString(),
-                            sourceRule.rule.splitNotBlank("&&")
-                        )
-
-                        Mode.Js -> evalJS(sourceRule.rule, it)
-                        Mode.Json -> getAnalyzeByJSonPath(it).getObject(sourceRule.rule)
-                        Mode.XPath -> getAnalyzeByXPath(it).getElements(sourceRule.rule)
-                        else -> getAnalyzeByJSoup(it).getElements(sourceRule.rule)
-                    }
-                    if (sourceRule.replaceRegex.isNotEmpty()) {
-                        result = replaceRegex(result.toString(), sourceRule)
-                    }
+                result ?: continue
+                val rule = sourceRule.rule
+                result = when (sourceRule.mode) {
+                    Mode.Regex -> AnalyzeByRegex.getElement(
+                        result.toString(),
+                        rule.splitNotBlank("&&")
+                    )
+
+                    Mode.Js -> evalJS(rule, result)
+                    Mode.Json -> getAnalyzeByJSonPath(result).getObject(rule)
+                    Mode.XPath -> getAnalyzeByXPath(result).getElements(rule)
+                    else -> getAnalyzeByJSoup(result).getElements(rule)
+                }
+                if (sourceRule.replaceRegex.isNotEmpty()) {
+                    result = replaceRegex(result.toString(), sourceRule)
                 }
             }
         }
@@ -361,21 +362,18 @@ class AnalyzeRule(
             result = content
             for (sourceRule in ruleList) {
                 putRule(sourceRule.putMap)
-                result?.let {
-                    result = when (sourceRule.mode) {
-                        Mode.Regex -> AnalyzeByRegex.getElements(
-                            result.toString(),
-                            sourceRule.rule.splitNotBlank("&&")
-                        )
-
-                        Mode.Js -> evalJS(sourceRule.rule, result)
-                        Mode.Json -> getAnalyzeByJSonPath(it).getList(sourceRule.rule)
-                        Mode.XPath -> getAnalyzeByXPath(it).getElements(sourceRule.rule)
-                        else -> getAnalyzeByJSoup(it).getElements(sourceRule.rule)
-                    }
-//                    if (sourceRule.replaceRegex.isNotEmpty()) {
-//                        result = replaceRegex(result.toString(), sourceRule)
-//                    }
+                result ?: continue
+                val rule = sourceRule.rule
+                result = when (sourceRule.mode) {
+                    Mode.Regex -> AnalyzeByRegex.getElements(
+                        result.toString(),
+                        rule.splitNotBlank("&&")
+                    )
+
+                    Mode.Js -> evalJS(rule, result)
+                    Mode.Json -> getAnalyzeByJSonPath(result).getList(rule)
+                    Mode.XPath -> getAnalyzeByXPath(result).getElements(rule)
+                    else -> getAnalyzeByJSoup(result).getElements(rule)
                 }
             }
         }

+ 10 - 8
app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceDialog.kt

@@ -17,6 +17,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import io.legado.app.R
 import io.legado.app.base.BaseDialogFragment
+import io.legado.app.constant.AppLog
 import io.legado.app.constant.EventBus
 import io.legado.app.data.appDb
 import io.legado.app.data.entities.Book
@@ -43,7 +44,6 @@ import io.legado.app.utils.getCompatDrawable
 import io.legado.app.utils.observeEvent
 import io.legado.app.utils.setLayout
 import io.legado.app.utils.startActivity
-import io.legado.app.utils.toastOnUi
 import io.legado.app.utils.viewbindingdelegate.viewBinding
 import kotlinx.coroutines.Dispatchers.IO
 import kotlinx.coroutines.delay
@@ -185,7 +185,9 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_
     private fun initNavigationView() {
         binding.toolBar.navigationIcon =
             getCompatDrawable(androidx.appcompat.R.drawable.abc_ic_ab_back_material)
-        binding.toolBar.setNavigationContentDescription(androidx.appcompat.R.string.abc_action_bar_up_description)
+        binding.toolBar.setNavigationContentDescription(
+            androidx.appcompat.R.string.abc_action_bar_up_description
+        )
         binding.toolBar.setNavigationOnClickListener {
             dismissAllowingStateLoss()
         }
@@ -239,7 +241,7 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_
 
         lifecycleScope.launch {
             repeatOnLifecycle(STARTED) {
-                viewModel.finishedChangeSourceResult
+                viewModel.changeSourceProgress
                     .drop(1)
                     .collect { (count, name) ->
                         binding.tvDur.text =
@@ -387,14 +389,14 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_
         waitDialog.setText(R.string.load_toc)
         waitDialog.show()
         val book = viewModel.bookMap[searchBook.primaryStr()] ?: searchBook.toBook()
-        val coroutine = viewModel.getToc(book, {
-            waitDialog.dismiss()
-            toastOnUi(it)
-        }) { toc, source ->
+        val coroutine = viewModel.getToc(book, { toc, source ->
             waitDialog.dismiss()
             callBack?.changeTo(source, book, toc)
             onSuccess?.invoke()
-        }
+        }, {
+            waitDialog.dismiss()
+            AppLog.put("换源获取目录出错\n$it", it, true)
+        })
         waitDialog.setOnCancelListener {
             coroutine.cancel()
         }

+ 8 - 8
app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt

@@ -68,13 +68,13 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
     private var oldBook: Book? = null
     private var screenKey: String = ""
     private var bookSourceParts = arrayListOf<BookSourcePart>()
-    val totalSourceCount:Int
+    val totalSourceCount: Int
         get() = bookSourceParts.size
     private var searchBookList = arrayListOf<SearchBook>()
     private val searchBooks = Collections.synchronizedList(arrayListOf<SearchBook>())
     private val tocMap = ConcurrentHashMap<String, List<BookChapter>>()
-    private val _finishedChangeSourceResult = MutableStateFlow(0 to "")
-    val finishedChangeSourceResult= _finishedChangeSourceResult.asStateFlow()
+    private val _changeSourceProgress = MutableStateFlow(0 to "")
+    val changeSourceProgress = _changeSourceProgress.asStateFlow()
     private var tocMapChapterCount = 0
     private val contentProcessor by lazy {
         ContentProcessor.get(oldBook!!)
@@ -191,7 +191,7 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
             tocMap.clear()
             bookMap.clear()
             tocMapChapterCount = 0
-            _finishedChangeSourceResult.value = 0 to ""
+            _changeSourceProgress.value = 0 to ""
             val searchGroup = AppConfig.searchGroup
             if (searchGroup.isBlank()) {
                 bookSourceParts.addAll(appDb.bookSourceDao.allEnabledPart)
@@ -243,7 +243,7 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
                 }
                 it
             }.onEachIndexed { index, value ->
-                _finishedChangeSourceResult.update { _ ->
+                _changeSourceProgress.update { _ ->
                     index + 1 to value.bookSourceName
                 }
             }.onCompletion {
@@ -446,8 +446,8 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
 
     fun getToc(
         book: Book,
-        onError: (msg: String) -> Unit,
-        onSuccess: (toc: List<BookChapter>, source: BookSource) -> Unit
+        onSuccess: (toc: List<BookChapter>, source: BookSource) -> Unit,
+        onError: (e: Throwable) -> Unit
     ): Coroutine<Pair<List<BookChapter>, BookSource>> {
         return execute {
             val toc = tocMap[book.primaryStr()]
@@ -461,7 +461,7 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
         }.onSuccess {
             onSuccess.invoke(it.first, it.second)
         }.onError {
-            onError.invoke(it.localizedMessage ?: "获取目录出错")
+            onError.invoke(it)
         }
     }
 

+ 6 - 5
app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt

@@ -18,6 +18,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import io.legado.app.R
 import io.legado.app.base.BaseDialogFragment
+import io.legado.app.constant.AppLog
 import io.legado.app.constant.EventBus
 import io.legado.app.data.appDb
 import io.legado.app.data.entities.Book
@@ -310,16 +311,16 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c
         binding.clToc.visible()
         binding.loadingToc.visible()
         val book = searchBook.toBook()
-        viewModel.getToc(book, {
-            binding.clToc.gone()
-            toastOnUi(it)
-        }) { toc: List<BookChapter>, _: BookSource ->
+        viewModel.getToc(book, { toc: List<BookChapter>, _: BookSource ->
             tocAdapter.durChapterIndex =
                 BookHelp.getDurChapter(viewModel.chapterIndex, viewModel.chapterTitle, toc)
             binding.loadingToc.gone()
             tocAdapter.setItems(toc)
             binding.recyclerViewToc.scrollToPosition(tocAdapter.durChapterIndex - 5)
-        }
+        }, {
+            binding.clToc.gone()
+            AppLog.put("单章换源获取目录出错\n$it", it, true)
+        })
     }
 
     override val oldBookUrl: String?