From b5308524db075f35a2d213510a74db3ae3033bcd Mon Sep 17 00:00:00 2001 From: Jason Yao Date: Mon, 16 Aug 2021 01:27:53 -0400 Subject: [PATCH 1/4] try to use flow --- .../java/io/legado/app/constant/EventBus.kt | 1 + .../main/java/io/legado/app/model/Debug.kt | 22 +++++++++-- .../legado/app/service/CheckSourceService.kt | 16 ++++++++ .../book/source/debug/BookSourceDebugModel.kt | 4 ++ .../book/source/manage/BookSourceActivity.kt | 37 ++++++++++++++++--- .../book/source/manage/BookSourceAdapter.kt | 16 ++++++++ .../rss/source/debug/RssSourceDebugModel.kt | 4 ++ .../io/legado/app/web/SourceDebugWebSocket.kt | 4 ++ app/src/main/res/layout/item_book_source.xml | 36 ++++++++++++++++-- 9 files changed, 127 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/io/legado/app/constant/EventBus.kt b/app/src/main/java/io/legado/app/constant/EventBus.kt index 1cb16afd5..5257596fa 100644 --- a/app/src/main/java/io/legado/app/constant/EventBus.kt +++ b/app/src/main/java/io/legado/app/constant/EventBus.kt @@ -22,6 +22,7 @@ object EventBus { const val UP_DOWNLOAD = "upDownload" const val SAVE_CONTENT = "saveContent" const val CHECK_SOURCE = "checkSource" + const val CHECK_SOURCE_MESSAGE = "checkSourceMessage" const val CHECK_SOURCE_DONE = "checkSourceDone" const val TIP_COLOR = "tipColor" const val SOURCE_CHANGED = "sourceChanged" diff --git a/app/src/main/java/io/legado/app/model/Debug.kt b/app/src/main/java/io/legado/app/model/Debug.kt index 834d53efa..a67fc9ca9 100644 --- a/app/src/main/java/io/legado/app/model/Debug.kt +++ b/app/src/main/java/io/legado/app/model/Debug.kt @@ -1,10 +1,9 @@ package io.legado.app.model import android.annotation.SuppressLint -import io.legado.app.data.entities.Book -import io.legado.app.data.entities.BookChapter -import io.legado.app.data.entities.RssArticle -import io.legado.app.data.entities.RssSource +import android.util.Log +import io.legado.app.constant.EventBus +import io.legado.app.data.entities.* import io.legado.app.help.coroutine.CompositeCoroutine import io.legado.app.model.rss.Rss import io.legado.app.model.webBook.WebBook @@ -12,13 +11,17 @@ import io.legado.app.utils.HtmlFormatter import io.legado.app.utils.isAbsUrl import io.legado.app.utils.msg import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.flow import java.text.SimpleDateFormat import java.util.* +import java.util.concurrent.ConcurrentHashMap +import kotlin.collections.ArrayList object Debug { var callback: Callback? = null private var debugSource: String? = null private val tasks: CompositeCoroutine = CompositeCoroutine() + val debugMessageMap = ConcurrentHashMap>() @SuppressLint("ConstantLocale") private val DEBUG_TIME_FORMAT = SimpleDateFormat("[mm:ss.SSS]", Locale.getDefault()) @@ -44,6 +47,10 @@ object Debug { printMsg = "$time $printMsg" } it.printLog(state, printMsg) + Log.d(EventBus.CHECK_SOURCE_MESSAGE, "debugMessage to filter $printMsg") + if (sourceUrl != null && printMsg.length < 30) { + debugMessageMap[sourceUrl]?.add(printMsg) + } } } @@ -61,6 +68,12 @@ object Debug { } } + fun startCheck(source: BookSource) { + debugSource = source.bookSourceUrl + startTime = System.currentTimeMillis() + debugMessageMap[source.bookSourceUrl] = arrayListOf() + } + fun startDebug(scope: CoroutineScope, rssSource: RssSource) { cancelDebug() debugSource = rssSource.sourceUrl @@ -246,6 +259,7 @@ object Debug { interface Callback { fun printLog(state: Int, msg: String) + fun printCheckSourceMessage(sourceUrl: String, msg: String) } } \ 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 0c19e7445..fd03e4822 100644 --- a/app/src/main/java/io/legado/app/service/CheckSourceService.kt +++ b/app/src/main/java/io/legado/app/service/CheckSourceService.kt @@ -1,6 +1,7 @@ package io.legado.app.service import android.content.Intent +import android.util.Log import androidx.core.app.NotificationCompat import io.legado.app.R import io.legado.app.base.BaseService @@ -12,6 +13,7 @@ import io.legado.app.data.entities.BookSource import io.legado.app.help.AppConfig import io.legado.app.help.IntentHelp import io.legado.app.help.coroutine.CompositeCoroutine +import io.legado.app.model.Debug import io.legado.app.model.webBook.WebBook import io.legado.app.service.help.CheckSource import io.legado.app.ui.book.source.manage.BookSourceActivity @@ -29,6 +31,16 @@ class CheckSourceService : BaseService() { private val checkedIds = ArrayList() private var processIndex = 0 private var notificationMsg = "" + private val debugCallback = object : Debug.Callback{ + override fun printLog(state: Int, msg: String) { + } + + @Synchronized + override fun printCheckSourceMessage(sourceUrl: String, msg: String) { + postEvent(EventBus.CHECK_SOURCE_MESSAGE, Pair(sourceUrl, msg)) + Log.d(EventBus.CHECK_SOURCE_MESSAGE, "printCheckSourceMessage to post $msg") + } + } private val notificationBuilder by lazy { NotificationCompat.Builder(this, AppConst.channelIdReadAloud) .setSmallIcon(R.drawable.ic_network_check) @@ -48,6 +60,7 @@ class CheckSourceService : BaseService() { override fun onCreate() { super.onCreate() notificationMsg = getString(R.string.start) + Debug.callback = debugCallback upNotification() } @@ -65,6 +78,7 @@ class CheckSourceService : BaseService() { super.onDestroy() tasks.clear() searchCoroutine.close() + Debug.callback = null postEvent(EventBus.CHECK_SOURCE_DONE, 0) } @@ -98,6 +112,7 @@ class CheckSourceService : BaseService() { if (index < allIds.size) { val sourceUrl = allIds[index] appDb.bookSourceDao.getBookSource(sourceUrl)?.let { source -> + Debug.startCheck(source) check(source) } ?: onNext(sourceUrl, "") } @@ -145,6 +160,7 @@ class CheckSourceService : BaseService() { }?.joinToString("\n") appDb.bookSourceDao.update(source) }.onFinally(searchCoroutine) { + postEvent(EventBus.CHECK_SOURCE_MESSAGE, Pair(source.bookSourceUrl, null)) onNext(source.bookSourceUrl, source.bookSourceName) } } diff --git a/app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugModel.kt b/app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugModel.kt index 991591029..e3a77be67 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugModel.kt @@ -51,6 +51,10 @@ class BookSourceDebugModel(application: Application) : BaseViewModel(application } } + override fun printCheckSourceMessage(sourceUrl: String, msg: String) { + TODO("Not yet implemented") + } + override fun onCleared() { super.onCleared() Debug.cancelDebug(true) diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt index 277335dd4..0d78984c5 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt @@ -9,6 +9,7 @@ import android.view.SubMenu import androidx.activity.viewModels import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.SearchView +import androidx.core.os.bundleOf import androidx.documentfile.provider.DocumentFile import androidx.recyclerview.widget.ItemTouchHelper import com.google.android.material.snackbar.Snackbar @@ -24,6 +25,7 @@ import io.legado.app.help.LocalConfig import io.legado.app.lib.dialogs.alert import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.primaryTextColor +import io.legado.app.model.Debug import io.legado.app.service.help.CheckSource import io.legado.app.ui.association.ImportBookSourceDialog import io.legado.app.ui.book.source.debug.BookSourceDebugActivity @@ -39,7 +41,8 @@ import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding import kotlinx.coroutines.Job -import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import java.io.File @@ -337,6 +340,7 @@ class BookSourceActivity : VMBaseActivity {} observeEvent(EventBus.CHECK_SOURCE) { msg -> snackBar?.setText(msg) ?: let { snackBar = Snackbar @@ -434,14 +439,36 @@ class BookSourceActivity : VMBaseActivity(EventBus.CHECK_SOURCE_DONE) { + adapter.notifyItemRangeChanged(0, adapter.itemCount, bundleOf(Pair("checkSourceDone", null))) snackBar?.dismiss() snackBar = null - groups.map { group -> - if (group.contains("失效")) { - searchView.setQuery("失效", true) - toastOnUi("发现有失效书源,已为您自动筛选!") +// groups.map { group -> +// if (group.contains("失效")) { +// searchView.setQuery("失效", true) +// toastOnUi("发现有失效书源,已为您自动筛选!") +// } +// } + } + observeEvent>(EventBus.CHECK_SOURCE_MESSAGE) { messagePair -> + sourceFlowJob?.cancel() + + val messageFlow = Debug.debugMessageMap[messagePair.first]?.asFlow() + if (messageFlow != null) { + sourceFlowJob = launch { + var index: Int = -1 + appDb.bookSourceDao.flowSearch(messagePair.first) + .map { adapter.getItems().indexOf(it[0]) } + .collect { + index = it } + if (index > -1){ + messageFlow.onEach { delay(300L) }.buffer(10) + .collect { adapter.notifyItemChanged(index, bundleOf(Pair(EventBus.CHECK_SOURCE_MESSAGE, it))) } + } + } } + + } } diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt index 7669362fc..9b575df85 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt @@ -13,9 +13,11 @@ import androidx.recyclerview.widget.RecyclerView import io.legado.app.R import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter +import io.legado.app.constant.EventBus import io.legado.app.data.entities.BookSource import io.legado.app.databinding.ItemBookSourceBinding import io.legado.app.lib.theme.backgroundColor +import io.legado.app.model.Debug import io.legado.app.ui.widget.recycler.DragSelectTouchHelper import io.legado.app.ui.widget.recycler.ItemTouchCallback.Callback import io.legado.app.utils.ColorUtils @@ -107,17 +109,31 @@ class BookSourceAdapter(context: Context, val callBack: CallBack) : } swtEnabled.isChecked = item.enabled cbBookSource.isChecked = selected.contains(item) + ivDebugText.text = Debug.debugMessageMap[item.bookSourceUrl]?.lastOrNull() ?: "" + ivDebugText.visibility = if(ivDebugText.text.toString().length > 1) View.VISIBLE else View.GONE upShowExplore(ivExplore, item) } else { payload.keySet().map { when (it) { "selected" -> cbBookSource.isChecked = selected.contains(item) + "startChecking" -> { + ivProgressBar.visibility = if(selected.contains(item)) View.VISIBLE else View.GONE + } + "checkSourceDone" -> { + ivProgressBar.visibility = if(selected.contains(item)) View.VISIBLE else ivProgressBar.visibility + } + EventBus.CHECK_SOURCE_MESSAGE -> { + ivDebugText.text = (payload[it] as? String) ?: "" + ivDebugText.visibility = if(ivDebugText.text.toString().length > 1) View.VISIBLE else View.GONE + } } } } } } + + override fun registerListener(holder: ItemViewHolder, binding: ItemBookSourceBinding) { binding.apply { swtEnabled.setOnCheckedChangeListener { view, checked -> diff --git a/app/src/main/java/io/legado/app/ui/rss/source/debug/RssSourceDebugModel.kt b/app/src/main/java/io/legado/app/ui/rss/source/debug/RssSourceDebugModel.kt index 23892dc6f..a22f9e531 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/debug/RssSourceDebugModel.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/debug/RssSourceDebugModel.kt @@ -44,6 +44,10 @@ class RssSourceDebugModel(application: Application) : BaseViewModel(application) } } + override fun printCheckSourceMessage(sourceUrl: String, msg: String) { + TODO("Not yet implemented") + } + override fun onCleared() { super.onCleared() Debug.cancelDebug(true) diff --git a/app/src/main/java/io/legado/app/web/SourceDebugWebSocket.kt b/app/src/main/java/io/legado/app/web/SourceDebugWebSocket.kt index c2c2f893f..307f0676e 100644 --- a/app/src/main/java/io/legado/app/web/SourceDebugWebSocket.kt +++ b/app/src/main/java/io/legado/app/web/SourceDebugWebSocket.kt @@ -95,4 +95,8 @@ class SourceDebugWebSocket(handshakeRequest: NanoHTTPD.IHTTPSession) : } } + override fun printCheckSourceMessage(sourceUrl: String, msg: String) { + TODO("Not yet implemented") + } + } diff --git a/app/src/main/res/layout/item_book_source.xml b/app/src/main/res/layout/item_book_source.xml index 4f3584999..1b2b3f89b 100644 --- a/app/src/main/res/layout/item_book_source.xml +++ b/app/src/main/res/layout/item_book_source.xml @@ -17,7 +17,7 @@ app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/swt_enabled" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" /> + app:layout_constraintBottom_toBottomOf="@id/iv_menu_more" /> + app:layout_constraintBottom_toBottomOf="@id/iv_menu_more" /> + app:layout_constraintBottom_toBottomOf="@id/iv_menu_more" /> + + + + \ No newline at end of file From 3539c118e24cd8256a42d831f4108bbc46220960 Mon Sep 17 00:00:00 2001 From: Jason Yao Date: Mon, 16 Aug 2021 02:36:18 -0400 Subject: [PATCH 2/4] change back to use debugMessageMap single thread works but last source is not showing the message --- .../main/java/io/legado/app/model/Debug.kt | 14 ++++++++------ .../legado/app/service/CheckSourceService.kt | 19 ++++++++++++++----- .../book/source/manage/BookSourceActivity.kt | 15 +++------------ .../book/source/manage/BookSourceAdapter.kt | 15 +++++++++++---- 4 files changed, 36 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/io/legado/app/model/Debug.kt b/app/src/main/java/io/legado/app/model/Debug.kt index a67fc9ca9..b696a108f 100644 --- a/app/src/main/java/io/legado/app/model/Debug.kt +++ b/app/src/main/java/io/legado/app/model/Debug.kt @@ -21,7 +21,8 @@ object Debug { var callback: Callback? = null private var debugSource: String? = null private val tasks: CompositeCoroutine = CompositeCoroutine() - val debugMessageMap = ConcurrentHashMap>() + val debugMessageMap = ConcurrentHashMap() + var isChecking: Boolean = false @SuppressLint("ConstantLocale") private val DEBUG_TIME_FORMAT = SimpleDateFormat("[mm:ss.SSS]", Locale.getDefault()) @@ -37,7 +38,7 @@ object Debug { state: Int = 1 ) { callback?.let { - if (debugSource != sourceUrl || !print) return + if ((debugSource != sourceUrl || !print) && !isChecking) return var printMsg = msg ?: "" if (isHtml) { printMsg = HtmlFormatter.format(msg) @@ -49,7 +50,8 @@ object Debug { it.printLog(state, printMsg) Log.d(EventBus.CHECK_SOURCE_MESSAGE, "debugMessage to filter $printMsg") if (sourceUrl != null && printMsg.length < 30) { - debugMessageMap[sourceUrl]?.add(printMsg) + debugMessageMap[sourceUrl] = printMsg + callback?.printCheckSourceMessage(sourceUrl, printMsg) } } } @@ -68,10 +70,10 @@ object Debug { } } - fun startCheck(source: BookSource) { - debugSource = source.bookSourceUrl + fun startChecking(source: BookSource) { startTime = System.currentTimeMillis() - debugMessageMap[source.bookSourceUrl] = arrayListOf() + isChecking = true + debugMessageMap[source.bookSourceUrl] = "开始校验" } fun startDebug(scope: CoroutineScope, rssSource: RssSource) { 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 fd03e4822..900825709 100644 --- a/app/src/main/java/io/legado/app/service/CheckSourceService.kt +++ b/app/src/main/java/io/legado/app/service/CheckSourceService.kt @@ -10,7 +10,6 @@ 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.help.AppConfig import io.legado.app.help.IntentHelp import io.legado.app.help.coroutine.CompositeCoroutine import io.legado.app.model.Debug @@ -24,7 +23,7 @@ import java.util.concurrent.Executors import kotlin.math.min class CheckSourceService : BaseService() { - private var threadCount = AppConfig.threadCount + private var threadCount = 1 private var searchCoroutine = Executors.newFixedThreadPool(min(threadCount,8)).asCoroutineDispatcher() private var tasks = CompositeCoroutine() private val allIds = ArrayList() @@ -37,7 +36,7 @@ class CheckSourceService : BaseService() { @Synchronized override fun printCheckSourceMessage(sourceUrl: String, msg: String) { - postEvent(EventBus.CHECK_SOURCE_MESSAGE, Pair(sourceUrl, msg)) + postEvent(EventBus.CHECK_SOURCE_MESSAGE, Pair(sourceUrl, null)) Log.d(EventBus.CHECK_SOURCE_MESSAGE, "printCheckSourceMessage to post $msg") } } @@ -79,6 +78,7 @@ class CheckSourceService : BaseService() { tasks.clear() searchCoroutine.close() Debug.callback = null + Debug.isChecking = false postEvent(EventBus.CHECK_SOURCE_DONE, 0) } @@ -112,7 +112,7 @@ class CheckSourceService : BaseService() { if (index < allIds.size) { val sourceUrl = allIds[index] appDb.bookSourceDao.getBookSource(sourceUrl)?.let { source -> - Debug.startCheck(source) + Debug.startChecking(source) check(source) } ?: onNext(sourceUrl, "") } @@ -150,6 +150,8 @@ class CheckSourceService : BaseService() { "error:${it.localizedMessage} ${source.bookSourceComment}" """.trimIndent() + val message = Debug.debugMessageMap[source.bookSourceUrl] + " 失败" + postEvent(EventBus.CHECK_SOURCE_MESSAGE, Pair(source.bookSourceUrl, message)) appDb.bookSourceDao.update(source) }.onSuccess(searchCoroutine) { source.removeGroup("失效") @@ -158,9 +160,16 @@ class CheckSourceService : BaseService() { ?.filterNot { it.startsWith("error:") }?.joinToString("\n") + Debug.debugMessageMap[source.bookSourceUrl]?.let { lastMessage -> + lastMessage.indexOf("]").let { + if (it > 0) { + val timeMessage = lastMessage.substring(0, it) + " 校验成功" + postEvent(EventBus.CHECK_SOURCE_MESSAGE, Pair(source.bookSourceUrl, timeMessage)) + } + } + } appDb.bookSourceDao.update(source) }.onFinally(searchCoroutine) { - postEvent(EventBus.CHECK_SOURCE_MESSAGE, Pair(source.bookSourceUrl, null)) onNext(source.bookSourceUrl, source.bookSourceName) } } diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt index 0d78984c5..7e3d3bf64 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt @@ -428,7 +428,6 @@ class BookSourceActivity : VMBaseActivity {} observeEvent(EventBus.CHECK_SOURCE) { msg -> snackBar?.setText(msg) ?: let { snackBar = Snackbar @@ -449,24 +448,16 @@ class BookSourceActivity : VMBaseActivity>(EventBus.CHECK_SOURCE_MESSAGE) { messagePair -> + observeEvent>(EventBus.CHECK_SOURCE_MESSAGE) { messagePair -> sourceFlowJob?.cancel() - - val messageFlow = Debug.debugMessageMap[messagePair.first]?.asFlow() - if (messageFlow != null) { sourceFlowJob = launch { var index: Int = -1 appDb.bookSourceDao.flowSearch(messagePair.first) .map { adapter.getItems().indexOf(it[0]) } .collect { - index = it } - if (index > -1){ - messageFlow.onEach { delay(300L) }.buffer(10) - .collect { adapter.notifyItemChanged(index, bundleOf(Pair(EventBus.CHECK_SOURCE_MESSAGE, it))) } - } - + index = it + adapter.notifyItemChanged(index, bundleOf(Pair(EventBus.CHECK_SOURCE_MESSAGE, messagePair.second))) } } - } } diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt index 9b575df85..4ebddca5e 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt @@ -109,7 +109,7 @@ class BookSourceAdapter(context: Context, val callBack: CallBack) : } swtEnabled.isChecked = item.enabled cbBookSource.isChecked = selected.contains(item) - ivDebugText.text = Debug.debugMessageMap[item.bookSourceUrl]?.lastOrNull() ?: "" + ivDebugText.text = Debug.debugMessageMap[item.bookSourceUrl] ?: "" ivDebugText.visibility = if(ivDebugText.text.toString().length > 1) View.VISIBLE else View.GONE upShowExplore(ivExplore, item) } else { @@ -117,13 +117,20 @@ class BookSourceAdapter(context: Context, val callBack: CallBack) : when (it) { "selected" -> cbBookSource.isChecked = selected.contains(item) "startChecking" -> { - ivProgressBar.visibility = if(selected.contains(item)) View.VISIBLE else View.GONE + ivProgressBar.visibility = if(selected.contains(item)) View.VISIBLE else ivProgressBar.visibility } "checkSourceDone" -> { - ivProgressBar.visibility = if(selected.contains(item)) View.VISIBLE else ivProgressBar.visibility + ivProgressBar.visibility = if(selected.contains(item)) View.GONE else ivProgressBar.visibility } EventBus.CHECK_SOURCE_MESSAGE -> { - ivDebugText.text = (payload[it] as? String) ?: "" + val message = payload[it] as? String? + if (message != null) { + ivDebugText.text = message + ivProgressBar.visibility = View.GONE + } + else{ + ivDebugText.text = Debug.debugMessageMap[item.bookSourceUrl] ?: "" + } ivDebugText.visibility = if(ivDebugText.text.toString().length > 1) View.VISIBLE else View.GONE } } From dee96f874f1a51f56c0674cec4ffba3913332fed Mon Sep 17 00:00:00 2001 From: Jason Yao Date: Thu, 19 Aug 2021 01:54:20 -0400 Subject: [PATCH 3/4] fix the last source stop checking by itself --- app/src/main/java/io/legado/app/model/Debug.kt | 9 ++++++--- .../java/io/legado/app/service/CheckSourceService.kt | 8 +++----- .../app/ui/book/source/manage/BookSourceActivity.kt | 5 ++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/io/legado/app/model/Debug.kt b/app/src/main/java/io/legado/app/model/Debug.kt index b696a108f..275f38c67 100644 --- a/app/src/main/java/io/legado/app/model/Debug.kt +++ b/app/src/main/java/io/legado/app/model/Debug.kt @@ -11,11 +11,9 @@ import io.legado.app.utils.HtmlFormatter import io.legado.app.utils.isAbsUrl import io.legado.app.utils.msg import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.flow import java.text.SimpleDateFormat import java.util.* import java.util.concurrent.ConcurrentHashMap -import kotlin.collections.ArrayList object Debug { var callback: Callback? = null @@ -48,10 +46,10 @@ object Debug { printMsg = "$time $printMsg" } it.printLog(state, printMsg) - Log.d(EventBus.CHECK_SOURCE_MESSAGE, "debugMessage to filter $printMsg") if (sourceUrl != null && printMsg.length < 30) { debugMessageMap[sourceUrl] = printMsg callback?.printCheckSourceMessage(sourceUrl, printMsg) + Log.d(EventBus.CHECK_SOURCE_MESSAGE, "debugMessage after filter $printMsg") } } } @@ -76,6 +74,11 @@ object Debug { debugMessageMap[source.bookSourceUrl] = "开始校验" } + fun finishChecking() { + callback = null + isChecking = false + } + fun startDebug(scope: CoroutineScope, rssSource: RssSource) { cancelDebug() debugSource = rssSource.sourceUrl 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 900825709..d9293cfca 100644 --- a/app/src/main/java/io/legado/app/service/CheckSourceService.kt +++ b/app/src/main/java/io/legado/app/service/CheckSourceService.kt @@ -37,7 +37,7 @@ class CheckSourceService : BaseService() { @Synchronized override fun printCheckSourceMessage(sourceUrl: String, msg: String) { postEvent(EventBus.CHECK_SOURCE_MESSAGE, Pair(sourceUrl, null)) - Log.d(EventBus.CHECK_SOURCE_MESSAGE, "printCheckSourceMessage to post $msg") + Log.d(EventBus.CHECK_SOURCE_MESSAGE, "printCheckSourceMessage to post $sourceUrl $msg") } } private val notificationBuilder by lazy { @@ -77,8 +77,6 @@ class CheckSourceService : BaseService() { super.onDestroy() tasks.clear() searchCoroutine.close() - Debug.callback = null - Debug.isChecking = false postEvent(EventBus.CHECK_SOURCE_DONE, 0) } @@ -112,7 +110,6 @@ class CheckSourceService : BaseService() { if (index < allIds.size) { val sourceUrl = allIds[index] appDb.bookSourceDao.getBookSource(sourceUrl)?.let { source -> - Debug.startChecking(source) check(source) } ?: onNext(sourceUrl, "") } @@ -121,6 +118,7 @@ class CheckSourceService : BaseService() { fun check(source: BookSource) { execute(context = searchCoroutine) { + Debug.startChecking(source) val webBook = WebBook(source) var books = webBook.searchBookAwait(this, CheckSource.keyword) if (books.isEmpty()) { @@ -181,7 +179,7 @@ class CheckSourceService : BaseService() { notificationMsg = getString(R.string.progress_show, sourceName, checkedIds.size, allIds.size) upNotification() - if (processIndex >= allIds.size + threadCount - 1) { + if (processIndex > allIds.size + threadCount - 1) { stopSelf() } } diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt index 7e3d3bf64..46f76a628 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt @@ -440,6 +440,7 @@ class BookSourceActivity : VMBaseActivity(EventBus.CHECK_SOURCE_DONE) { adapter.notifyItemRangeChanged(0, adapter.itemCount, bundleOf(Pair("checkSourceDone", null))) snackBar?.dismiss() + Debug.finishChecking() snackBar = null // groups.map { group -> // if (group.contains("失效")) { @@ -451,12 +452,10 @@ class BookSourceActivity : VMBaseActivity>(EventBus.CHECK_SOURCE_MESSAGE) { messagePair -> sourceFlowJob?.cancel() sourceFlowJob = launch { - var index: Int = -1 appDb.bookSourceDao.flowSearch(messagePair.first) .map { adapter.getItems().indexOf(it[0]) } .collect { - index = it - adapter.notifyItemChanged(index, bundleOf(Pair(EventBus.CHECK_SOURCE_MESSAGE, messagePair.second))) } + adapter.notifyItemChanged(it, bundleOf(Pair(EventBus.CHECK_SOURCE_MESSAGE, messagePair.second))) } } From f63c37235d92aec3a5a3a647acbb29ca5d332647 Mon Sep 17 00:00:00 2001 From: Jason Yao Date: Thu, 19 Aug 2021 03:34:21 -0400 Subject: [PATCH 4/4] adding share preference option and clear legacy code adding share preference option clear legacy code --- .../java/io/legado/app/constant/PreferKey.kt | 2 +- .../main/java/io/legado/app/help/AppConfig.kt | 3 ++ .../main/java/io/legado/app/model/Debug.kt | 8 +-- .../legado/app/service/CheckSourceService.kt | 49 ++++++++++--------- .../book/source/debug/BookSourceDebugModel.kt | 4 +- .../book/source/manage/BookSourceActivity.kt | 21 ++++---- .../book/source/manage/BookSourceAdapter.kt | 16 +----- .../rss/source/debug/RssSourceDebugModel.kt | 4 +- .../io/legado/app/web/SourceDebugWebSocket.kt | 2 +- app/src/main/res/layout/item_book_source.xml | 14 +++--- app/src/main/res/values-es-rES/strings.xml | 2 + app/src/main/res/values-ja-rJP/strings.xml | 2 + app/src/main/res/values-pt-rBR/strings.xml | 2 + app/src/main/res/values-zh-rHK/strings.xml | 2 + app/src/main/res/values-zh-rTW/strings.xml | 2 + app/src/main/res/values-zh/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/pref_config_other.xml | 7 +++ 18 files changed, 76 insertions(+), 68 deletions(-) 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 4c8759c31..518d053b0 100644 --- a/app/src/main/java/io/legado/app/constant/PreferKey.kt +++ b/app/src/main/java/io/legado/app/constant/PreferKey.kt @@ -100,5 +100,5 @@ object PreferKey { const val cNBBackground = "colorBottomBackgroundNight" const val bgImageN = "backgroundImageNight" const val bgImageNBlurring = "backgroundImageNightBlurring" - + const val checkSourceMessage = "checkSourceMessage" } diff --git a/app/src/main/java/io/legado/app/help/AppConfig.kt b/app/src/main/java/io/legado/app/help/AppConfig.kt index 16ebb95e1..2c4a781a4 100644 --- a/app/src/main/java/io/legado/app/help/AppConfig.kt +++ b/app/src/main/java/io/legado/app/help/AppConfig.kt @@ -246,6 +246,9 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener { val fullScreenGesturesSupport: Boolean get() = appCtx.getPrefBoolean(PreferKey.fullScreenGesturesSupport, false) + val checkSourceMessage: Boolean + get() = appCtx.getPrefBoolean(PreferKey.checkSourceMessage) + private fun getPrefUserAgent(): String { val ua = appCtx.getPrefString(PreferKey.userAgent) if (ua.isNullOrBlank()) { diff --git a/app/src/main/java/io/legado/app/model/Debug.kt b/app/src/main/java/io/legado/app/model/Debug.kt index 275f38c67..4151185bd 100644 --- a/app/src/main/java/io/legado/app/model/Debug.kt +++ b/app/src/main/java/io/legado/app/model/Debug.kt @@ -4,6 +4,7 @@ import android.annotation.SuppressLint import android.util.Log import io.legado.app.constant.EventBus import io.legado.app.data.entities.* +import io.legado.app.help.AppConfig import io.legado.app.help.coroutine.CompositeCoroutine import io.legado.app.model.rss.Rss import io.legado.app.model.webBook.WebBook @@ -20,7 +21,7 @@ object Debug { private var debugSource: String? = null private val tasks: CompositeCoroutine = CompositeCoroutine() val debugMessageMap = ConcurrentHashMap() - var isChecking: Boolean = false + private var isChecking: Boolean = false @SuppressLint("ConstantLocale") private val DEBUG_TIME_FORMAT = SimpleDateFormat("[mm:ss.SSS]", Locale.getDefault()) @@ -48,8 +49,7 @@ object Debug { it.printLog(state, printMsg) if (sourceUrl != null && printMsg.length < 30) { debugMessageMap[sourceUrl] = printMsg - callback?.printCheckSourceMessage(sourceUrl, printMsg) - Log.d(EventBus.CHECK_SOURCE_MESSAGE, "debugMessage after filter $printMsg") + callback?.postCheckMessageEvent(sourceUrl) } } } @@ -264,7 +264,7 @@ object Debug { interface Callback { fun printLog(state: Int, msg: String) - fun printCheckSourceMessage(sourceUrl: String, msg: String) + fun postCheckMessageEvent(sourceUrl: String) } } \ 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 d9293cfca..c788fae58 100644 --- a/app/src/main/java/io/legado/app/service/CheckSourceService.kt +++ b/app/src/main/java/io/legado/app/service/CheckSourceService.kt @@ -1,7 +1,6 @@ package io.legado.app.service import android.content.Intent -import android.util.Log import androidx.core.app.NotificationCompat import io.legado.app.R import io.legado.app.base.BaseService @@ -10,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.help.AppConfig import io.legado.app.help.IntentHelp import io.legado.app.help.coroutine.CompositeCoroutine import io.legado.app.model.Debug @@ -23,23 +23,14 @@ import java.util.concurrent.Executors import kotlin.math.min class CheckSourceService : BaseService() { - private var threadCount = 1 + private var threadCount = AppConfig.threadCount private var searchCoroutine = Executors.newFixedThreadPool(min(threadCount,8)).asCoroutineDispatcher() private var tasks = CompositeCoroutine() private val allIds = ArrayList() private val checkedIds = ArrayList() private var processIndex = 0 private var notificationMsg = "" - private val debugCallback = object : Debug.Callback{ - override fun printLog(state: Int, msg: String) { - } - - @Synchronized - override fun printCheckSourceMessage(sourceUrl: String, msg: String) { - postEvent(EventBus.CHECK_SOURCE_MESSAGE, Pair(sourceUrl, null)) - Log.d(EventBus.CHECK_SOURCE_MESSAGE, "printCheckSourceMessage to post $sourceUrl $msg") - } - } + private var debugCallback : Debug.Callback? = null private val notificationBuilder by lazy { NotificationCompat.Builder(this, AppConst.channelIdReadAloud) .setSmallIcon(R.drawable.ic_network_check) @@ -59,7 +50,18 @@ class CheckSourceService : BaseService() { override fun onCreate() { super.onCreate() notificationMsg = getString(R.string.start) - Debug.callback = debugCallback + if (AppConfig.checkSourceMessage) { + debugCallback = object : Debug.Callback { + override fun printLog(state: Int, msg: String) {} + + @Synchronized + override fun postCheckMessageEvent(sourceUrl: String) { + postEvent(EventBus.CHECK_SOURCE_MESSAGE, sourceUrl) + } + } + Debug.callback = debugCallback + threadCount = 1 + } upNotification() } @@ -118,7 +120,9 @@ class CheckSourceService : BaseService() { fun check(source: BookSource) { execute(context = searchCoroutine) { - Debug.startChecking(source) + if (AppConfig.checkSourceMessage) { + Debug.startChecking(source) + } val webBook = WebBook(source) var books = webBook.searchBookAwait(this, CheckSource.keyword) if (books.isEmpty()) { @@ -148,8 +152,10 @@ class CheckSourceService : BaseService() { "error:${it.localizedMessage} ${source.bookSourceComment}" """.trimIndent() - val message = Debug.debugMessageMap[source.bookSourceUrl] + " 失败" - postEvent(EventBus.CHECK_SOURCE_MESSAGE, Pair(source.bookSourceUrl, message)) + debugCallback?.let { + Debug.debugMessageMap[source.bookSourceUrl] = Debug.debugMessageMap[source.bookSourceUrl] + " 失败" + postEvent(EventBus.CHECK_SOURCE_MESSAGE, source.bookSourceUrl) + } appDb.bookSourceDao.update(source) }.onSuccess(searchCoroutine) { source.removeGroup("失效") @@ -158,14 +164,11 @@ class CheckSourceService : BaseService() { ?.filterNot { it.startsWith("error:") }?.joinToString("\n") - Debug.debugMessageMap[source.bookSourceUrl]?.let { lastMessage -> - lastMessage.indexOf("]").let { - if (it > 0) { - val timeMessage = lastMessage.substring(0, it) + " 校验成功" - postEvent(EventBus.CHECK_SOURCE_MESSAGE, Pair(source.bookSourceUrl, timeMessage)) - } - } + debugCallback?.let { debugCallback + Debug.debugMessageMap[source.bookSourceUrl] = Debug.debugMessageMap[source.bookSourceUrl] + " 成功" + postEvent(EventBus.CHECK_SOURCE_MESSAGE, source.bookSourceUrl) } + appDb.bookSourceDao.update(source) }.onFinally(searchCoroutine) { onNext(source.bookSourceUrl, source.bookSourceName) diff --git a/app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugModel.kt b/app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugModel.kt index e3a77be67..7d79dfca2 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugModel.kt @@ -51,9 +51,7 @@ class BookSourceDebugModel(application: Application) : BaseViewModel(application } } - override fun printCheckSourceMessage(sourceUrl: String, msg: String) { - TODO("Not yet implemented") - } + override fun postCheckMessageEvent(sourceUrl: String) {} override fun onCleared() { super.onCleared() diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt index 46f76a628..c3f0e7b9e 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt @@ -340,7 +340,6 @@ class BookSourceActivity : VMBaseActivity -// if (group.contains("失效")) { -// searchView.setQuery("失效", true) -// toastOnUi("发现有失效书源,已为您自动筛选!") -// } -// } + groups.map { group -> + if (group.contains("失效")) { + searchView.setQuery("失效", true) + toastOnUi("发现有失效书源,已为您自动筛选!") + } + } } - observeEvent>(EventBus.CHECK_SOURCE_MESSAGE) { messagePair -> + observeEvent(EventBus.CHECK_SOURCE_MESSAGE) { bookSourceUrl -> sourceFlowJob?.cancel() sourceFlowJob = launch { - appDb.bookSourceDao.flowSearch(messagePair.first) + appDb.bookSourceDao.flowSearch(bookSourceUrl) .map { adapter.getItems().indexOf(it[0]) } .collect { - adapter.notifyItemChanged(it, bundleOf(Pair(EventBus.CHECK_SOURCE_MESSAGE, messagePair.second))) } + adapter.notifyItemChanged(it, bundleOf(Pair(EventBus.CHECK_SOURCE_MESSAGE, null))) } } - - } } diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt index 4ebddca5e..121f0d3b2 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt @@ -116,22 +116,10 @@ class BookSourceAdapter(context: Context, val callBack: CallBack) : payload.keySet().map { when (it) { "selected" -> cbBookSource.isChecked = selected.contains(item) - "startChecking" -> { - ivProgressBar.visibility = if(selected.contains(item)) View.VISIBLE else ivProgressBar.visibility - } - "checkSourceDone" -> { - ivProgressBar.visibility = if(selected.contains(item)) View.GONE else ivProgressBar.visibility - } EventBus.CHECK_SOURCE_MESSAGE -> { - val message = payload[it] as? String? - if (message != null) { - ivDebugText.text = message - ivProgressBar.visibility = View.GONE - } - else{ - ivDebugText.text = Debug.debugMessageMap[item.bookSourceUrl] ?: "" - } + ivDebugText.text = Debug.debugMessageMap[item.bookSourceUrl] ?: "" ivDebugText.visibility = if(ivDebugText.text.toString().length > 1) View.VISIBLE else View.GONE + ivProgressBar.visibility = if(ivDebugText.text.toString().contains(Regex("成功|失败"))) View.GONE else View.VISIBLE } } } diff --git a/app/src/main/java/io/legado/app/ui/rss/source/debug/RssSourceDebugModel.kt b/app/src/main/java/io/legado/app/ui/rss/source/debug/RssSourceDebugModel.kt index a22f9e531..5d0ada568 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/debug/RssSourceDebugModel.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/debug/RssSourceDebugModel.kt @@ -44,9 +44,7 @@ class RssSourceDebugModel(application: Application) : BaseViewModel(application) } } - override fun printCheckSourceMessage(sourceUrl: String, msg: String) { - TODO("Not yet implemented") - } + override fun postCheckMessageEvent(sourceUrl: String) {} override fun onCleared() { super.onCleared() diff --git a/app/src/main/java/io/legado/app/web/SourceDebugWebSocket.kt b/app/src/main/java/io/legado/app/web/SourceDebugWebSocket.kt index 307f0676e..534a68b47 100644 --- a/app/src/main/java/io/legado/app/web/SourceDebugWebSocket.kt +++ b/app/src/main/java/io/legado/app/web/SourceDebugWebSocket.kt @@ -95,7 +95,7 @@ class SourceDebugWebSocket(handshakeRequest: NanoHTTPD.IHTTPSession) : } } - override fun printCheckSourceMessage(sourceUrl: String, msg: String) { + override fun postCheckMessageEvent(sourceUrl: String) { TODO("Not yet implemented") } diff --git a/app/src/main/res/layout/item_book_source.xml b/app/src/main/res/layout/item_book_source.xml index 1b2b3f89b..761f8e2d8 100644 --- a/app/src/main/res/layout/item_book_source.xml +++ b/app/src/main/res/layout/item_book_source.xml @@ -17,7 +17,7 @@ app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/swt_enabled" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="@id/iv_menu_more" /> + app:layout_constraintBottom_toTopOf="@id/iv_debug_text" /> + app:layout_constraintBottom_toTopOf="@id/iv_debug_text" /> + app:layout_constraintBottom_toTopOf="@id/iv_debug_text" /> + app:layout_constraintTop_toTopOf="@id/iv_debug_text" + app:layout_constraintBottom_toBottomOf="@id/iv_debug_text" /> diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index 49c3fec0a..da1c304ed 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -849,4 +849,6 @@ 未知错误 end 关闭替换分组/开启添加分组 + La fuente del libro de cheques muestra un mensaje de depuración + Muestra los pasos y el tiempo de la solicitud de red durante la verificación de la fuente del libro; actualmente solo admite la verificación de un solo hilo diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index 1ffd710ea..f42c368c8 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -850,4 +850,6 @@ No export chapter names end 关闭替换分组/开启添加分组 + Check book source shows debug message + Show network status and timestamp during source checking, currently only supports single-thread diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 78aa4c716..7901a2006 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -849,4 +849,6 @@ 未知错误 end 关闭替换分组/开启添加分组 + Verificar a fonte do livro mostra uma mensagem de depuração + Exibir etapas de solicitação de rede e tempo durante a verificação da fonte do livro; atualmente, oferece suporte apenas à verificação de thread único diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 70c62f14b..61b756c1a 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -851,5 +851,7 @@ TXT不導出章節名 end 关闭替换分组/开启添加分组 + 校驗書源顯示詳細信息 + 書源校驗時顯示網絡請求步驟和時間,當前只支持單線程校驗 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index bb8b6827a..e91784874 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -852,5 +852,7 @@ TXT不匯出章節名 end 关闭替换分组/开启添加分组 + 校驗書源顯示詳細信息 + 書源校驗時顯示網絡請求步驟和時間,當前只支持單線程校驗 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 78323bbeb..db964e59f 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -853,5 +853,7 @@ 自动备份失败 结束 关闭替换分组/开启添加分组 + 校验显示详细信息 + 书源校验时显示网络请求步骤和时间,当前只支持单线程校验 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 70aa39e1a..f3430ce78 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -855,5 +855,7 @@ Autobackup failed end 关闭替换分组/开启添加分组 + Check book source shows debug message + Show network status and timestamp during source checking, currently only supports single-thread diff --git a/app/src/main/res/xml/pref_config_other.xml b/app/src/main/res/xml/pref_config_other.xml index 28360973f..bb65cb3bd 100644 --- a/app/src/main/res/xml/pref_config_other.xml +++ b/app/src/main/res/xml/pref_config_other.xml @@ -103,6 +103,13 @@ android:title="@string/threads_num_title" app:iconSpaceReserved="false" /> + +