kunfei hace 4 años
padre
commit
77be89a7a0

+ 1 - 1
app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt

@@ -145,7 +145,7 @@ class Coroutine<T>(
         context: CoroutineContext,
         block: suspend CoroutineScope.() -> T
     ): Job {
-        return (scope + Dispatchers.Main).launch(start = startOption) {
+        return (scope.plus(Dispatchers.Main)).launch(start = startOption) {
             try {
                 start?.let { dispatchVoidCallback(this, it) }
                 ensureActive()

+ 48 - 19
app/src/main/java/io/legado/app/utils/RegexExtensions.kt

@@ -1,35 +1,64 @@
 package io.legado.app.utils
 
+import android.util.Log
+import androidx.core.os.postDelayed
 import com.script.SimpleBindings
 import io.legado.app.constant.AppConst
 import io.legado.app.exception.RegexTimeoutException
+import io.legado.app.help.CrashHandler
+import io.legado.app.help.coroutine.Coroutine
+import kotlinx.coroutines.suspendCancellableCoroutine
+import splitties.init.appCtx
+import kotlin.coroutines.resume
+import kotlin.coroutines.resumeWithException
+
+private val handler by lazy { buildMainHandler() }
 
 /**
  * 带有超时检测的正则替换
  */
-fun CharSequence.replace(regex: Regex, replacement: String, timeout: Long): String {
-    val startTime = System.currentTimeMillis()
-    val charSequence = this
+suspend fun CharSequence.replace(regex: Regex, replacement: String, timeout: Long): String {
+    val charSequence = this@replace
     val isJs = replacement.startsWith("@js:")
     val replacement1 = if (isJs) replacement.substring(4) else replacement
-    val pattern = regex.toPattern()
-    val matcher = pattern.matcher(charSequence)
-    val stringBuffer = StringBuffer()
-    while (matcher.find()) {
-        if (System.currentTimeMillis() - startTime > timeout) {
-            val timeoutMsg = "替换超时,将禁用替换规则"
-            throw RegexTimeoutException(timeoutMsg)
+    return suspendCancellableCoroutine { block ->
+        val coroutine = Coroutine.async {
+            try {
+                val pattern = regex.toPattern()
+                val matcher = pattern.matcher(charSequence)
+                val stringBuffer = StringBuffer()
+                while (matcher.find()) {
+                    if (isJs) {
+                        val bindings = SimpleBindings()
+                        bindings["result"] = matcher.group()
+                        val jsResult =
+                            AppConst.SCRIPT_ENGINE.eval(replacement1, bindings).toString()
+                        matcher.appendReplacement(stringBuffer, jsResult)
+                    } else {
+                        matcher.appendReplacement(stringBuffer, replacement1)
+                    }
+                }
+                matcher.appendTail(stringBuffer)
+                Log.e("regex", "end")
+                block.resume(stringBuffer.toString())
+            } catch (e: Exception) {
+                block.resumeWithException(e)
+            }
         }
-        if (isJs) {
-            val bindings = SimpleBindings()
-            bindings["result"] = matcher.group()
-            val jsResult = AppConst.SCRIPT_ENGINE.eval(replacement1, bindings).toString()
-            matcher.appendReplacement(stringBuffer, jsResult)
-        } else {
-            matcher.appendReplacement(stringBuffer, replacement1)
+        handler.postDelayed(timeout) {
+            if (coroutine.isActive) {
+                val timeoutMsg = "替换超时,3秒后还未结束将重启应用\n替换规则$regex\n替换内容:${this}"
+                val exception = RegexTimeoutException(timeoutMsg)
+                block.cancel(exception)
+                appCtx.longToastOnUi(timeoutMsg)
+                CrashHandler.saveCrashInfo2File(exception)
+                handler.postDelayed(3000) {
+                    if (coroutine.isActive) {
+                        appCtx.restart()
+                    }
+                }
+            }
         }
     }
-    matcher.appendTail(stringBuffer)
-    return stringBuffer.toString()
 }