mirror of
https://github.com/gedoor/legado.git
synced 2025-08-10 00:52:30 +00:00
优化
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
8
app/src/main/res/menu/source_picker.xml
Normal file
8
app/src/main/res/menu/source_picker.xml
Normal 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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user