This commit is contained in:
Horis
2023-09-01 22:33:44 +08:00
parent 59aad58cc2
commit 5b69647abb
24 changed files with 134 additions and 49 deletions

View File

@@ -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"

View File

@@ -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)

View File

@@ -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)

View File

@@ -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}")

View File

@@ -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<String> {
return Coroutine.async(scope, context) {
return Coroutine.async(scope, context, executeContext = executeContext) {
getContentAwait(bookSource, book, bookChapter, nextChapterUrl, needSave)
}
}

View File

@@ -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")

View File

@@ -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)
}
}

View File

@@ -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 {

View File

@@ -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<GroupManageDialog>()
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()

View File

@@ -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<Book>, 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)

View File

@@ -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<BookSourcePart, Item1lineTextBinding>(context) {

View File

@@ -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<Any>
) {
binding.root.setBackgroundColor(context.backgroundColor)
binding.textView.text = item.key
}

View File

@@ -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"

View File

@@ -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" />

View File

@@ -20,4 +20,9 @@
</item>
</menu>
<item
android:id="@+id/menu_open_book_info_by_click_title"
android:checkable="true"
android:title="@string/open_book_info_by_click_title" />
</menu>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_change_source_delay"
android:title="@string/change_source_delay" />
</menu>

View File

@@ -1125,4 +1125,6 @@
<string name="export_book">导出书籍</string>
<string name="export_book_notification_content">正在导出(%1$s),还有%2$d本待导出</string>
<string name="export_md">导出(MD)</string>
<string name="change_source_delay">换源间隔</string>
<string name="open_book_info_by_click_title">点击书名打开详情</string>
</resources>

View File

@@ -1128,4 +1128,6 @@
<string name="export_book">导出书籍</string>
<string name="export_book_notification_content">正在导出(%1$s),还有%2$d本待导出</string>
<string name="export_md">导出(MD)</string>
<string name="change_source_delay">换源间隔</string>
<string name="open_book_info_by_click_title">点击书名打开详情</string>
</resources>

View File

@@ -1128,4 +1128,6 @@
<string name="export_book">导出书籍</string>
<string name="export_book_notification_content">正在导出(%1$s),还有%2$d本待导出</string>
<string name="export_md">导出(MD)</string>
<string name="change_source_delay">换源间隔</string>
<string name="open_book_info_by_click_title">点击书名打开详情</string>
</resources>

View File

@@ -1124,4 +1124,6 @@ Còn </string>
<string name="export_book">导出书籍</string>
<string name="export_book_notification_content">正在导出(%1$s),还有%2$d本待导出</string>
<string name="export_md">导出(MD)</string>
<string name="change_source_delay">换源间隔</string>
<string name="open_book_info_by_click_title">点击书名打开详情</string>
</resources>

View File

@@ -1125,4 +1125,6 @@
<string name="export_book">导出书籍</string>
<string name="export_book_notification_content">正在导出(%1$s),还有%2$d本待导出</string>
<string name="export_md">导出(MD)</string>
<string name="change_source_delay">换源间隔</string>
<string name="open_book_info_by_click_title">点击书名打开详情</string>
</resources>

View File

@@ -1127,4 +1127,6 @@
<string name="export_book">导出书籍</string>
<string name="export_book_notification_content">正在导出(%1$s),还有%2$d本待导出</string>
<string name="export_md">导出(MD)</string>
<string name="change_source_delay">换源间隔</string>
<string name="open_book_info_by_click_title">点击书名打开详情</string>
</resources>

View File

@@ -1127,4 +1127,6 @@
<string name="export_book">导出书籍</string>
<string name="export_book_notification_content">正在导出(%1$s),还有%2$d本待导出</string>
<string name="export_md">导出(MD)</string>
<string name="change_source_delay">换源间隔</string>
<string name="open_book_info_by_click_title">点击书名打开详情</string>
</resources>

View File

@@ -1128,4 +1128,6 @@
<string name="export_book">导出书籍</string>
<string name="export_book_notification_content">正在导出(%1$s),还有%2$d本待导出</string>
<string name="export_md">导出(MD)</string>
<string name="change_source_delay">换源间隔</string>
<string name="open_book_info_by_click_title">点击书名打开详情</string>
</resources>