Просмотр исходного кода

Merge remote-tracking branch 'origin/master'

kunfei 3 лет назад
Родитель
Сommit
b802f08228

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

@@ -19,6 +19,7 @@ import kotlin.coroutines.CoroutineContext
 
 /**
  * 链式协程
+ * 注意:如果协程太快完成,回调会不执行
  */
 @Suppress("unused", "MemberVisibilityCanBePrivate")
 class Coroutine<T>(

+ 25 - 17
app/src/main/java/io/legado/app/model/CacheBook.kt

@@ -18,6 +18,7 @@ import io.legado.app.utils.postEvent
 
 import io.legado.app.utils.startService
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.CoroutineStart
 import kotlinx.coroutines.Dispatchers.IO
 import kotlinx.coroutines.delay
 
@@ -268,6 +269,7 @@ object CacheBook {
                 book,
                 chapter,
                 context = context,
+                start = CoroutineStart.LAZY,
                 executeContext = context
             ).onSuccess { content ->
                 onSuccess(chapter)
@@ -282,7 +284,7 @@ object CacheBook {
                 onCancel(chapterIndex)
             }.onFinally {
                 onFinally()
-            }
+            }.start()
         }
 
         @Synchronized
@@ -297,22 +299,28 @@ object CacheBook {
             postEvent(EventBus.UP_DOWNLOAD, book.bookUrl)
             onDownloadSet.add(chapter.index)
             waitDownloadSet.remove(chapter.index)
-            WebBook.getContent(scope, bookSource, book, chapter, executeContext = IO)
-                .onSuccess { content ->
-                    onSuccess(chapter)
-                    ReadBook.downloadedChapters.add(chapter.index)
-                    ReadBook.downloadFailChapters.remove(chapter.index)
-                    downloadFinish(chapter, content, resetPageOffset)
-                }.onError {
-                    onError(chapter, it)
-                    ReadBook.downloadFailChapters[chapter.index] =
-                        (ReadBook.downloadFailChapters[chapter.index] ?: 0) + 1
-                    downloadFinish(chapter, "获取正文失败\n${it.localizedMessage}", resetPageOffset)
-                }.onCancel {
-                    onCancel(chapter.index)
-                }.onFinally {
-                    postEvent(EventBus.UP_DOWNLOAD, book.bookUrl)
-                }
+            WebBook.getContent(
+                scope,
+                bookSource,
+                book,
+                chapter,
+                start = CoroutineStart.LAZY,
+                executeContext = IO
+            ).onSuccess { content ->
+                onSuccess(chapter)
+                ReadBook.downloadedChapters.add(chapter.index)
+                ReadBook.downloadFailChapters.remove(chapter.index)
+                downloadFinish(chapter, content, resetPageOffset)
+            }.onError {
+                onError(chapter, it)
+                ReadBook.downloadFailChapters[chapter.index] =
+                    (ReadBook.downloadFailChapters[chapter.index] ?: 0) + 1
+                downloadFinish(chapter, "获取正文失败\n${it.localizedMessage}", resetPageOffset)
+            }.onCancel {
+                onCancel(chapter.index)
+            }.onFinally {
+                postEvent(EventBus.UP_DOWNLOAD, book.bookUrl)
+            }.start()
         }
 
         private fun downloadFinish(

+ 4 - 1
app/src/main/java/io/legado/app/model/webBook/SearchModel.kt

@@ -11,6 +11,7 @@ import io.legado.app.help.coroutine.CompositeCoroutine
 import io.legado.app.ui.book.search.SearchScope
 import io.legado.app.utils.getPrefBoolean
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.CoroutineStart
 import kotlinx.coroutines.ExecutorCoroutineDispatcher
 import kotlinx.coroutines.asCoroutineDispatcher
 import kotlinx.coroutines.ensureActive
@@ -76,7 +77,7 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB
             return
         }
         searchIndex++
-        val source = bookSourceList[searchIndex]
+        val source = bookSourceList.getOrNull(searchIndex) ?: return
         val searchPool = searchPool ?: return
         val task = WebBook.searchBook(
             scope,
@@ -84,6 +85,7 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB
             searchKey,
             searchPage,
             context = searchPool,
+            start = CoroutineStart.LAZY,
             executeContext = searchPool
         ).timeout(30000L)
             .onSuccess {
@@ -93,6 +95,7 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB
             .onFinally {
                 onFinally(searchId)
             }
+        task.start()
         tasks.add(task)
     }
 

+ 5 - 2
app/src/main/java/io/legado/app/model/webBook/WebBook.kt

@@ -14,6 +14,7 @@ import io.legado.app.model.analyzeRule.AnalyzeRule
 import io.legado.app.model.analyzeRule.AnalyzeUrl
 import io.legado.app.model.analyzeRule.RuleData
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.CoroutineStart
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.isActive
 import kotlin.coroutines.CoroutineContext
@@ -30,9 +31,10 @@ object WebBook {
         key: String,
         page: Int? = 1,
         context: CoroutineContext = Dispatchers.IO,
+        start: CoroutineStart = CoroutineStart.DEFAULT,
         executeContext: CoroutineContext = Dispatchers.Main,
     ): Coroutine<ArrayList<SearchBook>> {
-        return Coroutine.async(scope, context, executeContext = executeContext) {
+        return Coroutine.async(scope, context, start = start, executeContext = executeContext) {
             searchBookAwait(bookSource, key, page)
         }
     }
@@ -266,9 +268,10 @@ object WebBook {
         nextChapterUrl: String? = null,
         needSave: Boolean = true,
         context: CoroutineContext = Dispatchers.IO,
+        start: CoroutineStart = CoroutineStart.DEFAULT,
         executeContext: CoroutineContext = Dispatchers.Main,
     ): Coroutine<String> {
-        return Coroutine.async(scope, context, executeContext = executeContext) {
+        return Coroutine.async(scope, context, start = start, executeContext = executeContext) {
             getContentAwait(bookSource, book, bookChapter, nextChapterUrl, needSave)
         }
     }

+ 1 - 1
app/src/main/java/io/legado/app/service/AudioPlayService.kt

@@ -452,7 +452,7 @@ class AudioPlayService : BaseService(),
                 .setBufferedPosition(exoPlayer.bufferedPosition)
                 .addCustomAction(
                     APP_ACTION_STOP,
-                    getString(R.string.set_timer),
+                    getString(R.string.stop),
                     R.drawable.ic_stop_black_24dp
                 )
                 .addCustomAction(

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

@@ -200,9 +200,13 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
             }
             ++searchIndex
         }
-        val source = bookSourceList[searchIndex]
+        val source = bookSourceList.getOrNull(searchIndex) ?: return
         bookSourceList[searchIndex] = emptyBookSource
-        val task = execute(context = searchPool!!, executeContext = searchPool!!) {
+        val task = execute(
+            context = searchPool!!,
+            start = CoroutineStart.LAZY,
+            executeContext = searchPool!!
+        ) {
             val resultBooks = WebBook.searchBookAwait(source, name)
             resultBooks.forEach { searchBook ->
                 if (searchBook.name != name) {
@@ -223,11 +227,14 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
             }
         }.timeout(60000L)
             .onError {
+                ensureActive()
                 nextSearch()
             }
             .onSuccess {
+                ensureActive()
                 nextSearch()
             }
+        task.start()
         tasks.add(task)
     }
 
@@ -293,8 +300,9 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
         searchCallback?.searchSuccess(searchBook)
     }
 
+    @Synchronized
     private fun nextSearch() {
-        synchronized(this) {
+        kotlin.runCatching {
             if (searchIndex < bookSourceList.lastIndex) {
                 search()
             } else {

+ 18 - 9
app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt

@@ -36,6 +36,7 @@ import org.apache.commons.text.StringEscapeUtils
 import org.jsoup.Jsoup
 import java.io.ByteArrayInputStream
 import java.net.URLDecoder
+import java.util.regex.PatternSyntaxException
 
 /**
  * rss阅读界面
@@ -346,24 +347,32 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
             request: WebResourceRequest
         ): WebResourceResponse? {
             val url = request.url.toString()
-            viewModel.rssSource?.let { source ->
-                val blacklist = source.contentBlacklist?.splitNotBlank(",")
-                if (!blacklist.isNullOrEmpty()) {
-                    blacklist.forEach {
+            val source = viewModel.rssSource ?: return super.shouldInterceptRequest(view, request)
+            val blacklist = source.contentBlacklist?.splitNotBlank(",")
+            if (!blacklist.isNullOrEmpty()) {
+                blacklist.forEach {
+                    try {
                         if (url.startsWith(it) || url.matches(it.toRegex())) {
                             return createEmptyResource()
                         }
+                    } catch (e: PatternSyntaxException) {
+                        AppLog.put("黑名单规则正则语法错误 源名称:${source.sourceName} 正则:$it", e)
                     }
-                } else {
-                    val whitelist = source.contentWhitelist?.splitNotBlank(",")
-                    if (!whitelist.isNullOrEmpty()) {
-                        whitelist.forEach {
+                }
+            } else {
+                val whitelist = source.contentWhitelist?.splitNotBlank(",")
+                if (!whitelist.isNullOrEmpty()) {
+                    whitelist.forEach {
+                        try {
                             if (url.startsWith(it) || url.matches(it.toRegex())) {
                                 return super.shouldInterceptRequest(view, request)
                             }
+                        } catch (e: PatternSyntaxException) {
+                            val msg = "白名单规则正则语法错误 源名称:${source.sourceName} 正则:$it"
+                            AppLog.put(msg, e)
                         }
-                        return createEmptyResource()
                     }
+                    return createEmptyResource()
                 }
             }
             return super.shouldInterceptRequest(view, request)

+ 5 - 6
app/src/main/java/io/legado/app/utils/ToastUtils.kt

@@ -4,6 +4,7 @@ package io.legado.app.utils
 
 import android.annotation.SuppressLint
 import android.content.Context
+import android.view.View
 import android.widget.TextView
 import android.widget.Toast
 import androidx.cardview.widget.CardView
@@ -28,12 +29,10 @@ fun Context.toastOnUi(message: Int, duration: Int = Toast.LENGTH_SHORT) {
 fun Context.toastOnUi(message: CharSequence?, duration: Int = Toast.LENGTH_SHORT) {
     runOnUI {
         kotlin.runCatching {
-            if (toast == null || BuildConfig.DEBUG || AppConfig.recordLog) {
-                toast?.cancel()
-                toast = Toast(this)
-                toast?.view = inflate(R.layout.view_toast)
-            }
-            val toastView = toast?.view!!
+            toast?.cancel()
+            toast = Toast(this)
+            val toastView: View = inflate(R.layout.view_toast)
+            toast?.view = toastView
             val cardView = toastView.findViewById<CardView>(R.id.cv_content)
             cardView.setCardBackgroundColor(bottomBackground)
             val isLight = ColorUtils.isColorLight(bottomBackground)