diff --git a/app/src/main/java/io/legado/app/constant/PreferKey.kt b/app/src/main/java/io/legado/app/constant/PreferKey.kt index 640aa1bc5..62ff58866 100644 --- a/app/src/main/java/io/legado/app/constant/PreferKey.kt +++ b/app/src/main/java/io/legado/app/constant/PreferKey.kt @@ -91,6 +91,8 @@ object PreferKey { const val doublePageHorizontal = "doublePageHorizontal" const val readUrlOpenInBrowser = "readUrlInBrowser" const val defaultBookTreeUri = "defaultBookTreeUri" + const val checkSource = "checkSource" + const val uploadRule = "uploadRule" const val cPrimary = "colorPrimary" const val cAccent = "colorAccent" diff --git a/app/src/main/java/io/legado/app/model/CheckSource.kt b/app/src/main/java/io/legado/app/model/CheckSource.kt index a938c48d2..887235701 100644 --- a/app/src/main/java/io/legado/app/model/CheckSource.kt +++ b/app/src/main/java/io/legado/app/model/CheckSource.kt @@ -7,9 +7,17 @@ import io.legado.app.data.entities.BookSource import io.legado.app.service.CheckSourceService import io.legado.app.utils.startService import io.legado.app.utils.toastOnUi +import io.legado.app.help.CacheManager object CheckSource { 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) { if (sources.isEmpty()) { @@ -31,4 +39,13 @@ object CheckSource { 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) + } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/service/CheckSourceService.kt b/app/src/main/java/io/legado/app/service/CheckSourceService.kt index 7ae8268d5..45c40a395 100644 --- a/app/src/main/java/io/legado/app/service/CheckSourceService.kt +++ b/app/src/main/java/io/legado/app/service/CheckSourceService.kt @@ -9,6 +9,7 @@ import io.legado.app.constant.EventBus import io.legado.app.constant.IntentAction import io.legado.app.data.appDb 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.coroutine.CompositeCoroutine import io.legado.app.model.CheckSource @@ -33,6 +34,8 @@ class CheckSourceService : BaseService() { private val checkedIds = ArrayList() private var processIndex = 0 private var notificationMsg = "" + private var books = ArrayList() + private val notificationBuilder by lazy { NotificationCompat.Builder(this, AppConst.channelIdReadAloud) .setSmallIcon(R.drawable.ic_network_check) @@ -118,45 +121,58 @@ class CheckSourceService : BaseService() { searchWord = it } } - var books = WebBook.searchBookAwait(this, source, searchWord) - if (books.isEmpty()) { - source.addGroup("搜索失效") - val exs = source.exploreKinds - var url: String? = null - for (ex in exs) { - url = ex.url - if (!url.isNullOrBlank()) { - break + //校验搜索 + if (CheckSource.checkSearch) { + books = WebBook.searchBookAwait(this, source, searchWord) + if (books.isEmpty()) source.addGroup("搜索失效") else source.removeGroup("搜索失效") + } + //校验发现 + if (CheckSource.checkDiscovery) { + if (books.isEmpty()) { + val exs = source.exploreKinds + var url: String? = null + for (ex in exs) { + url = ex.url + if (!url.isNullOrBlank()) { + break + } + } + if (url.isNullOrBlank()) { + throw NoStackTraceException("搜索内容为空并且没有发现") + } + books = WebBook.exploreBookAwait(this, source, url) + if (books.isEmpty()) { + throw NoStackTraceException("发现书籍为空") } } - if (url.isNullOrBlank()) { - throw NoStackTraceException("搜索内容为空并且没有发现") + } + //校验详情 + if (CheckSource.checkInfo) { + var book = books.first().toBook() + if (book.tocUrl.isBlank()) { + book = WebBook.getBookInfoAwait(this, source, book) } - books = WebBook.exploreBookAwait(this, source, url) - if (books.isEmpty()) { - throw NoStackTraceException("发现书籍为空") + //校验目录 + if (CheckSource.checkCategory) { + val toc = WebBook.getChapterListAwait(this, source, book) + val nextChapterUrl = toc.getOrNull(1)?.url ?: toc.first().url + //校验正文 + if (CheckSource.checkContent) { + val content = WebBook.getContentAwait( + this, + bookSource = source, + book = book, + bookChapter = toc.first(), + nextChapterUrl = nextChapterUrl, + needSave = false + ) + if ( !toc.first().isVolume && content.isBlank()) { + throw NoStackTraceException("正文内容为空") + } + } } - } else { - source.removeGroup("搜索失效") - } - var book = books.first().toBook() - if (book.tocUrl.isBlank()) { - book = WebBook.getBookInfoAwait(this, source, book) - } - val toc = WebBook.getChapterListAwait(this, source, book) - val nextChapterUrl = toc.getOrNull(1)?.url ?: toc.first().url - val content = WebBook.getContentAwait( - this, - bookSource = source, - book = book, - bookChapter = toc.first(), - nextChapterUrl = nextChapterUrl, - needSave = false - ) - if ( !toc.first().isVolume && content.isBlank()) { - throw NoStackTraceException("正文内容为空") } - }.timeout(180000L) + }.timeout(CheckSource.timeout) .onError(searchCoroutine) { source.addGroup("失效") if (source.bookSourceComment?.contains("Error: ") == false) { diff --git a/app/src/main/java/io/legado/app/ui/config/CheckSourceConfig.kt b/app/src/main/java/io/legado/app/ui/config/CheckSourceConfig.kt new file mode 100644 index 000000000..0be6dee25 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/config/CheckSourceConfig.kt @@ -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() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/config/DirectLinkUploadConfig.kt b/app/src/main/java/io/legado/app/ui/config/DirectLinkUploadConfig.kt index b9e4ade7e..0e7359bd0 100644 --- a/app/src/main/java/io/legado/app/ui/config/DirectLinkUploadConfig.kt +++ b/app/src/main/java/io/legado/app/ui/config/DirectLinkUploadConfig.kt @@ -41,11 +41,11 @@ class DirectLinkUploadConfig : BaseDialogFragment(R.layout.dialog_direct_link_up val uploadUrl = binding.editUploadUrl.text?.toString() val downloadUrlRule = binding.editDownloadUrlRule.text?.toString() val summary = binding.editSummary.text?.toString() - uploadUrl ?: let { + if (uploadUrl.isNullOrBlank()) { toastOnUi("上传Url不能为空") return@onClick } - downloadUrlRule ?: let { + if (downloadUrlRule.isNullOrBlank()) { toastOnUi("下载Url规则不能为空") return@onClick } diff --git a/app/src/main/java/io/legado/app/ui/config/OtherConfigFragment.kt b/app/src/main/java/io/legado/app/ui/config/OtherConfigFragment.kt index 20089afd9..31ea56012 100644 --- a/app/src/main/java/io/legado/app/ui/config/OtherConfigFragment.kt +++ b/app/src/main/java/io/legado/app/ui/config/OtherConfigFragment.kt @@ -70,7 +70,7 @@ class OtherConfigFragment : BasePreferenceFragment(), when (preference?.key) { PreferKey.userAgent -> showUserAgentDialog() PreferKey.defaultBookTreeUri -> localBookTreeSelect.launch { - title = "选择保存书籍的文件夹" + title = getString(R.string.select_book_folder) mode = HandleFileContract.DIR_SYS } PreferKey.preDownloadNum -> NumberPickerDialog(requireContext()) @@ -98,7 +98,8 @@ class OtherConfigFragment : BasePreferenceFragment(), AppConfig.webPort = it } PreferKey.cleanCache -> clearCache() - "uploadRule" -> DirectLinkUploadConfig().show(childFragmentManager, "uploadRuleConfig") + PreferKey.uploadRule -> showDialogFragment() + PreferKey.checkSource -> showDialogFragment() } return super.onPreferenceTreeClick(preference) } @@ -155,9 +156,9 @@ class OtherConfigFragment : BasePreferenceFragment(), @SuppressLint("InflateParams") private fun showUserAgentDialog() { - alert("UserAgent") { + alert(getString(R.string.user_agent)) { val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { - editView.hint = "UserAgent" + editView.hint = getString(R.string.user_agent) editView.setText(AppConfig.userAgent) } customView { alertBinding.root } diff --git a/app/src/main/res/layout/dialog_check_source_config.xml b/app/src/main/res/layout/dialog_check_source_config.xml new file mode 100644 index 000000000..663c75650 --- /dev/null +++ b/app/src/main/res/layout/dialog_check_source_config.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/dialog_direct_link_upload_config.xml b/app/src/main/res/layout/dialog_direct_link_upload_config.xml index 2fcebd28e..69605ec28 100644 --- a/app/src/main/res/layout/dialog_direct_link_upload_config.xml +++ b/app/src/main/res/layout/dialog_direct_link_upload_config.xml @@ -11,7 +11,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="?attr/actionBarStyle" - app:title="直链上传配置" + app:title="@string/direct_link_upload_config" app:popupTheme="@style/AppTheme.PopupOverlay" app:titleTextAppearance="@style/ToolbarTitle" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d88a10077..c71cc8598 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -877,6 +877,7 @@ path 直链上传规则 用于导出书源书单时生成直链url + 直链上传配置 拷贝播放Url 设置源变量 设置书籍变量 @@ -916,5 +917,20 @@ 展开文本选择菜单 书籍保存位置 从其它应用打开的书籍保存位置 + 选择保存书籍的文件夹 + 用户代理 + + 校验设置 + 单个书源校验超时(秒) + 超时 + + 小于 + 校验搜索 + 校验发现 + 校验详情 + 校验目录 + 校验正文 + 搜索发现至少校验一个 + diff --git a/app/src/main/res/xml/pref_config_other.xml b/app/src/main/res/xml/pref_config_other.xml index 27a3cb17e..65571633f 100644 --- a/app/src/main/res/xml/pref_config_other.xml +++ b/app/src/main/res/xml/pref_config_other.xml @@ -54,13 +54,17 @@ + android:title="@string/user_agent" /> + +