pull/1649/head
kunfei 3 years ago
parent e2c38639ea
commit 70121781ff
  1. 21
      app/src/main/java/io/legado/app/help/BookHelp.kt
  2. 6
      app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceDialog.kt
  3. 4
      app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceAdapter.kt
  4. 12
      app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt
  5. 6
      app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt
  6. 7
      app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
  7. 25
      app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt
  8. 0
      app/src/main/res/layout/dialog_book_change_source.xml
  9. 58
      app/src/main/res/layout/dialog_chapter_change_source.xml

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

@ -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>
Loading…
Cancel
Save