mirror of
https://github.com/gedoor/legado.git
synced 2024-07-06 23:47:49 +08:00
Compare commits
3 Commits
7ca6844be3
...
0b5d575405
Author | SHA1 | Date | |
---|---|---|---|
|
0b5d575405 | ||
|
aebdd9f946 | ||
|
9d52d3402d |
@ -111,6 +111,20 @@ interface BookSourceDao {
|
||||
)
|
||||
fun flowNoGroup(): Flow<List<BookSourcePart>>
|
||||
|
||||
@Query(
|
||||
"""select bookSourceUrl, bookSourceName, bookSourceGroup, customOrder, enabled, enabledExplore,
|
||||
trim(loginUrl) <> '' hasLoginUrl, lastUpdateTime, respondTime, weight, trim(exploreUrl) <> '' hasExploreUrl
|
||||
from book_sources where enabledExplore = 1 order by customOrder asc"""
|
||||
)
|
||||
fun flowEnabledExplore(): Flow<List<BookSourcePart>>
|
||||
|
||||
@Query(
|
||||
"""select bookSourceUrl, bookSourceName, bookSourceGroup, customOrder, enabled, enabledExplore,
|
||||
trim(loginUrl) <> '' hasLoginUrl, lastUpdateTime, respondTime, weight, trim(exploreUrl) <> '' hasExploreUrl
|
||||
from book_sources where enabledExplore = 0 order by customOrder asc"""
|
||||
)
|
||||
fun flowDisabledExplore(): Flow<List<BookSourcePart>>
|
||||
|
||||
@Query(
|
||||
"""select * from book_sources
|
||||
where enabledExplore = 1
|
||||
@ -193,6 +207,12 @@ interface BookSourceDao {
|
||||
@get:Query("select * from book_sources where bookSourceGroup is null or bookSourceGroup = '' or bookSourceGroup like '%未分组%'")
|
||||
val allNoGroup: List<BookSource>
|
||||
|
||||
@get:Query("select * from book_sources where enabledExplore = 1 order by customOrder")
|
||||
val allEnabledExplore: List<BookSource>
|
||||
|
||||
@get:Query("select * from book_sources where enabledExplore = 0 order by customOrder")
|
||||
val allDisabledExplore: List<BookSource>
|
||||
|
||||
@get:Query("select * from book_sources where loginUrl is not null and loginUrl != ''")
|
||||
val allLogin: List<BookSource>
|
||||
|
||||
|
@ -133,7 +133,10 @@ object ExoPlayerHelper {
|
||||
* Okhttp DataSource.Factory
|
||||
*/
|
||||
private val okhttpDataFactory by lazy {
|
||||
OkHttpDataSource.Factory(okHttpClient)
|
||||
val client = okHttpClient.newBuilder()
|
||||
.callTimeout(0, TimeUnit.SECONDS)
|
||||
.build()
|
||||
OkHttpDataSource.Factory(client)
|
||||
.setCacheControl(CacheControl.Builder().maxAge(1, TimeUnit.DAYS).build())
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ import java.util.concurrent.atomic.AtomicBoolean
|
||||
abstract class AbsCallBack(
|
||||
var originalRequest: Request,
|
||||
val mCall: Call,
|
||||
var readTimeoutMillis: Int,
|
||||
private val eventListener: EventListener? = null,
|
||||
private val responseCallback: Callback? = null
|
||||
) : UrlRequest.Callback() {
|
||||
@ -52,6 +53,9 @@ abstract class AbsCallBack(
|
||||
private var redirectRequest: Request? = null
|
||||
|
||||
init {
|
||||
if (readTimeoutMillis == 0) {
|
||||
readTimeoutMillis = Int.MAX_VALUE
|
||||
}
|
||||
if (originalRequest.header(cookieJarHeader) != null) {
|
||||
enableCookieJar = true
|
||||
originalRequest = originalRequest.newBuilder()
|
||||
@ -411,7 +415,7 @@ abstract class AbsCallBack(
|
||||
|
||||
private var buffer = ByteBuffer.allocateDirect(32 * 1024)
|
||||
private var closed = false
|
||||
private val timeout = mCall.timeout().timeoutNanos()
|
||||
private val timeout = readTimeoutMillis.toLong()
|
||||
|
||||
override fun close() {
|
||||
cancelJob?.cancel()
|
||||
@ -443,7 +447,7 @@ abstract class AbsCallBack(
|
||||
|
||||
request?.read(buffer)
|
||||
|
||||
val result = callbackResults.poll(timeout, TimeUnit.NANOSECONDS)
|
||||
val result = callbackResults.poll(timeout, TimeUnit.MILLISECONDS)
|
||||
if (result == null) {
|
||||
request?.cancel()
|
||||
throw IOException("Body Read Timeout")
|
||||
|
@ -5,7 +5,12 @@ import io.legado.app.utils.printOnDebug
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import okhttp3.*
|
||||
import okhttp3.Call
|
||||
import okhttp3.CookieJar
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import okhttp3.internal.http.receiveHeaders
|
||||
import org.chromium.net.UrlRequest
|
||||
import org.chromium.net.UrlResponseInfo
|
||||
@ -43,12 +48,12 @@ class CronetCoroutineInterceptor(private val cookieJar: CookieJar) : Interceptor
|
||||
runBlocking() {
|
||||
if (timeout > 0) {
|
||||
withTimeout(timeout) {
|
||||
proceedWithCronet(newReq, chain.call()).also { response ->
|
||||
proceedWithCronet(newReq, chain.call(), chain.readTimeoutMillis()).also { response ->
|
||||
cookieJar.receiveHeaders(newReq.url, response.headers)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
proceedWithCronet(newReq, chain.call()).also { response ->
|
||||
proceedWithCronet(newReq, chain.call(), chain.readTimeoutMillis()).also { response ->
|
||||
cookieJar.receiveHeaders(newReq.url, response.headers)
|
||||
}
|
||||
}
|
||||
@ -68,10 +73,14 @@ class CronetCoroutineInterceptor(private val cookieJar: CookieJar) : Interceptor
|
||||
}
|
||||
|
||||
|
||||
private suspend fun proceedWithCronet(request: Request, call: Call): Response =
|
||||
private suspend fun proceedWithCronet(
|
||||
request: Request,
|
||||
call: Call,
|
||||
readTimeoutMillis: Int
|
||||
): Response =
|
||||
suspendCancellableCoroutine<Response> { coroutine ->
|
||||
|
||||
val callBack = object : AbsCallBack(originalRequest = request, mCall = call) {
|
||||
val callBack = object : AbsCallBack(request, call, readTimeoutMillis) {
|
||||
override fun waitForDone(urlRequest: UrlRequest): Response {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ class CronetInterceptor(private val cookieJar: CookieJar) : Interceptor {
|
||||
builder.removeHeader("Accept-Encoding")
|
||||
|
||||
val newReq = builder.build()
|
||||
proceedWithCronet(newReq, chain.call())/*?.let { response ->
|
||||
proceedWithCronet(newReq, chain.call(), chain.readTimeoutMillis())/*?.let { response ->
|
||||
//从Response 中保存Cookie到CookieJar
|
||||
//cookieJar.receiveHeaders(newReq.url, response.headers)
|
||||
response
|
||||
@ -45,11 +45,11 @@ class CronetInterceptor(private val cookieJar: CookieJar) : Interceptor {
|
||||
}
|
||||
|
||||
@SuppressLint("ObsoleteSdkInt")
|
||||
private fun proceedWithCronet(request: Request, call: Call): Response? {
|
||||
private fun proceedWithCronet(request: Request, call: Call, readTimeoutMillis: Int): Response? {
|
||||
val callBack = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
NewCallBack(request, call)
|
||||
NewCallBack(request, call, readTimeoutMillis)
|
||||
} else {
|
||||
OldCallback(request, call)
|
||||
OldCallback(request, call, readTimeoutMillis)
|
||||
}
|
||||
buildRequest(request, callBack)?.runCatching {
|
||||
return callBack.waitForDone(this)
|
||||
|
@ -15,7 +15,8 @@ import java.util.concurrent.TimeUnit
|
||||
@SuppressLint("ObsoleteSdkInt")
|
||||
@Keep
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
class NewCallBack(originalRequest: Request, mCall: Call) : AbsCallBack(originalRequest, mCall) {
|
||||
class NewCallBack(originalRequest: Request, mCall: Call, readTimeoutMillis: Int) :
|
||||
AbsCallBack(originalRequest, mCall, readTimeoutMillis) {
|
||||
|
||||
private val responseFuture = CompletableFuture<Response>()
|
||||
|
||||
|
@ -9,7 +9,8 @@ import org.chromium.net.UrlRequest
|
||||
import java.io.IOException
|
||||
|
||||
@Keep
|
||||
class OldCallback(originalRequest: Request, mCall: Call) : AbsCallBack(originalRequest, mCall) {
|
||||
class OldCallback(originalRequest: Request, mCall: Call, readTimeoutMillis: Int) :
|
||||
AbsCallBack(originalRequest, mCall, readTimeoutMillis) {
|
||||
|
||||
private val mResponseCondition = ConditionVariable()
|
||||
private var mException: IOException? = null
|
||||
|
@ -30,6 +30,7 @@ import java.net.URLEncoder
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneOffset
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@Suppress("unused", "MemberVisibilityCanBePrivate")
|
||||
open class WebDav(
|
||||
@ -97,6 +98,7 @@ open class WebDav(
|
||||
chain.proceed(request)
|
||||
}
|
||||
okHttpClient.newBuilder().run {
|
||||
callTimeout(0, TimeUnit.SECONDS)
|
||||
interceptors().add(0, authInterceptor)
|
||||
addNetworkInterceptor(authInterceptor)
|
||||
build()
|
||||
|
@ -27,12 +27,15 @@ import io.legado.app.utils.*
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.Response
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.InputStream
|
||||
import java.net.URLEncoder
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.math.max
|
||||
|
||||
/**
|
||||
* Created by GKF on 2018/1/24.
|
||||
@ -51,6 +54,7 @@ class AnalyzeUrl(
|
||||
private val source: BaseSource? = null,
|
||||
private val ruleData: RuleDataInterface? = null,
|
||||
private val chapter: BookChapter? = null,
|
||||
private val readTimeout: Long? = null,
|
||||
headerMapF: Map<String, String>? = null,
|
||||
) : JsExtensions {
|
||||
companion object {
|
||||
@ -404,7 +408,7 @@ class AnalyzeUrl(
|
||||
if (this.useWebView && useWebView) {
|
||||
strResponse = when (method) {
|
||||
RequestMethod.POST -> {
|
||||
val res = getProxyClient(proxy).newCallStrResponse(retry) {
|
||||
val res = getClient().newCallStrResponse(retry) {
|
||||
addHeaders(headerMap)
|
||||
url(urlNoQuery)
|
||||
if (fieldMap.isNotEmpty() || body.isNullOrBlank()) {
|
||||
@ -432,7 +436,7 @@ class AnalyzeUrl(
|
||||
).getStrResponse()
|
||||
}
|
||||
} else {
|
||||
strResponse = getProxyClient(proxy).newCallStrResponse(retry) {
|
||||
strResponse = getClient().newCallStrResponse(retry) {
|
||||
addHeaders(headerMap)
|
||||
when (method) {
|
||||
RequestMethod.POST -> {
|
||||
@ -484,7 +488,7 @@ class AnalyzeUrl(
|
||||
val concurrentRecord = getConcurrentRecord()
|
||||
try {
|
||||
setCookie()
|
||||
val response = getProxyClient(proxy).newCallResponse(retry) {
|
||||
val response = getClient().newCallResponse(retry) {
|
||||
addHeaders(headerMap)
|
||||
when (method) {
|
||||
RequestMethod.POST -> {
|
||||
@ -511,15 +515,24 @@ class AnalyzeUrl(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getClient(): OkHttpClient {
|
||||
val client = getProxyClient(proxy)
|
||||
if (readTimeout == null) {
|
||||
return client
|
||||
}
|
||||
return client.newBuilder()
|
||||
.readTimeout(readTimeout, TimeUnit.MILLISECONDS)
|
||||
.callTimeout(max(60 * 1000L, readTimeout * 2), TimeUnit.MILLISECONDS)
|
||||
.build()
|
||||
}
|
||||
|
||||
fun getResponse(): Response {
|
||||
return runBlocking {
|
||||
getResponseAwait()
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UnnecessaryVariable")
|
||||
private fun getByteArrayIfDataUri(): ByteArray? {
|
||||
@Suppress("RegExpRedundantEscape")
|
||||
val dataUriFindResult = dataUriRegex.find(urlNoQuery)
|
||||
if (dataUriFindResult != null) {
|
||||
val dataUriBase64 = dataUriFindResult.groupValues[1]
|
||||
|
@ -167,7 +167,8 @@ class HttpReadAloudService : BaseReadAloudService(),
|
||||
speakText = speakText,
|
||||
speakSpeed = speechRate,
|
||||
source = httpTts,
|
||||
headerMapF = httpTts.getHeaderMap(true)
|
||||
headerMapF = httpTts.getHeaderMap(true),
|
||||
readTimeout = 300 * 1000L
|
||||
)
|
||||
var response = analyzeUrl.getResponseAwait()
|
||||
coroutineContext.ensureActive()
|
||||
|
@ -217,6 +217,14 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
||||
searchView.setQuery(getString(R.string.no_group), true)
|
||||
}
|
||||
|
||||
R.id.menu_enabled_explore_group -> {
|
||||
searchView.setQuery(getString(R.string.enabled_explore), true)
|
||||
}
|
||||
|
||||
R.id.menu_disabled_explore_group -> {
|
||||
searchView.setQuery(getString(R.string.disabled_explore), true)
|
||||
}
|
||||
|
||||
R.id.menu_help -> showHelp()
|
||||
}
|
||||
if (item.groupId == R.id.source_group) {
|
||||
@ -272,6 +280,14 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
||||
appDb.bookSourceDao.flowNoGroup()
|
||||
}
|
||||
|
||||
searchKey == getString(R.string.enabled_explore) -> {
|
||||
appDb.bookSourceDao.flowEnabledExplore()
|
||||
}
|
||||
|
||||
searchKey == getString(R.string.disabled_explore) -> {
|
||||
appDb.bookSourceDao.flowDisabledExplore()
|
||||
}
|
||||
|
||||
searchKey.startsWith("group:") -> {
|
||||
val key = searchKey.substringAfter("group:")
|
||||
appDb.bookSourceDao.flowGroupSearch(key)
|
||||
|
@ -191,6 +191,14 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application)
|
||||
appDb.bookSourceDao.allNoGroup
|
||||
}
|
||||
|
||||
searchKey == appCtx.getString(R.string.enabled_explore) -> {
|
||||
appDb.bookSourceDao.allEnabledExplore
|
||||
}
|
||||
|
||||
searchKey == appCtx.getString(R.string.disabled_explore) -> {
|
||||
appDb.bookSourceDao.allDisabledExplore
|
||||
}
|
||||
|
||||
searchKey.startsWith("group:") -> {
|
||||
val key = searchKey.substringAfter("group:")
|
||||
appDb.bookSourceDao.groupSearch(key)
|
||||
|
@ -92,6 +92,14 @@
|
||||
android:id="@+id/menu_group_null"
|
||||
android:title="@string/no_group" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_enabled_explore_group"
|
||||
android:title="@string/enabled_explore" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_disabled_explore_group"
|
||||
android:title="@string/disabled_explore" />
|
||||
|
||||
<group android:id="@+id/source_group">
|
||||
|
||||
</group>
|
||||
|
@ -729,6 +729,8 @@
|
||||
<string name="import_old_summary">Seleccione una carpeta de respaldo heredada</string>
|
||||
<string name="enabled">Activado</string>
|
||||
<string name="disabled">Desactivado</string>
|
||||
<string name="enabled_explore">Discovery Enabled</string>
|
||||
<string name="disabled_explore">Discovery Disabled</string>
|
||||
<string name="starting_download">Iniciando descarga</string>
|
||||
<string name="already_in_download">Este libro ya está en la lista de descargas</string>
|
||||
<string name="click_to_open">Haga clic para abrir</string>
|
||||
|
@ -732,6 +732,8 @@
|
||||
<string name="import_old_summary">Select a legacy backup folder</string>
|
||||
<string name="enabled">Enabled</string>
|
||||
<string name="disabled">Disabled</string>
|
||||
<string name="enabled_explore">Discovery Enabled</string>
|
||||
<string name="disabled_explore">Discovery Disabled</string>
|
||||
<string name="starting_download">Starting download</string>
|
||||
<string name="already_in_download">This book is already in Download list</string>
|
||||
<string name="click_to_open">Click to open</string>
|
||||
|
@ -730,6 +730,8 @@
|
||||
<string name="import_old_summary">Selecione uma pasta Legado de Backup</string>
|
||||
<string name="enabled">Ativado</string>
|
||||
<string name="disabled">Desativado</string>
|
||||
<string name="enabled_explore">Discovery Enabled</string>
|
||||
<string name="disabled_explore">Discovery Disabled</string>
|
||||
<string name="starting_download">Iniciando o download</string>
|
||||
<string name="already_in_download">Este livro já está na lista de download</string>
|
||||
<string name="click_to_open">Clique para abrir</string>
|
||||
|
@ -730,6 +730,8 @@ Còn </string>
|
||||
<string name="import_old_summary">Chọn thư mục sao lưu kế thừa</string>
|
||||
<string name="enabled">Đã bật</string>
|
||||
<string name="disabled">Đã tắt</string>
|
||||
<string name="enabled_explore">Discovery Enabled</string>
|
||||
<string name="disabled_explore">Discovery Disabled</string>
|
||||
<string name="starting_download">Bắt đầu tải xuống</string>
|
||||
<string name="already_in_download">Cuốn sách này đã có trong danh sách Download</string>
|
||||
<string name="click_to_open">Nhấp để mở</string>
|
||||
|
@ -723,6 +723,8 @@
|
||||
<string name="import_old_summary">選擇舊版備份文件夾</string>
|
||||
<string name="enabled">已啓用</string>
|
||||
<string name="disabled">已禁用</string>
|
||||
<string name="enabled_explore">已啟用發現</string>
|
||||
<string name="disabled_explore">已禁用發現</string>
|
||||
<string name="text_bottom_justify">文字底部對齊</string>
|
||||
<string name="starting_download">正在啟動下載</string>
|
||||
<string name="already_in_download">該書已在下載列表</string>
|
||||
|
@ -731,6 +731,8 @@
|
||||
<string name="import_old_summary">選擇舊版備份資料夾</string>
|
||||
<string name="enabled">已啟用</string>
|
||||
<string name="disabled">已禁用</string>
|
||||
<string name="enabled_explore">已啟用發現</string>
|
||||
<string name="disabled_explore">已禁用發現</string>
|
||||
<string name="starting_download">正在啟動下載</string>
|
||||
<string name="already_in_download">該書已在下載列表</string>
|
||||
<string name="click_to_open">點擊打開</string>
|
||||
|
@ -732,6 +732,8 @@
|
||||
<string name="import_old_summary">选择旧版备份文件夹</string>
|
||||
<string name="enabled">已启用</string>
|
||||
<string name="disabled">已禁用</string>
|
||||
<string name="enabled_explore">已启用发现</string>
|
||||
<string name="disabled_explore">已禁用发现</string>
|
||||
<string name="starting_download">正在启动下载</string>
|
||||
<string name="already_in_download">该书已在下载列表</string>
|
||||
<string name="click_to_open">点击打开</string>
|
||||
|
@ -734,6 +734,8 @@
|
||||
<string name="import_old_summary">Select a legacy backup folder</string>
|
||||
<string name="enabled">Enabled</string>
|
||||
<string name="disabled">Disabled</string>
|
||||
<string name="enabled_explore">Discovery Enabled</string>
|
||||
<string name="disabled_explore">Discovery Disabled</string>
|
||||
<string name="starting_download">Starting download</string>
|
||||
<string name="already_in_download">This book is already in Download list</string>
|
||||
<string name="click_to_open">Click to open</string>
|
||||
|
Loading…
Reference in New Issue
Block a user