diff --git a/app/src/main/java/io/legado/app/help/JsExtensions.kt b/app/src/main/java/io/legado/app/help/JsExtensions.kt index 93a8ec98f..7a5fb5fcb 100644 --- a/app/src/main/java/io/legado/app/help/JsExtensions.kt +++ b/app/src/main/java/io/legado/app/help/JsExtensions.kt @@ -82,7 +82,7 @@ interface JsExtensions { }.onFailure { it.printStackTrace() }.getOrElse { - StrResponse(analyzeUrl.url, it.localizedMessage) + StrResponse(analyzeUrl.getDirectUrl(), it.localizedMessage) } } } @@ -96,7 +96,7 @@ interface JsExtensions { }.onFailure { it.printStackTrace() }.getOrElse { - StrResponse(analyzeUrl.url, it.localizedMessage) + StrResponse(analyzeUrl.getDirectUrl(), it.localizedMessage) } } } diff --git a/app/src/main/java/io/legado/app/model/CacheBook.kt b/app/src/main/java/io/legado/app/model/CacheBook.kt index 1b34170ee..baffe0f84 100644 --- a/app/src/main/java/io/legado/app/model/CacheBook.kt +++ b/app/src/main/java/io/legado/app/model/CacheBook.kt @@ -3,6 +3,7 @@ package io.legado.app.model import android.content.Context import io.legado.app.R import io.legado.app.constant.IntentAction +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookSource @@ -12,67 +13,91 @@ import io.legado.app.utils.msg import io.legado.app.utils.startService import kotlinx.coroutines.CoroutineScope import splitties.init.appCtx -import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.CopyOnWriteArraySet -object CacheBook { - val logs = arrayListOf() - private val downloadMap = ConcurrentHashMap>() +class CacheBook(val bookSource: BookSource, val book: Book) { - fun addLog(log: String?) { - log ?: return - synchronized(this) { - if (logs.size > 1000) { - logs.removeAt(0) + companion object { + + val logs = arrayListOf() + private val cacheBookMap = hashMapOf() + + fun get(bookUrl: String): CacheBook? { + var cacheBook = cacheBookMap[bookUrl] + if (cacheBook != null) { + return cacheBook } - logs.add(log) + val book = appDb.bookDao.getBook(bookUrl) ?: return null + val bookSource = appDb.bookSourceDao.getBookSource(book.origin) ?: return null + cacheBook = CacheBook(bookSource, book) + cacheBookMap[bookUrl] = cacheBook + return cacheBook } - } - fun start(context: Context, bookUrl: String, start: Int, end: Int) { - context.startService { - action = IntentAction.start - putExtra("bookUrl", bookUrl) - putExtra("start", start) - putExtra("end", end) + fun get(bookSource: BookSource, book: Book): CacheBook { + var cacheBook = cacheBookMap[book.bookUrl] + if (cacheBook != null) { + return cacheBook + } + cacheBook = CacheBook(bookSource, book) + cacheBookMap[book.bookUrl] = cacheBook + return cacheBook } - } - fun remove(context: Context, bookUrl: String) { - context.startService { - action = IntentAction.remove - putExtra("bookUrl", bookUrl) + fun addLog(log: String?) { + log ?: return + synchronized(this) { + if (logs.size > 1000) { + logs.removeAt(0) + } + logs.add(log) + } } - } - fun stop(context: Context) { - context.startService { - action = IntentAction.stop + fun start(context: Context, bookUrl: String, start: Int, end: Int) { + context.startService { + action = IntentAction.start + putExtra("bookUrl", bookUrl) + putExtra("start", start) + putExtra("end", end) + } } - } - fun downloadCount(): Int { - var count = 0 - downloadMap.forEach { - count += it.value.size + fun remove(context: Context, bookUrl: String) { + context.startService { + action = IntentAction.remove + putExtra("bookUrl", bookUrl) + } } - return count + + fun stop(context: Context) { + context.startService { + action = IntentAction.stop + } + } + + val downloadCount: Int + get() { + var count = 0 + cacheBookMap.forEach { + count += it.value.downloadSet.size + } + return count + } + } + val downloadSet = CopyOnWriteArraySet() + fun download( scope: CoroutineScope, - bookSource: BookSource, - book: Book, chapter: BookChapter, resetPageOffset: Boolean = false ) { - if (downloadMap[book.bookUrl]?.contains(chapter.index) == true) { + if (downloadSet.contains(chapter.index)) { return } - if (downloadMap[book.bookUrl] == null) { - downloadMap[book.bookUrl] = CopyOnWriteArraySet() - } - downloadMap[book.bookUrl]?.add(chapter.index) + downloadSet.add(chapter.index) WebBook.getContent(scope, bookSource, book, chapter) .onSuccess { content -> if (ReadBook.book?.bookUrl == book.bookUrl) { @@ -93,10 +118,7 @@ object CacheBook { ) } }.onFinally { - downloadMap[book.bookUrl]?.remove(chapter.index) - if (downloadMap[book.bookUrl].isNullOrEmpty()) { - downloadMap.remove(book.bookUrl) - } + downloadSet.remove(chapter.index) ReadBook.removeLoading(chapter.index) } } diff --git a/app/src/main/java/io/legado/app/model/ReadBook.kt b/app/src/main/java/io/legado/app/model/ReadBook.kt index 2c75ed3dd..eb5aea66d 100644 --- a/app/src/main/java/io/legado/app/model/ReadBook.kt +++ b/app/src/main/java/io/legado/app/model/ReadBook.kt @@ -295,7 +295,7 @@ object ReadBook : CoroutineScope by MainScope() { val book = book val bookSource = bookSource if (book != null && bookSource != null) { - CacheBook.download(scope, bookSource, book, chapter) + CacheBook.get(bookSource, book).download(scope, chapter) } else if (book != null) { contentLoadFinish( book, chapter, "没有书源", resetPageOffset = resetPageOffset diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt index 7ef656a80..43fbfe5a3 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt @@ -35,7 +35,6 @@ class AnalyzeUrl( val speakText: String? = null, val speakSpeed: Int? = null, var baseUrl: String = "", - var useWebView: Boolean = false, val book: BaseBook? = null, val chapter: BookChapter? = null, private val ruleData: RuleDataInterface? = null, @@ -48,17 +47,18 @@ class AnalyzeUrl( private val accessTime = hashMapOf() } - var url: String = "" val headerMap = HashMap() var body: String? = null var type: String? = null - private lateinit var urlHasQuery: String + private var url: String = "" private var queryStr: String? = null private val fieldMap = LinkedHashMap() private var charset: String? = null private var method = RequestMethod.GET private var proxy: String? = null private var retry: Int = 0 + private var useWebView: Boolean = false + private var webJs: String? = null init { val urlMatcher = paramPattern.matcher(baseUrl) @@ -141,12 +141,13 @@ class AnalyzeUrl( */ private fun initUrl() { //replaceKeyPageJs已经替换掉额外内容,此处url是基础形式,可以直接切首个‘,’之前字符串。 val urlMatcher = paramPattern.matcher(ruleUrl) - urlHasQuery = if (urlMatcher.find()) ruleUrl.substring(0, urlMatcher.start()) else ruleUrl - url = NetworkUtils.getAbsoluteURL(baseUrl, urlHasQuery) + val urlNoOption = + if (urlMatcher.find()) ruleUrl.substring(0, urlMatcher.start()) else ruleUrl + url = NetworkUtils.getAbsoluteURL(baseUrl, urlNoOption) NetworkUtils.getBaseUrl(url)?.let { baseUrl = it } - if (urlHasQuery.length != ruleUrl.length) { + if (urlNoOption.length != ruleUrl.length) { GSON.fromJsonObject(ruleUrl.substring(urlMatcher.end()))?.let { option -> option.method?.let { if (it.equals("POST", true)) method = RequestMethod.POST @@ -171,6 +172,7 @@ class AnalyzeUrl( useWebView = true } } + webJs = option.webJs option.js?.let { evalJS(it) } @@ -183,21 +185,21 @@ class AnalyzeUrl( } when (method) { RequestMethod.GET -> { - if (!useWebView) { - val pos = url.indexOf('?') - if (pos != -1) { - analyzeFields(url.substring(pos + 1)) - url = url.substring(0, pos) - } - } - } - RequestMethod.POST -> { - body?.let { + val pos = url.indexOf('?') + if (pos != -1) { + analyzeFields(url.substring(pos + 1)) + url = url.substring(0, pos) + } else body?.let { if (!it.isJson()) { analyzeFields(it) } } } + RequestMethod.POST -> body?.let { + if (!it.isJson()) { + analyzeFields(it) + } + } } } @@ -416,7 +418,14 @@ class AnalyzeUrl( headerMap.forEach { (key, value) -> headers.addHeader(key, value) } - return GlideUrl(urlHasQuery, headers.build()) + return GlideUrl(getDirectUrl(), headers.build()) + } + + fun getDirectUrl(): String { + val qs = fieldMap.map { + "${it.key}=${it.value}" + } + return "$url?${qs.joinToString("&")}" } fun getUserAgent(): String { @@ -431,6 +440,7 @@ class AnalyzeUrl( val method: String?, val charset: String?, val webView: Any?, + val webJs: String?, val headers: Any?, val body: Any?, val type: String?, diff --git a/app/src/main/java/io/legado/app/service/AudioPlayService.kt b/app/src/main/java/io/legado/app/service/AudioPlayService.kt index b0e60648e..4cf4d3248 100644 --- a/app/src/main/java/io/legado/app/service/AudioPlayService.kt +++ b/app/src/main/java/io/legado/app/service/AudioPlayService.kt @@ -131,10 +131,9 @@ class AudioPlayService : BaseService(), AnalyzeUrl( url, headerMapF = AudioPlay.headers(), - source = AudioPlay.bookSource, - useWebView = true + source = AudioPlay.bookSource ) - val uri = Uri.parse(analyzeUrl.url) + val uri = Uri.parse(analyzeUrl.getDirectUrl()) val dataSourceFactory = OkHttpDataSource.Factory(okHttpClient) .setDefaultRequestProperties(analyzeUrl.headerMap) val mediaSource = ExoPlayerHelper diff --git a/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt b/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt index ac6bda9e7..113027b3a 100644 --- a/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt @@ -118,8 +118,9 @@ class MainViewModel(application: Application) : BaseViewModel(application) { if (!BookHelp.hasContent(book, chapter)) { var addToCache = false while (!addToCache) { - if (CacheBook.downloadCount() < 10) { - CacheBook.download(this, bookSource, book, chapter) + val cacheBook = CacheBook.get(bookSource, book) + if (CacheBook.downloadCount < 10) { + cacheBook.download(this, chapter) addToCache = true } else { delay(100) diff --git a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt index 64448eb51..c8e12c6dd 100644 --- a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt +++ b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt @@ -193,7 +193,7 @@ class ReadRssActivity : VMBaseActivity } viewModel.urlLiveData.observe(this) { upJavaScriptEnable() - binding.webView.loadUrl(it.url, it.headerMap) + binding.webView.loadUrl(it.getDirectUrl(), it.headerMap) } } diff --git a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt index 1badb5706..171bb55b9 100644 --- a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt @@ -84,7 +84,6 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application), val analyzeUrl = AnalyzeUrl( ruleUrl = url, baseUrl = baseUrl, - useWebView = true, headerMapF = rssSource?.getHeaderMap() ) urlLiveData.postValue(analyzeUrl)