Horis před 1 rokem
rodič
revize
5d508f0f6c

+ 9 - 9
app/src/main/java/io/legado/app/help/JsExtensions.kt

@@ -47,7 +47,6 @@ import io.legado.app.utils.toStringArray
 import io.legado.app.utils.toastOnUi
 import kotlinx.coroutines.Dispatchers.IO
 import kotlinx.coroutines.async
-import kotlinx.coroutines.ensureActive
 import kotlinx.coroutines.runBlocking
 import okio.use
 import org.jsoup.Connection
@@ -83,11 +82,11 @@ interface JsExtensions : JsEncodeUtils {
 
     fun getSource(): BaseSource?
 
+    private val rhinoContext: RhinoContext
+        get() = Context.getCurrentContext() as RhinoContext
+
     private val context: CoroutineContext
-        get() {
-            val rhinoContext = Context.getCurrentContext() as RhinoContext
-            return rhinoContext.coroutineContext ?: EmptyCoroutineContext
-        }
+        get() = rhinoContext.coroutineContext ?: EmptyCoroutineContext
 
     /**
      * 访问网络,返回String
@@ -361,7 +360,7 @@ interface JsExtensions : JsEncodeUtils {
         } else headers
         val rateLimiter = ConcurrentRateLimiter(getSource())
         val response = rateLimiter.withLimitBlocking {
-            context.ensureActive()
+            rhinoContext.ensureActive()
             Jsoup.connect(urlStr)
                 .sslSocketFactory(SSLHelper.unsafeSSLSocketFactory)
                 .ignoreContentType(true)
@@ -382,7 +381,7 @@ interface JsExtensions : JsEncodeUtils {
         } else headers
         val rateLimiter = ConcurrentRateLimiter(getSource())
         val response = rateLimiter.withLimitBlocking {
-            context.ensureActive()
+            rhinoContext.ensureActive()
             Jsoup.connect(urlStr)
                 .sslSocketFactory(SSLHelper.unsafeSSLSocketFactory)
                 .ignoreContentType(true)
@@ -403,7 +402,7 @@ interface JsExtensions : JsEncodeUtils {
         } else headers
         val rateLimiter = ConcurrentRateLimiter(getSource())
         val response = rateLimiter.withLimitBlocking {
-            context.ensureActive()
+            rhinoContext.ensureActive()
             Jsoup.connect(urlStr)
                 .sslSocketFactory(SSLHelper.unsafeSSLSocketFactory)
                 .ignoreContentType(true)
@@ -897,7 +896,8 @@ interface JsExtensions : JsEncodeUtils {
         s ?: return null
         val matcher = AppPattern.titleNumPattern.matcher(s)
         if (matcher.find()) {
-            return "${matcher.group(1)}${StringUtils.stringToInt(matcher.group(2))}${matcher.group(3)}"
+            val intStr = StringUtils.stringToInt(matcher.group(2))
+            return "${matcher.group(1)}${intStr}${matcher.group(3)}"
         }
         return s
     }

+ 2 - 0
app/src/main/java/io/legado/app/model/CacheBook.kt

@@ -21,6 +21,7 @@ import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.CoroutineStart
 import kotlinx.coroutines.Dispatchers.IO
 import kotlinx.coroutines.delay
+import kotlinx.coroutines.sync.Semaphore
 import java.util.concurrent.ConcurrentHashMap
 import kotlin.coroutines.CoroutineContext
 
@@ -338,6 +339,7 @@ object CacheBook {
         fun download(
             scope: CoroutineScope,
             chapter: BookChapter,
+            semaphore: Semaphore?,
             resetPageOffset: Boolean = false
         ) {
             if (onDownloadSet.contains(chapter.index)) {

+ 15 - 3
app/src/main/java/io/legado/app/model/ReadBook.kt

@@ -42,6 +42,7 @@ import kotlinx.coroutines.ensureActive
 import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.receiveAsFlow
 import kotlinx.coroutines.launch
+import kotlinx.coroutines.sync.Semaphore
 import kotlinx.coroutines.withContext
 import splitties.init.appCtx
 import kotlin.math.max
@@ -92,6 +93,7 @@ object ReadBook : CoroutineScope by MainScope() {
     val downloadFailChapters = hashMapOf<Int, Int>()
     var contentProcessor: ContentProcessor? = null
     val downloadScope = CoroutineScope(SupervisorJob() + IO)
+    val preDownloadSemaphore = Semaphore(2)
     val executor = globalExecutor
 
     //暂时保存跳转前进度
@@ -492,6 +494,8 @@ object ReadBook : CoroutineScope by MainScope() {
 
     val isScroll inline get() = pageAnim() == scrollPageAnim
 
+    val contentLoadFinish get() = curTextChapter != null || msg != null
+
     /**
      * chapterOnDur: 0为当前页,1为下一页,-1为上一页
      */
@@ -612,10 +616,10 @@ object ReadBook : CoroutineScope by MainScope() {
                         downloadedChapters.add(chapter.index)
                     } else {
                         delay(1000)
-                        download(downloadScope, chapter, false)
+                        download(downloadScope, chapter, false, preDownloadSemaphore)
                     }
                 } ?: removeLoading(index)
-            } catch (e: Exception) {
+            } catch (_: Exception) {
                 removeLoading(index)
             }
         }
@@ -628,12 +632,13 @@ object ReadBook : CoroutineScope by MainScope() {
         scope: CoroutineScope,
         chapter: BookChapter,
         resetPageOffset: Boolean,
+        semaphore: Semaphore? = null,
         success: (() -> Unit)? = null
     ) {
         val book = book ?: return removeLoading(chapter.index)
         val bookSource = bookSource
         if (bookSource != null) {
-            CacheBook.getOrCreate(bookSource, book).download(scope, chapter)
+            CacheBook.getOrCreate(bookSource, book).download(scope, chapter, semaphore)
         } else {
             val msg = if (book.isLocal) "无内容" else "没有书源"
             contentLoadFinish(
@@ -905,6 +910,13 @@ object ReadBook : CoroutineScope by MainScope() {
         }
     }
 
+    fun cancelPreDownloadTask() {
+        if (contentLoadFinish) {
+            preDownloadTask?.cancel()
+            downloadScope.coroutineContext.cancelChildren()
+        }
+    }
+
     /**
      * 注册回调
      */

+ 8 - 1
app/src/main/java/io/legado/app/model/webBook/WebBook.kt

@@ -20,6 +20,8 @@ import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.CoroutineStart
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.isActive
+import kotlinx.coroutines.sync.Semaphore
+import kotlinx.coroutines.sync.withPermit
 import kotlin.coroutines.CoroutineContext
 import kotlin.coroutines.coroutineContext
 
@@ -282,9 +284,14 @@ object WebBook {
         context: CoroutineContext = Dispatchers.IO,
         start: CoroutineStart = CoroutineStart.DEFAULT,
         executeContext: CoroutineContext = Dispatchers.Main,
+        semaphore: Semaphore? = null,
     ): Coroutine<String> {
         return Coroutine.async(scope, context, start = start, executeContext = executeContext) {
-            getContentAwait(bookSource, book, bookChapter, nextChapterUrl, needSave)
+            semaphore?.withPermit {
+                getContentAwait(bookSource, book, bookChapter, nextChapterUrl, needSave)
+            } ?: run {
+                getContentAwait(bookSource, book, bookChapter, nextChapterUrl, needSave)
+            }
         }
     }
 

+ 3 - 0
app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt

@@ -312,6 +312,8 @@ class ReadBookActivity : BaseReadBookActivity(),
         upSystemUiVisibility()
         if (hasFocus) {
             binding.readMenu.upBrightnessState()
+        } else if (!menuLayoutIsVisible) {
+            ReadBook.cancelPreDownloadTask()
         }
     }
 
@@ -356,6 +358,7 @@ class ReadBookActivity : BaseReadBookActivity(),
         autoPageStop()
         backupJob?.cancel()
         ReadBook.saveRead()
+        ReadBook.cancelPreDownloadTask()
         unregisterReceiver(timeBatteryReceiver)
         upSystemUiVisibility()
         if (!BuildConfig.DEBUG) {