优化
This commit is contained in:
@@ -226,27 +226,6 @@ object BookHelp {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 反转章节内容
|
|
||||||
*/
|
|
||||||
fun reverseContent(book: Book, bookChapter: BookChapter) {
|
|
||||||
if (!book.isLocalBook()) {
|
|
||||||
val file = downloadDir.getFile(
|
|
||||||
cacheFolderName,
|
|
||||||
book.getFolderName(),
|
|
||||||
bookChapter.getFileName()
|
|
||||||
)
|
|
||||||
if (file.exists()) {
|
|
||||||
val text = file.readText()
|
|
||||||
val stringBuilder = StringBuilder()
|
|
||||||
text.toStringArray().forEach {
|
|
||||||
stringBuilder.insert(0, it)
|
|
||||||
}
|
|
||||||
file.writeText(stringBuilder.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除章节内容
|
* 删除章节内容
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import io.legado.app.data.appDb
|
|||||||
import io.legado.app.data.entities.Book
|
import io.legado.app.data.entities.Book
|
||||||
import io.legado.app.data.entities.BookSource
|
import io.legado.app.data.entities.BookSource
|
||||||
import io.legado.app.data.entities.SearchBook
|
import io.legado.app.data.entities.SearchBook
|
||||||
import io.legado.app.databinding.DialogChangeSourceBinding
|
import io.legado.app.databinding.DialogBookChangeSourceBinding
|
||||||
import io.legado.app.help.AppConfig
|
import io.legado.app.help.AppConfig
|
||||||
import io.legado.app.lib.theme.primaryColor
|
import io.legado.app.lib.theme.primaryColor
|
||||||
import io.legado.app.ui.book.source.edit.BookSourceEditActivity
|
import io.legado.app.ui.book.source.edit.BookSourceEditActivity
|
||||||
@@ -31,7 +31,7 @@ import kotlinx.coroutines.delay
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_change_source),
|
class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_source),
|
||||||
Toolbar.OnMenuItemClickListener,
|
Toolbar.OnMenuItemClickListener,
|
||||||
ChangeBookSourceAdapter.CallBack {
|
ChangeBookSourceAdapter.CallBack {
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_change_sourc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val binding by viewBinding(DialogChangeSourceBinding::bind)
|
private val binding by viewBinding(DialogBookChangeSourceBinding::bind)
|
||||||
private val groups = linkedSetOf<String>()
|
private val groups = linkedSetOf<String>()
|
||||||
private val callBack: CallBack? get() = activity as? CallBack
|
private val callBack: CallBack? get() = activity as? CallBack
|
||||||
private val viewModel: ChangeBookSourceViewModel by viewModels()
|
private val viewModel: ChangeBookSourceViewModel by viewModels()
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class ChangeChapterSourceAdapter(
|
|||||||
override fun registerListener(holder: ItemViewHolder, binding: ItemChangeSourceBinding) {
|
override fun registerListener(holder: ItemViewHolder, binding: ItemChangeSourceBinding) {
|
||||||
holder.itemView.setOnClickListener {
|
holder.itemView.setOnClickListener {
|
||||||
getItem(holder.layoutPosition)?.let {
|
getItem(holder.layoutPosition)?.let {
|
||||||
callBack.changeTo(it)
|
callBack.openToc(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
holder.itemView.onLongClick {
|
holder.itemView.onLongClick {
|
||||||
@@ -112,7 +112,7 @@ class ChangeChapterSourceAdapter(
|
|||||||
|
|
||||||
interface CallBack {
|
interface CallBack {
|
||||||
val bookUrl: String?
|
val bookUrl: String?
|
||||||
fun changeTo(searchBook: SearchBook)
|
fun openToc(searchBook: SearchBook)
|
||||||
fun topSource(searchBook: SearchBook)
|
fun topSource(searchBook: SearchBook)
|
||||||
fun bottomSource(searchBook: SearchBook)
|
fun bottomSource(searchBook: SearchBook)
|
||||||
fun editSource(searchBook: SearchBook)
|
fun editSource(searchBook: SearchBook)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import io.legado.app.data.appDb
|
|||||||
import io.legado.app.data.entities.Book
|
import io.legado.app.data.entities.Book
|
||||||
import io.legado.app.data.entities.BookSource
|
import io.legado.app.data.entities.BookSource
|
||||||
import io.legado.app.data.entities.SearchBook
|
import io.legado.app.data.entities.SearchBook
|
||||||
import io.legado.app.databinding.DialogChangeSourceBinding
|
import io.legado.app.databinding.DialogChapterChangeSourceBinding
|
||||||
import io.legado.app.help.AppConfig
|
import io.legado.app.help.AppConfig
|
||||||
import io.legado.app.lib.theme.primaryColor
|
import io.legado.app.lib.theme.primaryColor
|
||||||
import io.legado.app.ui.book.source.edit.BookSourceEditActivity
|
import io.legado.app.ui.book.source.edit.BookSourceEditActivity
|
||||||
@@ -31,7 +31,7 @@ import kotlinx.coroutines.delay
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_change_source),
|
class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_change_source),
|
||||||
Toolbar.OnMenuItemClickListener,
|
Toolbar.OnMenuItemClickListener,
|
||||||
ChangeChapterSourceAdapter.CallBack {
|
ChangeChapterSourceAdapter.CallBack {
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_change_so
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val binding by viewBinding(DialogChangeSourceBinding::bind)
|
private val binding by viewBinding(DialogChapterChangeSourceBinding::bind)
|
||||||
private val groups = linkedSetOf<String>()
|
private val groups = linkedSetOf<String>()
|
||||||
private val callBack: CallBack? get() = activity as? CallBack
|
private val callBack: CallBack? get() = activity as? CallBack
|
||||||
private val viewModel: ChangeChapterSourceViewModel by viewModels()
|
private val viewModel: ChangeChapterSourceViewModel by viewModels()
|
||||||
@@ -196,9 +196,8 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_change_so
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun changeTo(searchBook: SearchBook) {
|
override fun openToc(searchBook: SearchBook) {
|
||||||
changeSource(searchBook)
|
|
||||||
dismissAllowingStateLoss()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val bookUrl: String?
|
override val bookUrl: String?
|
||||||
@@ -282,6 +281,7 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_change_so
|
|||||||
interface CallBack {
|
interface CallBack {
|
||||||
val oldBook: Book?
|
val oldBook: Book?
|
||||||
fun changeTo(source: BookSource, book: Book)
|
fun changeTo(source: BookSource, book: Book)
|
||||||
|
fun replaceContent(content: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+5
-1
@@ -11,6 +11,7 @@ import io.legado.app.constant.AppPattern
|
|||||||
import io.legado.app.constant.PreferKey
|
import io.legado.app.constant.PreferKey
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
import io.legado.app.data.entities.Book
|
import io.legado.app.data.entities.Book
|
||||||
|
import io.legado.app.data.entities.BookChapter
|
||||||
import io.legado.app.data.entities.BookSource
|
import io.legado.app.data.entities.BookSource
|
||||||
import io.legado.app.data.entities.SearchBook
|
import io.legado.app.data.entities.SearchBook
|
||||||
import io.legado.app.help.AppConfig
|
import io.legado.app.help.AppConfig
|
||||||
@@ -28,6 +29,7 @@ import kotlinx.coroutines.flow.flowOn
|
|||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import splitties.init.appCtx
|
import splitties.init.appCtx
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
@@ -35,6 +37,7 @@ import kotlin.math.min
|
|||||||
class ChangeChapterSourceViewModel(application: Application) : BaseViewModel(application) {
|
class ChangeChapterSourceViewModel(application: Application) : BaseViewModel(application) {
|
||||||
private val threadCount = AppConfig.threadCount
|
private val threadCount = AppConfig.threadCount
|
||||||
private var searchPool: ExecutorCoroutineDispatcher? = null
|
private var searchPool: ExecutorCoroutineDispatcher? = null
|
||||||
|
private val searchGroup get() = appCtx.getPrefString("searchGroup") ?: ""
|
||||||
val searchStateData = MutableLiveData<Boolean>()
|
val searchStateData = MutableLiveData<Boolean>()
|
||||||
var name: String = ""
|
var name: String = ""
|
||||||
var author: String = ""
|
var author: String = ""
|
||||||
@@ -42,7 +45,7 @@ class ChangeChapterSourceViewModel(application: Application) : BaseViewModel(app
|
|||||||
private var screenKey: String = ""
|
private var screenKey: String = ""
|
||||||
private var bookSourceList = arrayListOf<BookSource>()
|
private var bookSourceList = arrayListOf<BookSource>()
|
||||||
private val searchBooks = ConcurrentHashSet<SearchBook>()
|
private val searchBooks = ConcurrentHashSet<SearchBook>()
|
||||||
private val searchGroup get() = appCtx.getPrefString("searchGroup") ?: ""
|
private val tocMap = ConcurrentHashMap<String, List<BookChapter>>()
|
||||||
private var searchCallback: SourceCallback? = null
|
private var searchCallback: SourceCallback? = null
|
||||||
val searchDataFlow = callbackFlow {
|
val searchDataFlow = callbackFlow {
|
||||||
|
|
||||||
@@ -203,6 +206,7 @@ class ChangeChapterSourceViewModel(application: Application) : BaseViewModel(app
|
|||||||
private fun loadBookToc(source: BookSource, book: Book) {
|
private fun loadBookToc(source: BookSource, book: Book) {
|
||||||
WebBook.getChapterList(viewModelScope, source, book, context = searchPool!!)
|
WebBook.getChapterList(viewModelScope, source, book, context = searchPool!!)
|
||||||
.onSuccess(IO) { chapters ->
|
.onSuccess(IO) { chapters ->
|
||||||
|
tocMap[book.bookUrl] = chapters
|
||||||
book.latestChapterTitle = chapters.last().title
|
book.latestChapterTitle = chapters.last().title
|
||||||
val searchBook: SearchBook = book.toSearchBook()
|
val searchBook: SearchBook = book.toSearchBook()
|
||||||
searchCallback?.searchSuccess(searchBook)
|
searchCallback?.searchSuccess(searchBook)
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ class ReadBookActivity : BaseReadBookActivity(),
|
|||||||
SearchMenu.CallBack,
|
SearchMenu.CallBack,
|
||||||
ReadAloudDialog.CallBack,
|
ReadAloudDialog.CallBack,
|
||||||
ChangeBookSourceDialog.CallBack,
|
ChangeBookSourceDialog.CallBack,
|
||||||
|
ChangeChapterSourceDialog.CallBack,
|
||||||
ReadBook.CallBack,
|
ReadBook.CallBack,
|
||||||
AutoReadDialog.CallBack,
|
AutoReadDialog.CallBack,
|
||||||
TocRegexDialog.CallBack,
|
TocRegexDialog.CallBack,
|
||||||
@@ -689,6 +690,12 @@ class ReadBookActivity : BaseReadBookActivity(),
|
|||||||
viewModel.changeTo(source, book)
|
viewModel.changeTo(source, book)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun replaceContent(content: String) {
|
||||||
|
ReadBook.book?.let {
|
||||||
|
viewModel.saveContent(it, content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun showActionMenu() {
|
override fun showActionMenu() {
|
||||||
when {
|
when {
|
||||||
BaseReadAloudService.isRun -> showReadAloudDialog()
|
BaseReadAloudService.isRun -> showReadAloudDialog()
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import io.legado.app.ui.book.read.page.entities.TextChapter
|
|||||||
import io.legado.app.ui.book.searchContent.SearchResult
|
import io.legado.app.ui.book.searchContent.SearchResult
|
||||||
import io.legado.app.utils.msg
|
import io.legado.app.utils.msg
|
||||||
import io.legado.app.utils.postEvent
|
import io.legado.app.utils.postEvent
|
||||||
|
import io.legado.app.utils.toStringArray
|
||||||
import io.legado.app.utils.toastOnUi
|
import io.legado.app.utils.toastOnUi
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.ensureActive
|
import kotlinx.coroutines.ensureActive
|
||||||
@@ -283,16 +284,36 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reverseContent(book: Book) {
|
/**
|
||||||
|
* 保存内容
|
||||||
|
*/
|
||||||
|
fun saveContent(book: Book, content: String) {
|
||||||
execute {
|
execute {
|
||||||
appDb.bookChapterDao.getChapter(book.bookUrl, ReadBook.durChapterIndex)
|
appDb.bookChapterDao.getChapter(book.bookUrl, ReadBook.durChapterIndex)
|
||||||
?.let { chapter ->
|
?.let { chapter ->
|
||||||
BookHelp.reverseContent(book, chapter)
|
BookHelp.saveText(book, chapter, content)
|
||||||
ReadBook.loadContent(ReadBook.durChapterIndex, resetPageOffset = false)
|
ReadBook.loadContent(ReadBook.durChapterIndex, resetPageOffset = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反转内容
|
||||||
|
*/
|
||||||
|
fun reverseContent(book: Book) {
|
||||||
|
execute {
|
||||||
|
val chapter = appDb.bookChapterDao.getChapter(book.bookUrl, ReadBook.durChapterIndex)
|
||||||
|
?: return@execute
|
||||||
|
val content = BookHelp.getContent(book, chapter) ?: return@execute
|
||||||
|
val stringBuilder = StringBuilder()
|
||||||
|
content.toStringArray().forEach {
|
||||||
|
stringBuilder.insert(0, it)
|
||||||
|
}
|
||||||
|
BookHelp.saveText(book, chapter, stringBuilder.toString())
|
||||||
|
ReadBook.loadContent(ReadBook.durChapterIndex, resetPageOffset = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 内容搜索跳转
|
* 内容搜索跳转
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/background">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/tool_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/background_menu"
|
||||||
|
android:elevation="5dp"
|
||||||
|
android:theme="?attr/actionBarStyle"
|
||||||
|
app:titleTextAppearance="@style/ToolbarTitle"
|
||||||
|
app:popupTheme="@style/AppTheme.PopupOverlay"
|
||||||
|
app:displayHomeAsUp="false"
|
||||||
|
app:fitStatusBar="false"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<io.legado.app.ui.widget.anima.RefreshProgressBar
|
||||||
|
android:id="@+id/refresh_progress_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="2dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/tool_bar" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/refresh_progress_bar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.LinearLayoutCompat
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:background="@color/background"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/tool_bar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="36dp"
|
||||||
|
android:src="@drawable/ic_arrow_down"
|
||||||
|
app:tint="@color/primaryText" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler_view_toc"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/refresh_progress_bar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
|
|
||||||
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
Reference in New Issue
Block a user