mirror of
https://github.com/gedoor/legado.git
synced 2024-08-30 09:23:26 +08:00
commit
ee2b6b7920
@ -91,6 +91,8 @@ object PreferKey {
|
|||||||
const val doublePageHorizontal = "doublePageHorizontal"
|
const val doublePageHorizontal = "doublePageHorizontal"
|
||||||
const val readUrlOpenInBrowser = "readUrlInBrowser"
|
const val readUrlOpenInBrowser = "readUrlInBrowser"
|
||||||
const val defaultBookTreeUri = "defaultBookTreeUri"
|
const val defaultBookTreeUri = "defaultBookTreeUri"
|
||||||
|
const val checkSource = "checkSource"
|
||||||
|
const val uploadRule = "uploadRule"
|
||||||
|
|
||||||
const val cPrimary = "colorPrimary"
|
const val cPrimary = "colorPrimary"
|
||||||
const val cAccent = "colorAccent"
|
const val cAccent = "colorAccent"
|
||||||
|
@ -7,9 +7,17 @@ import io.legado.app.data.entities.BookSource
|
|||||||
import io.legado.app.service.CheckSourceService
|
import io.legado.app.service.CheckSourceService
|
||||||
import io.legado.app.utils.startService
|
import io.legado.app.utils.startService
|
||||||
import io.legado.app.utils.toastOnUi
|
import io.legado.app.utils.toastOnUi
|
||||||
|
import io.legado.app.help.CacheManager
|
||||||
|
|
||||||
object CheckSource {
|
object CheckSource {
|
||||||
var keyword = "我的"
|
var keyword = "我的"
|
||||||
|
//校验设置
|
||||||
|
var timeout = CacheManager.getLong("checkSourceTimeout") ?: 180000L
|
||||||
|
var checkSearch = CacheManager.get("checkSearch")?.toBoolean() ?: true
|
||||||
|
var checkDiscovery = CacheManager.get("checkDiscovery")?.toBoolean() ?: true
|
||||||
|
var checkInfo = CacheManager.get("checkInfo")?.toBoolean() ?: true
|
||||||
|
var checkCategory = CacheManager.get("checkCategory")?.toBoolean() ?: true
|
||||||
|
var checkContent = CacheManager.get("checkContent")?.toBoolean() ?: true
|
||||||
|
|
||||||
fun start(context: Context, sources: List<BookSource>) {
|
fun start(context: Context, sources: List<BookSource>) {
|
||||||
if (sources.isEmpty()) {
|
if (sources.isEmpty()) {
|
||||||
@ -31,4 +39,13 @@ object CheckSource {
|
|||||||
action = IntentAction.stop
|
action = IntentAction.stop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun putConfig() {
|
||||||
|
CacheManager.put("checkSourceTimeout", timeout * 1000)
|
||||||
|
CacheManager.put("checkSearch", checkSearch)
|
||||||
|
CacheManager.put("checkDiscovery", checkDiscovery)
|
||||||
|
CacheManager.put("checkInfo", checkInfo)
|
||||||
|
CacheManager.put("checkCategory", checkCategory)
|
||||||
|
CacheManager.put("checkContent", checkContent)
|
||||||
|
}
|
||||||
}
|
}
|
@ -9,6 +9,7 @@ import io.legado.app.constant.EventBus
|
|||||||
import io.legado.app.constant.IntentAction
|
import io.legado.app.constant.IntentAction
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
import io.legado.app.data.entities.BookSource
|
import io.legado.app.data.entities.BookSource
|
||||||
|
import io.legado.app.data.entities.SearchBook
|
||||||
import io.legado.app.help.AppConfig
|
import io.legado.app.help.AppConfig
|
||||||
import io.legado.app.help.coroutine.CompositeCoroutine
|
import io.legado.app.help.coroutine.CompositeCoroutine
|
||||||
import io.legado.app.model.CheckSource
|
import io.legado.app.model.CheckSource
|
||||||
@ -33,6 +34,8 @@ class CheckSourceService : BaseService() {
|
|||||||
private val checkedIds = ArrayList<String>()
|
private val checkedIds = ArrayList<String>()
|
||||||
private var processIndex = 0
|
private var processIndex = 0
|
||||||
private var notificationMsg = ""
|
private var notificationMsg = ""
|
||||||
|
private var books = ArrayList<SearchBook>()
|
||||||
|
|
||||||
private val notificationBuilder by lazy {
|
private val notificationBuilder by lazy {
|
||||||
NotificationCompat.Builder(this, AppConst.channelIdReadAloud)
|
NotificationCompat.Builder(this, AppConst.channelIdReadAloud)
|
||||||
.setSmallIcon(R.drawable.ic_network_check)
|
.setSmallIcon(R.drawable.ic_network_check)
|
||||||
@ -118,9 +121,14 @@ class CheckSourceService : BaseService() {
|
|||||||
searchWord = it
|
searchWord = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var books = WebBook.searchBookAwait(this, source, searchWord)
|
//校验搜索
|
||||||
|
if (CheckSource.checkSearch) {
|
||||||
|
books = WebBook.searchBookAwait(this, source, searchWord)
|
||||||
|
if (books.isEmpty()) source.addGroup("搜索失效") else source.removeGroup("搜索失效")
|
||||||
|
}
|
||||||
|
//校验发现
|
||||||
|
if (CheckSource.checkDiscovery) {
|
||||||
if (books.isEmpty()) {
|
if (books.isEmpty()) {
|
||||||
source.addGroup("搜索失效")
|
|
||||||
val exs = source.exploreKinds
|
val exs = source.exploreKinds
|
||||||
var url: String? = null
|
var url: String? = null
|
||||||
for (ex in exs) {
|
for (ex in exs) {
|
||||||
@ -136,15 +144,20 @@ class CheckSourceService : BaseService() {
|
|||||||
if (books.isEmpty()) {
|
if (books.isEmpty()) {
|
||||||
throw NoStackTraceException("发现书籍为空")
|
throw NoStackTraceException("发现书籍为空")
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
source.removeGroup("搜索失效")
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
//校验详情
|
||||||
|
if (CheckSource.checkInfo) {
|
||||||
var book = books.first().toBook()
|
var book = books.first().toBook()
|
||||||
if (book.tocUrl.isBlank()) {
|
if (book.tocUrl.isBlank()) {
|
||||||
book = WebBook.getBookInfoAwait(this, source, book)
|
book = WebBook.getBookInfoAwait(this, source, book)
|
||||||
}
|
}
|
||||||
|
//校验目录
|
||||||
|
if (CheckSource.checkCategory) {
|
||||||
val toc = WebBook.getChapterListAwait(this, source, book)
|
val toc = WebBook.getChapterListAwait(this, source, book)
|
||||||
val nextChapterUrl = toc.getOrNull(1)?.url ?: toc.first().url
|
val nextChapterUrl = toc.getOrNull(1)?.url ?: toc.first().url
|
||||||
|
//校验正文
|
||||||
|
if (CheckSource.checkContent) {
|
||||||
val content = WebBook.getContentAwait(
|
val content = WebBook.getContentAwait(
|
||||||
this,
|
this,
|
||||||
bookSource = source,
|
bookSource = source,
|
||||||
@ -156,7 +169,10 @@ class CheckSourceService : BaseService() {
|
|||||||
if ( !toc.first().isVolume && content.isBlank()) {
|
if ( !toc.first().isVolume && content.isBlank()) {
|
||||||
throw NoStackTraceException("正文内容为空")
|
throw NoStackTraceException("正文内容为空")
|
||||||
}
|
}
|
||||||
}.timeout(180000L)
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.timeout(CheckSource.timeout)
|
||||||
.onError(searchCoroutine) {
|
.onError(searchCoroutine) {
|
||||||
source.addGroup("失效")
|
source.addGroup("失效")
|
||||||
if (source.bookSourceComment?.contains("Error: ") == false) {
|
if (source.bookSourceComment?.contains("Error: ") == false) {
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
package io.legado.app.ui.config
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import io.legado.app.R
|
||||||
|
import io.legado.app.base.BaseDialogFragment
|
||||||
|
import io.legado.app.databinding.DialogCheckSourceConfigBinding
|
||||||
|
import io.legado.app.model.CheckSource
|
||||||
|
import io.legado.app.lib.theme.primaryColor
|
||||||
|
import io.legado.app.utils.setLayout
|
||||||
|
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||||
|
import io.legado.app.utils.toastOnUi
|
||||||
|
import splitties.views.onClick
|
||||||
|
|
||||||
|
class CheckSourceConfig : BaseDialogFragment(R.layout.dialog_check_source_config) {
|
||||||
|
|
||||||
|
private val binding by viewBinding(DialogCheckSourceConfigBinding::bind)
|
||||||
|
//允许的最小超时时间,秒
|
||||||
|
private val minTimeout = 60L
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
setLayout(
|
||||||
|
0.9f,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
binding.toolBar.setBackgroundColor(primaryColor)
|
||||||
|
CheckSource.run {
|
||||||
|
binding.checkSourceTimeout.setText((timeout / 1000).toString())
|
||||||
|
binding.checkSearch?.isChecked = checkSearch
|
||||||
|
binding.checkDiscovery?.isChecked = checkDiscovery
|
||||||
|
binding.checkInfo?.isChecked = checkInfo
|
||||||
|
binding.checkCategory?.isChecked = checkCategory
|
||||||
|
binding.checkContent?.isChecked = checkContent
|
||||||
|
binding.tvCancel.onClick {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
binding.tvOk.onClick {
|
||||||
|
val text = binding.checkSourceTimeout.text.toString()
|
||||||
|
when {
|
||||||
|
text.isBlank() -> {
|
||||||
|
toastOnUi("${getString(R.string.timeout)}${getString(R.string.cannot_empty)}")
|
||||||
|
return@onClick
|
||||||
|
}
|
||||||
|
text.toLong() < minTimeout -> {
|
||||||
|
toastOnUi("${getString(R.string.timeout)}${getString(R.string.less_than)}${minTimeout}${getString(R.string.seconds)}")
|
||||||
|
return@onClick
|
||||||
|
}
|
||||||
|
else -> timeout = text.toLong() * 1000
|
||||||
|
}
|
||||||
|
val _checkSearch = binding.checkSearch?.isChecked
|
||||||
|
val _checkDiscovery = binding.checkDiscovery?.isChecked
|
||||||
|
if (!_checkSearch && !_checkDiscovery) {
|
||||||
|
toastOnUi(getString(R.string.error_check_source_config))
|
||||||
|
return@onClick
|
||||||
|
}
|
||||||
|
checkSearch = _checkSearch
|
||||||
|
checkDiscovery = _checkDiscovery
|
||||||
|
checkInfo = binding.checkInfo?.isChecked
|
||||||
|
checkCategory = binding.checkCategory?.isChecked
|
||||||
|
checkContent = binding.checkContent?.isChecked
|
||||||
|
putConfig()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -41,11 +41,11 @@ class DirectLinkUploadConfig : BaseDialogFragment(R.layout.dialog_direct_link_up
|
|||||||
val uploadUrl = binding.editUploadUrl.text?.toString()
|
val uploadUrl = binding.editUploadUrl.text?.toString()
|
||||||
val downloadUrlRule = binding.editDownloadUrlRule.text?.toString()
|
val downloadUrlRule = binding.editDownloadUrlRule.text?.toString()
|
||||||
val summary = binding.editSummary.text?.toString()
|
val summary = binding.editSummary.text?.toString()
|
||||||
uploadUrl ?: let {
|
if (uploadUrl.isNullOrBlank()) {
|
||||||
toastOnUi("上传Url不能为空")
|
toastOnUi("上传Url不能为空")
|
||||||
return@onClick
|
return@onClick
|
||||||
}
|
}
|
||||||
downloadUrlRule ?: let {
|
if (downloadUrlRule.isNullOrBlank()) {
|
||||||
toastOnUi("下载Url规则不能为空")
|
toastOnUi("下载Url规则不能为空")
|
||||||
return@onClick
|
return@onClick
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ class OtherConfigFragment : BasePreferenceFragment(),
|
|||||||
when (preference?.key) {
|
when (preference?.key) {
|
||||||
PreferKey.userAgent -> showUserAgentDialog()
|
PreferKey.userAgent -> showUserAgentDialog()
|
||||||
PreferKey.defaultBookTreeUri -> localBookTreeSelect.launch {
|
PreferKey.defaultBookTreeUri -> localBookTreeSelect.launch {
|
||||||
title = "选择保存书籍的文件夹"
|
title = getString(R.string.select_book_folder)
|
||||||
mode = HandleFileContract.DIR_SYS
|
mode = HandleFileContract.DIR_SYS
|
||||||
}
|
}
|
||||||
PreferKey.preDownloadNum -> NumberPickerDialog(requireContext())
|
PreferKey.preDownloadNum -> NumberPickerDialog(requireContext())
|
||||||
@ -98,7 +98,8 @@ class OtherConfigFragment : BasePreferenceFragment(),
|
|||||||
AppConfig.webPort = it
|
AppConfig.webPort = it
|
||||||
}
|
}
|
||||||
PreferKey.cleanCache -> clearCache()
|
PreferKey.cleanCache -> clearCache()
|
||||||
"uploadRule" -> DirectLinkUploadConfig().show(childFragmentManager, "uploadRuleConfig")
|
PreferKey.uploadRule -> showDialogFragment<DirectLinkUploadConfig>()
|
||||||
|
PreferKey.checkSource -> showDialogFragment<CheckSourceConfig>()
|
||||||
}
|
}
|
||||||
return super.onPreferenceTreeClick(preference)
|
return super.onPreferenceTreeClick(preference)
|
||||||
}
|
}
|
||||||
@ -155,9 +156,9 @@ class OtherConfigFragment : BasePreferenceFragment(),
|
|||||||
|
|
||||||
@SuppressLint("InflateParams")
|
@SuppressLint("InflateParams")
|
||||||
private fun showUserAgentDialog() {
|
private fun showUserAgentDialog() {
|
||||||
alert("UserAgent") {
|
alert(getString(R.string.user_agent)) {
|
||||||
val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply {
|
val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply {
|
||||||
editView.hint = "UserAgent"
|
editView.hint = getString(R.string.user_agent)
|
||||||
editView.setText(AppConfig.userAgent)
|
editView.setText(AppConfig.userAgent)
|
||||||
}
|
}
|
||||||
customView { alertBinding.root }
|
customView { alertBinding.root }
|
||||||
|
94
app/src/main/res/layout/dialog_check_source_config.xml
Normal file
94
app/src/main/res/layout/dialog_check_source_config.xml
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/tool_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:theme="?attr/actionBarStyle"
|
||||||
|
app:title="@string/check_source_config"
|
||||||
|
app:popupTheme="@style/AppTheme.PopupOverlay"
|
||||||
|
app:titleTextAppearance="@style/ToolbarTitle" />
|
||||||
|
|
||||||
|
<io.legado.app.ui.widget.text.TextInputLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="3dp">
|
||||||
|
|
||||||
|
<io.legado.app.lib.theme.view.ThemeEditText
|
||||||
|
android:id="@+id/check_source_timeout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/check_source_timeout"
|
||||||
|
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
|
||||||
|
|
||||||
|
</io.legado.app.ui.widget.text.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="12dp"
|
||||||
|
android:paddingRight="12dp"
|
||||||
|
app:flexWrap="wrap"
|
||||||
|
app:justifyContent="space_between">
|
||||||
|
|
||||||
|
<io.legado.app.lib.theme.view.ThemeCheckBox
|
||||||
|
android:id="@+id/check_search"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/check_search" />
|
||||||
|
<io.legado.app.lib.theme.view.ThemeCheckBox
|
||||||
|
android:id="@+id/check_discovery"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/check_discovery" />
|
||||||
|
<io.legado.app.lib.theme.view.ThemeCheckBox
|
||||||
|
android:id="@+id/check_info"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_wrapBefore="true"
|
||||||
|
android:text="@string/check_info" />
|
||||||
|
<io.legado.app.lib.theme.view.ThemeCheckBox
|
||||||
|
android:id="@+id/check_category"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/check_category" />
|
||||||
|
<io.legado.app.lib.theme.view.ThemeCheckBox
|
||||||
|
android:id="@+id/check_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/check_content" />
|
||||||
|
|
||||||
|
</com.google.android.flexbox.FlexboxLayout>
|
||||||
|
|
||||||
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="12dp"
|
||||||
|
android:paddingRight="12dp"
|
||||||
|
app:flexWrap="wrap"
|
||||||
|
app:justifyContent="flex_end">
|
||||||
|
|
||||||
|
<io.legado.app.ui.widget.text.AccentTextView
|
||||||
|
android:id="@+id/tv_cancel"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:text="@string/cancel"
|
||||||
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
|
<io.legado.app.ui.widget.text.AccentTextView
|
||||||
|
android:id="@+id/tv_ok"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:text="@string/ok"
|
||||||
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
|
</com.google.android.flexbox.FlexboxLayout>
|
||||||
|
</LinearLayout>
|
@ -11,7 +11,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:theme="?attr/actionBarStyle"
|
android:theme="?attr/actionBarStyle"
|
||||||
app:title="直链上传配置"
|
app:title="@string/direct_link_upload_config"
|
||||||
app:popupTheme="@style/AppTheme.PopupOverlay"
|
app:popupTheme="@style/AppTheme.PopupOverlay"
|
||||||
app:titleTextAppearance="@style/ToolbarTitle" />
|
app:titleTextAppearance="@style/ToolbarTitle" />
|
||||||
|
|
||||||
|
@ -877,6 +877,7 @@
|
|||||||
<string name="path">path</string>
|
<string name="path">path</string>
|
||||||
<string name="direct_link_upload_rule">直链上传规则</string>
|
<string name="direct_link_upload_rule">直链上传规则</string>
|
||||||
<string name="direct_link_upload_rule_summary">用于导出书源书单时生成直链url</string>
|
<string name="direct_link_upload_rule_summary">用于导出书源书单时生成直链url</string>
|
||||||
|
<string name="direct_link_upload_config">直链上传配置</string>
|
||||||
<string name="copy_play_url">拷贝播放Url</string>
|
<string name="copy_play_url">拷贝播放Url</string>
|
||||||
<string name="set_source_variable">设置源变量</string>
|
<string name="set_source_variable">设置源变量</string>
|
||||||
<string name="set_book_variable">设置书籍变量</string>
|
<string name="set_book_variable">设置书籍变量</string>
|
||||||
@ -916,6 +917,21 @@
|
|||||||
<string name="expand_text_menu">展开文本选择菜单</string>
|
<string name="expand_text_menu">展开文本选择菜单</string>
|
||||||
<string name="book_tree_uri_t">书籍保存位置</string>
|
<string name="book_tree_uri_t">书籍保存位置</string>
|
||||||
<string name="book_tree_uri_s">从其它应用打开的书籍保存位置</string>
|
<string name="book_tree_uri_s">从其它应用打开的书籍保存位置</string>
|
||||||
|
<string name="select_book_folder">选择保存书籍的文件夹</string>
|
||||||
|
<string name="user_agent">用户代理</string>
|
||||||
<string name="bg_alpha">背景透明度</string>
|
<string name="bg_alpha">背景透明度</string>
|
||||||
|
|
||||||
|
<!-- check source config string -->
|
||||||
|
<string name="check_source_config">校验设置</string>
|
||||||
|
<string name="check_source_timeout">单个书源校验超时(秒)</string>
|
||||||
|
<string name="timeout">超时</string>
|
||||||
|
<string name="seconds">秒</string>
|
||||||
|
<string name="less_than">小于</string>
|
||||||
|
<string name="check_search">校验搜索</string>
|
||||||
|
<string name="check_discovery">校验发现</string>
|
||||||
|
<string name="check_info">校验详情</string>
|
||||||
|
<string name="check_category">校验目录</string>
|
||||||
|
<string name="check_content">校验正文</string>
|
||||||
|
<string name="error_check_source_config">搜索发现至少校验一个</string>
|
||||||
|
<!-- string end -->
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -54,13 +54,17 @@
|
|||||||
|
|
||||||
<io.legado.app.ui.widget.prefs.Preference
|
<io.legado.app.ui.widget.prefs.Preference
|
||||||
android:key="userAgent"
|
android:key="userAgent"
|
||||||
android:title="UserAgent" />
|
android:title="@string/user_agent" />
|
||||||
|
|
||||||
<io.legado.app.ui.widget.prefs.Preference
|
<io.legado.app.ui.widget.prefs.Preference
|
||||||
android:key="defaultBookTreeUri"
|
android:key="defaultBookTreeUri"
|
||||||
android:title="@string/book_tree_uri_t"
|
android:title="@string/book_tree_uri_t"
|
||||||
android:summary="@string/book_tree_uri_s" />
|
android:summary="@string/book_tree_uri_s" />
|
||||||
|
|
||||||
|
<io.legado.app.ui.widget.prefs.Preference
|
||||||
|
android:key="checkSource"
|
||||||
|
android:title="@string/check_source_config" />
|
||||||
|
|
||||||
<io.legado.app.ui.widget.prefs.Preference
|
<io.legado.app.ui.widget.prefs.Preference
|
||||||
android:key="uploadRule"
|
android:key="uploadRule"
|
||||||
android:title="@string/direct_link_upload_rule"
|
android:title="@string/direct_link_upload_rule"
|
||||||
|
Loading…
Reference in New Issue
Block a user