From 5b69647abb38c5f6333ad7bb2f38f100bce21183 Mon Sep 17 00:00:00 2001
From: Horis <821938089@qq.com>
Date: Fri, 1 Sep 2023 22:33:44 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/io/legado/app/constant/PreferKey.kt | 2 +
.../io/legado/app/help/config/AppConfig.kt | 12 +++++
.../java/io/legado/app/model/CacheBook.kt | 8 +--
.../main/java/io/legado/app/model/ReadBook.kt | 54 ++++++++++---------
.../io/legado/app/model/webBook/WebBook.kt | 5 +-
.../app/service/HttpReadAloudService.kt | 12 ++---
.../legado/app/service/TTSReadAloudService.kt | 3 +-
.../legado/app/ui/book/manage/BookAdapter.kt | 9 ++--
.../ui/book/manage/BookshelfManageActivity.kt | 7 +++
.../book/manage/BookshelfManageViewModel.kt | 5 +-
.../app/ui/book/manage/SourcePickerDialog.kt | 31 ++++++++++-
.../widget/keyboard/KeyboardAssistsConfig.kt | 2 +
.../main/res/layout/dialog_source_picker.xml | 1 -
.../res/layout/item_1line_text_and_del.xml | 1 -
app/src/main/res/menu/bookshelf_manage.xml | 7 ++-
app/src/main/res/menu/source_picker.xml | 8 +++
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-vi/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 +
24 files changed, 134 insertions(+), 49 deletions(-)
create mode 100644 app/src/main/res/menu/source_picker.xml
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 53ba82c0b..8b13715d9 100644
--- a/app/src/main/java/io/legado/app/constant/PreferKey.kt
+++ b/app/src/main/java/io/legado/app/constant/PreferKey.kt
@@ -133,6 +133,8 @@ object PreferKey {
const val onlyLatestBackup = "onlyLatestBackup"
const val brightnessVwPos = "brightnessVwPos"
const val shrinkDatabase = "shrinkDatabase"
+ const val batchChangeSourceDelay = "batchChangeSourceDelay"
+ const val openBookInfoByClickTitle = "openBookInfoByClickTitle"
const val cPrimary = "colorPrimary"
const val cAccent = "colorAccent"
diff --git a/app/src/main/java/io/legado/app/help/config/AppConfig.kt b/app/src/main/java/io/legado/app/help/config/AppConfig.kt
index 3a754924c..6739ccc79 100644
--- a/app/src/main/java/io/legado/app/help/config/AppConfig.kt
+++ b/app/src/main/java/io/legado/app/help/config/AppConfig.kt
@@ -380,12 +380,24 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
appCtx.putPrefBoolean(PreferKey.changeSourceLoadWordCount, value)
}
+ var openBookInfoByClickTitle: Boolean
+ get() = appCtx.getPrefBoolean(PreferKey.openBookInfoByClickTitle, true)
+ set(value) {
+ appCtx.putPrefBoolean(PreferKey.openBookInfoByClickTitle, value)
+ }
+
var contentSelectSpeakMod: Int
get() = appCtx.getPrefInt(PreferKey.contentSelectSpeakMod)
set(value) {
appCtx.putPrefInt(PreferKey.contentSelectSpeakMod, value)
}
+ var batchChangeSourceDelay: Int
+ get() = appCtx.getPrefInt(PreferKey.batchChangeSourceDelay)
+ set(value) {
+ appCtx.putPrefInt(PreferKey.batchChangeSourceDelay, value)
+ }
+
val importKeepName get() = appCtx.getPrefBoolean(PreferKey.importKeepName)
val importKeepGroup get() = appCtx.getPrefBoolean(PreferKey.importKeepGroup)
diff --git a/app/src/main/java/io/legado/app/model/CacheBook.kt b/app/src/main/java/io/legado/app/model/CacheBook.kt
index 24815d3c3..937b5a20b 100644
--- a/app/src/main/java/io/legado/app/model/CacheBook.kt
+++ b/app/src/main/java/io/legado/app/model/CacheBook.kt
@@ -18,6 +18,7 @@ import io.legado.app.utils.postEvent
import io.legado.app.utils.startService
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.delay
import java.util.concurrent.ConcurrentHashMap
@@ -243,7 +244,7 @@ object CacheBook {
waitDownloadSet.remove(chapterIndex)
onDownloadSet.add(chapterIndex)
if (BookHelp.hasContent(book, chapter)) {
- Coroutine.async {
+ Coroutine.async(executeContext = context) {
BookHelp.getContent(book, chapter)?.let {
BookHelp.saveImages(bookSource, book, chapter, it)
}
@@ -266,7 +267,8 @@ object CacheBook {
bookSource,
book,
chapter,
- context = context
+ context = context,
+ executeContext = context
).onSuccess { content ->
onSuccess(chapter)
downloadFinish(chapter, content)
@@ -295,7 +297,7 @@ object CacheBook {
postEvent(EventBus.UP_DOWNLOAD, book.bookUrl)
onDownloadSet.add(chapter.index)
waitDownloadSet.remove(chapter.index)
- WebBook.getContent(scope, bookSource, book, chapter)
+ WebBook.getContent(scope, bookSource, book, chapter, executeContext = IO)
.onSuccess { content ->
onSuccess(chapter)
downloadFinish(chapter, content, resetPageOffset)
diff --git a/app/src/main/java/io/legado/app/model/ReadBook.kt b/app/src/main/java/io/legado/app/model/ReadBook.kt
index afdb82d2c..034a19b22 100644
--- a/app/src/main/java/io/legado/app/model/ReadBook.kt
+++ b/app/src/main/java/io/legado/app/model/ReadBook.kt
@@ -441,38 +441,40 @@ object ReadBook : CoroutineScope by MainScope() {
pageChanged: Boolean,
success: (() -> Unit)? = null
) {
+ if (chapter.index !in durChapterIndex - 1..durChapterIndex + 1) {
+ return
+ }
Coroutine.async {
removeLoading(chapter.index)
- if (chapter.index in durChapterIndex - 1..durChapterIndex + 1) {
- val contentProcessor = ContentProcessor.get(book.name, book.origin)
- val displayTitle = chapter.getDisplayTitle(
- contentProcessor.getTitleReplaceRules(),
- book.getUseReplaceRule()
- )
- val contents = contentProcessor
- .getContent(book, chapter, content, includeTitle = false)
- val textChapter = ChapterProvider
- .getTextChapter(book, chapter, displayTitle, contents, chapterSize)
- when (val offset = chapter.index - durChapterIndex) {
- 0 -> {
- curTextChapter = textChapter
- if (upContent) callBack?.upContent(offset, resetPageOffset)
- callBack?.upMenuView()
- if (pageChanged) curPageChanged()
- callBack?.contentLoadFinish()
- }
+ val contentProcessor = ContentProcessor.get(book.name, book.origin)
+ val displayTitle = chapter.getDisplayTitle(
+ contentProcessor.getTitleReplaceRules(),
+ book.getUseReplaceRule()
+ )
+ val contents = contentProcessor
+ .getContent(book, chapter, content, includeTitle = false)
+ val textChapter = ChapterProvider
+ .getTextChapter(book, chapter, displayTitle, contents, chapterSize)
+ when (val offset = chapter.index - durChapterIndex) {
+ 0 -> {
+ curTextChapter = textChapter
+ if (upContent) callBack?.upContent(offset, resetPageOffset)
+ callBack?.upMenuView()
+ if (pageChanged) curPageChanged()
+ callBack?.contentLoadFinish()
+ }
- -1 -> {
- prevTextChapter = textChapter
- if (upContent) callBack?.upContent(offset, resetPageOffset)
- }
+ -1 -> {
+ prevTextChapter = textChapter
+ if (upContent) callBack?.upContent(offset, resetPageOffset)
+ }
- 1 -> {
- nextTextChapter = textChapter
- if (upContent) callBack?.upContent(offset, resetPageOffset)
- }
+ 1 -> {
+ nextTextChapter = textChapter
+ if (upContent) callBack?.upContent(offset, resetPageOffset)
}
}
+ Unit
}.onError {
AppLog.put("ChapterProvider ERROR", it)
appCtx.toastOnUi("ChapterProvider ERROR:\n${it.stackTraceStr}")
diff --git a/app/src/main/java/io/legado/app/model/webBook/WebBook.kt b/app/src/main/java/io/legado/app/model/webBook/WebBook.kt
index ecd9841b8..0592a50ef 100644
--- a/app/src/main/java/io/legado/app/model/webBook/WebBook.kt
+++ b/app/src/main/java/io/legado/app/model/webBook/WebBook.kt
@@ -265,9 +265,10 @@ object WebBook {
bookChapter: BookChapter,
nextChapterUrl: String? = null,
needSave: Boolean = true,
- context: CoroutineContext = Dispatchers.IO
+ context: CoroutineContext = Dispatchers.IO,
+ executeContext: CoroutineContext = Dispatchers.Main,
): Coroutine {
- return Coroutine.async(scope, context) {
+ return Coroutine.async(scope, context, executeContext = executeContext) {
getContentAwait(bookSource, book, bookChapter, nextChapterUrl, needSave)
}
}
diff --git a/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt b/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt
index c0f8a785b..388dc4148 100644
--- a/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt
+++ b/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt
@@ -152,8 +152,7 @@ class HttpReadAloudService : BaseReadAloudService(),
}
}
}.onError {
- toastOnUi("朗读出错:${it.localizedMessage}")
- AppLog.put("朗读下载出错\n${it.localizedMessage}", it)
+ AppLog.put("朗读下载出错\n${it.localizedMessage}", it, true)
}
}
@@ -196,8 +195,7 @@ class HttpReadAloudService : BaseReadAloudService(),
is CancellationException -> throw e
is ConcurrentException -> delay(e.waitTime.toLong())
is ScriptException, is WrappedException -> {
- AppLog.put("js错误\n${e.localizedMessage}", e)
- toastOnUi("js错误\n${e.localizedMessage}")
+ AppLog.put("js错误\n${e.localizedMessage}", e, true)
e.printOnDebug()
throw e
}
@@ -206,8 +204,7 @@ class HttpReadAloudService : BaseReadAloudService(),
downloadErrorNo++
if (downloadErrorNo > 5) {
val msg = "tts超时或连接错误超过5次\n${e.localizedMessage}"
- AppLog.put(msg, e)
- toastOnUi(msg)
+ AppLog.put(msg, e, true)
throw e
}
}
@@ -219,8 +216,7 @@ class HttpReadAloudService : BaseReadAloudService(),
e.printOnDebug()
if (downloadErrorNo > 5) {
val msg1 = "TTS服务器连续5次错误,已暂停阅读。"
- AppLog.put(msg1)
- toastOnUi(msg1)
+ AppLog.put(msg1, e, true)
throw e
} else {
AppLog.put("TTS下载音频出错,使用无声音频代替。\n朗读文本:$speakText")
diff --git a/app/src/main/java/io/legado/app/service/TTSReadAloudService.kt b/app/src/main/java/io/legado/app/service/TTSReadAloudService.kt
index a92bb00b6..122a1b62b 100644
--- a/app/src/main/java/io/legado/app/service/TTSReadAloudService.kt
+++ b/app/src/main/java/io/legado/app/service/TTSReadAloudService.kt
@@ -117,8 +117,7 @@ class TTSReadAloudService : BaseReadAloudService(), TextToSpeech.OnInitListener
}
}
}.onError {
- AppLog.put("tts朗读出错", it)
- toastOnUi(it.localizedMessage)
+ AppLog.put("tts朗读出错\n${it.localizedMessage}", it, true)
}
}
diff --git a/app/src/main/java/io/legado/app/ui/book/manage/BookAdapter.kt b/app/src/main/java/io/legado/app/ui/book/manage/BookAdapter.kt
index 83dbb3b46..3ecb9ce51 100644
--- a/app/src/main/java/io/legado/app/ui/book/manage/BookAdapter.kt
+++ b/app/src/main/java/io/legado/app/ui/book/manage/BookAdapter.kt
@@ -13,6 +13,7 @@ import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookGroup
import io.legado.app.databinding.ItemArrangeBookBinding
import io.legado.app.help.book.isLocal
+import io.legado.app.help.config.AppConfig
import io.legado.app.lib.theme.backgroundColor
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
import io.legado.app.ui.widget.recycler.ItemTouchCallback
@@ -89,9 +90,11 @@ class BookAdapter(context: Context, val callBack: CallBack) :
callBack.upSelectCount()
}
}
- tvName.setOnClickListener {
- getItem(holder.layoutPosition)?.let {
- callBack.openBook(it)
+ if (AppConfig.openBookInfoByClickTitle) {
+ tvName.setOnClickListener {
+ getItem(holder.layoutPosition)?.let {
+ callBack.openBook(it)
+ }
}
}
tvDelete.setOnClickListener {
diff --git a/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageActivity.kt b/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageActivity.kt
index e0c72c02d..7da1ca368 100644
--- a/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageActivity.kt
+++ b/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageActivity.kt
@@ -120,6 +120,8 @@ class BookshelfManageActivity :
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
this.menu = menu
+ menu.findItem(R.id.menu_open_book_info_by_click_title)?.isChecked =
+ AppConfig.openBookInfoByClickTitle
upMenu()
return super.onPrepareOptionsMenu(menu)
}
@@ -248,6 +250,11 @@ class BookshelfManageActivity :
override fun onCompatOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.menu_group_manage -> showDialogFragment()
+ R.id.menu_open_book_info_by_click_title -> {
+ AppConfig.openBookInfoByClickTitle = !item.isChecked
+ adapter.notifyItemRangeChanged(0, adapter.itemCount)
+ }
+
else -> if (item.groupId == R.id.menu_group) {
viewModel.groupName = item.title.toString()
upTitle()
diff --git a/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageViewModel.kt b/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageViewModel.kt
index fae2f2fa6..7ac618269 100644
--- a/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageViewModel.kt
+++ b/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageViewModel.kt
@@ -10,10 +10,11 @@ import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookSource
import io.legado.app.help.book.isLocal
import io.legado.app.help.book.removeType
+import io.legado.app.help.config.AppConfig
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.model.localBook.LocalBook
import io.legado.app.model.webBook.WebBook
-import io.legado.app.utils.toastOnUi
+import kotlinx.coroutines.delay
class BookshelfManageViewModel(application: Application) : BaseViewModel(application) {
@@ -52,6 +53,7 @@ class BookshelfManageViewModel(application: Application) : BaseViewModel(applica
fun changeSource(books: List, source: BookSource) {
batchChangeSourceCoroutine?.cancel()
batchChangeSourceCoroutine = execute {
+ val changeSourceDelay = AppConfig.batchChangeSourceDelay * 1000L
books.forEachIndexed { index, book ->
batchChangeSourceProcessLiveData.postValue("${index + 1} / ${books.size}")
if (book.isLocal) return@forEachIndexed
@@ -69,6 +71,7 @@ class BookshelfManageViewModel(application: Application) : BaseViewModel(applica
appDb.bookDao.insert(newBook)
appDb.bookChapterDao.insert(*toc.toTypedArray())
}
+ delay(changeSourceDelay)
}
}.onStart {
batchChangeSourceState.postValue(true)
diff --git a/app/src/main/java/io/legado/app/ui/book/manage/SourcePickerDialog.kt b/app/src/main/java/io/legado/app/ui/book/manage/SourcePickerDialog.kt
index 4c4a0bab1..7b273bd44 100644
--- a/app/src/main/java/io/legado/app/ui/book/manage/SourcePickerDialog.kt
+++ b/app/src/main/java/io/legado/app/ui/book/manage/SourcePickerDialog.kt
@@ -2,9 +2,11 @@ package io.legado.app.ui.book.manage
import android.content.Context
import android.os.Bundle
+import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.SearchView
+import androidx.appcompat.widget.Toolbar
import androidx.core.view.setPadding
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
@@ -17,8 +19,10 @@ import io.legado.app.data.entities.BookSource
import io.legado.app.data.entities.BookSourcePart
import io.legado.app.databinding.DialogSourcePickerBinding
import io.legado.app.databinding.Item1lineTextBinding
+import io.legado.app.help.config.AppConfig
import io.legado.app.lib.theme.primaryColor
import io.legado.app.lib.theme.primaryTextColor
+import io.legado.app.ui.widget.number.NumberPickerDialog
import io.legado.app.utils.applyTint
import io.legado.app.utils.dpToPx
import io.legado.app.utils.setLayout
@@ -27,12 +31,16 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import splitties.views.onClick
-class SourcePickerDialog : BaseDialogFragment(R.layout.dialog_source_picker) {
+class SourcePickerDialog : BaseDialogFragment(R.layout.dialog_source_picker),
+ Toolbar.OnMenuItemClickListener {
private val binding by viewBinding(DialogSourcePickerBinding::bind)
private val searchView: SearchView by lazy {
binding.toolBar.findViewById(R.id.search_view)
}
+ private val toolBar: Toolbar by lazy {
+ binding.toolBar.toolbar
+ }
private val adapter by lazy {
SourceAdapter(requireContext())
}
@@ -46,6 +54,7 @@ class SourcePickerDialog : BaseDialogFragment(R.layout.dialog_source_picker) {
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
initView()
initData()
+ initMenu()
}
private fun initView() {
@@ -82,6 +91,26 @@ class SourcePickerDialog : BaseDialogFragment(R.layout.dialog_source_picker) {
}
}
+ private fun initMenu() {
+ toolBar.setOnMenuItemClickListener(this)
+ toolBar.inflateMenu(R.menu.source_picker)
+ toolBar.menu.applyTint(requireContext())
+ }
+
+ override fun onMenuItemClick(item: MenuItem?): Boolean {
+ when (item?.itemId) {
+ R.id.menu_change_source_delay -> NumberPickerDialog(requireContext())
+ .setTitle(getString(R.string.change_source_delay))
+ .setMaxValue(9999)
+ .setMinValue(0)
+ .setValue(AppConfig.batchChangeSourceDelay)
+ .show {
+ AppConfig.batchChangeSourceDelay = it
+ }
+ }
+ return true
+ }
+
inner class SourceAdapter(context: Context) :
RecyclerAdapter(context) {
diff --git a/app/src/main/java/io/legado/app/ui/widget/keyboard/KeyboardAssistsConfig.kt b/app/src/main/java/io/legado/app/ui/widget/keyboard/KeyboardAssistsConfig.kt
index d8111deab..b87a5ccf5 100644
--- a/app/src/main/java/io/legado/app/ui/widget/keyboard/KeyboardAssistsConfig.kt
+++ b/app/src/main/java/io/legado/app/ui/widget/keyboard/KeyboardAssistsConfig.kt
@@ -21,6 +21,7 @@ import io.legado.app.databinding.DialogMultipleEditTextBinding
import io.legado.app.databinding.DialogRecyclerViewBinding
import io.legado.app.databinding.Item1lineTextAndDelBinding
import io.legado.app.lib.dialogs.alert
+import io.legado.app.lib.theme.backgroundColor
import io.legado.app.lib.theme.primaryColor
import io.legado.app.ui.widget.recycler.ItemTouchCallback
import io.legado.app.ui.widget.recycler.VerticalDivider
@@ -132,6 +133,7 @@ class KeyboardAssistsConfig : BaseDialogFragment(R.layout.dialog_recycler_view),
item: KeyboardAssist,
payloads: MutableList
) {
+ binding.root.setBackgroundColor(context.backgroundColor)
binding.textView.text = item.key
}
diff --git a/app/src/main/res/layout/dialog_source_picker.xml b/app/src/main/res/layout/dialog_source_picker.xml
index 4b0818ebd..03d2a5a00 100644
--- a/app/src/main/res/layout/dialog_source_picker.xml
+++ b/app/src/main/res/layout/dialog_source_picker.xml
@@ -11,7 +11,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="?attr/actionBarStyle"
- android:paddingRight="16dp"
app:attachToActivity="false"
app:contentLayout="@layout/view_search"
app:fitStatusBar="false"
diff --git a/app/src/main/res/layout/item_1line_text_and_del.xml b/app/src/main/res/layout/item_1line_text_and_del.xml
index b65a0b09b..2cc6daa2c 100644
--- a/app/src/main/res/layout/item_1line_text_and_del.xml
+++ b/app/src/main/res/layout/item_1line_text_and_del.xml
@@ -14,7 +14,6 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:background="?attr/selectableItemBackground"
android:singleLine="true"
android:textColor="@color/primaryText" />
diff --git a/app/src/main/res/menu/bookshelf_manage.xml b/app/src/main/res/menu/bookshelf_manage.xml
index ade58293c..c682bf1e3 100644
--- a/app/src/main/res/menu/bookshelf_manage.xml
+++ b/app/src/main/res/menu/bookshelf_manage.xml
@@ -20,4 +20,9 @@
-
\ No newline at end of file
+
+
+
diff --git a/app/src/main/res/menu/source_picker.xml b/app/src/main/res/menu/source_picker.xml
new file mode 100644
index 000000000..b34e11e76
--- /dev/null
+++ b/app/src/main/res/menu/source_picker.xml
@@ -0,0 +1,8 @@
+
+
diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml
index 948acfb64..64a02416e 100644
--- a/app/src/main/res/values-es-rES/strings.xml
+++ b/app/src/main/res/values-es-rES/strings.xml
@@ -1125,4 +1125,6 @@
导出书籍
正在导出(%1$s),还有%2$d本待导出
导出(MD)
+ 换源间隔
+ 点击书名打开详情
diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml
index 09346afe6..1c86d0b6c 100644
--- a/app/src/main/res/values-ja-rJP/strings.xml
+++ b/app/src/main/res/values-ja-rJP/strings.xml
@@ -1128,4 +1128,6 @@
导出书籍
正在导出(%1$s),还有%2$d本待导出
导出(MD)
+ 换源间隔
+ 点击书名打开详情
diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml
index 62b16481e..af2703f1a 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -1128,4 +1128,6 @@
导出书籍
正在导出(%1$s),还有%2$d本待导出
导出(MD)
+ 换源间隔
+ 点击书名打开详情
diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml
index 937c8b02c..6f7183e50 100644
--- a/app/src/main/res/values-vi/strings.xml
+++ b/app/src/main/res/values-vi/strings.xml
@@ -1124,4 +1124,6 @@ Còn
导出书籍
正在导出(%1$s),还有%2$d本待导出
导出(MD)
+ 换源间隔
+ 点击书名打开详情
\ No newline at end of file
diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml
index d3b6b8231..6dca930f6 100644
--- a/app/src/main/res/values-zh-rHK/strings.xml
+++ b/app/src/main/res/values-zh-rHK/strings.xml
@@ -1125,4 +1125,6 @@
导出书籍
正在导出(%1$s),还有%2$d本待导出
导出(MD)
+ 换源间隔
+ 点击书名打开详情
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index bf4303581..1754cd749 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -1127,4 +1127,6 @@
导出书籍
正在导出(%1$s),还有%2$d本待导出
导出(MD)
+ 换源间隔
+ 点击书名打开详情
diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml
index 0ec77bfdc..e88d33d01 100644
--- a/app/src/main/res/values-zh/strings.xml
+++ b/app/src/main/res/values-zh/strings.xml
@@ -1127,4 +1127,6 @@
导出书籍
正在导出(%1$s),还有%2$d本待导出
导出(MD)
+ 换源间隔
+ 点击书名打开详情
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 744f5e0fa..ed5967110 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1128,4 +1128,6 @@
导出书籍
正在导出(%1$s),还有%2$d本待导出
导出(MD)
+ 换源间隔
+ 点击书名打开详情