pull/1319/head
gedoor 4 years ago
parent 04c02c1120
commit 878635559f
  1. 2
      app/src/main/java/io/legado/app/model/Exceptions.kt
  2. 8
      app/src/main/java/io/legado/app/model/localBook/LocalBook.kt
  3. 4
      app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt
  4. 18
      app/src/main/java/io/legado/app/model/webBook/WebBook.kt
  5. 5
      app/src/main/java/io/legado/app/ui/book/audio/AudioPlayActivity.kt
  6. 21
      app/src/main/java/io/legado/app/ui/book/audio/AudioPlayViewModel.kt
  7. 18
      app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceDialog.kt
  8. 5
      app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt
  9. 18
      app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt
  10. 5
      app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
  11. 114
      app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt
  12. 2
      app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt

@ -1,5 +1,7 @@
package io.legado.app.model package io.legado.app.model
class AppException(msg: String) : Exception(msg)
/** /**
* 内容为空 * 内容为空
*/ */

@ -9,6 +9,7 @@ import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookChapter
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.BookHelp import io.legado.app.help.BookHelp
import io.legado.app.model.AppException
import io.legado.app.utils.* import io.legado.app.utils.*
import splitties.init.appCtx import splitties.init.appCtx
import java.io.File import java.io.File
@ -22,8 +23,9 @@ object LocalBook {
FileUtils.createFolderIfNotExist(appCtx.externalFiles, folderName) FileUtils.createFolderIfNotExist(appCtx.externalFiles, folderName)
} }
@Throws(Exception::class)
fun getChapterList(book: Book): ArrayList<BookChapter> { fun getChapterList(book: Book): ArrayList<BookChapter> {
return when { val chapters = when {
book.isEpub() -> { book.isEpub() -> {
EpubFile.getChapterList(book) EpubFile.getChapterList(book)
} }
@ -34,6 +36,10 @@ object LocalBook {
TextFile().analyze(book) TextFile().analyze(book)
} }
} }
if (chapters.isEmpty()) {
throw AppException("目录为空")
}
return chapters
} }
fun getContext(book: Book, chapter: BookChapter): String? { fun getContext(book: Book, chapter: BookChapter): String? {

@ -6,6 +6,7 @@ import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter 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.rule.TocRule import io.legado.app.data.entities.rule.TocRule
import io.legado.app.model.AppException
import io.legado.app.model.Debug import io.legado.app.model.Debug
import io.legado.app.model.analyzeRule.AnalyzeRule import io.legado.app.model.analyzeRule.AnalyzeRule
import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.analyzeRule.AnalyzeUrl
@ -97,6 +98,9 @@ object BookChapterList {
} }
} }
} }
if (chapterList.isEmpty()) {
throw AppException("目录为空")
}
//去重 //去重
if (!reverse) { if (!reverse) {
chapterList.reverse() chapterList.reverse()

@ -23,19 +23,19 @@ object WebBook {
bookSources: List<BookSource>, bookSources: List<BookSource>,
name: String, name: String,
author: String author: String
): Book? { ): Pair<BookSource, Book>? {
bookSources.forEach { bookSource -> bookSources.forEach { source ->
kotlin.runCatching { kotlin.runCatching {
if (!scope.isActive) return null if (!scope.isActive) return null
searchBookAwait(scope, bookSource, name).firstOrNull { searchBookAwait(scope, source, name).firstOrNull {
it.name == name && it.author == author it.name == name && it.author == author
}?.let { }?.let { searchBook ->
return if (it.tocUrl.isBlank()) { if (!scope.isActive) return null
if (!scope.isActive) return null var book = searchBook.toBook()
getBookInfoAwait(scope, bookSource, it.toBook()) if (book.tocUrl.isBlank()) {
} else { book = getBookInfoAwait(scope, source, book)
it.toBook()
} }
return Pair(source, book)
} }
} }
} }

@ -18,6 +18,7 @@ import io.legado.app.constant.EventBus
import io.legado.app.constant.Status import io.legado.app.constant.Status
import io.legado.app.constant.Theme import io.legado.app.constant.Theme
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.databinding.ActivityAudioPlayBinding import io.legado.app.databinding.ActivityAudioPlayBinding
import io.legado.app.help.BlurTransformation import io.legado.app.help.BlurTransformation
import io.legado.app.help.glide.ImageLoader import io.legado.app.help.glide.ImageLoader
@ -193,8 +194,8 @@ class AudioPlayActivity :
override val oldBook: Book? override val oldBook: Book?
get() = AudioPlay.book get() = AudioPlay.book
override fun changeTo(book: Book) { override fun changeTo(source: BookSource, book: Book) {
viewModel.changeTo(book) viewModel.changeTo(source, book)
} }
override fun finish() { override fun finish() {

@ -8,6 +8,7 @@ import io.legado.app.constant.EventBus
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.BookChapter
import io.legado.app.data.entities.BookSource
import io.legado.app.help.BookHelp import io.legado.app.help.BookHelp
import io.legado.app.model.AudioPlay import io.legado.app.model.AudioPlay
import io.legado.app.model.webBook.WebBook import io.legado.app.model.webBook.WebBook
@ -90,24 +91,24 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application)
} }
} }
fun changeTo(book1: Book) { fun changeTo(source: BookSource, book: Book) {
execute { execute {
var oldTocSize: Int = book1.totalChapterNum var oldTocSize: Int = book.totalChapterNum
AudioPlay.book?.let { AudioPlay.book?.let {
oldTocSize = it.totalChapterNum oldTocSize = it.totalChapterNum
book1.order = it.order book.order = it.order
appDb.bookDao.delete(it) appDb.bookDao.delete(it)
} }
appDb.bookDao.insert(book1) appDb.bookDao.insert(book)
AudioPlay.book = book1 AudioPlay.book = book
AudioPlay.bookSource = appDb.bookSourceDao.getBookSource(book1.origin) AudioPlay.bookSource = source
if (book1.tocUrl.isEmpty()) { if (book.tocUrl.isEmpty()) {
loadBookInfo(book1) { upChangeDurChapterIndex(book1, oldTocSize, it) } loadBookInfo(book) { upChangeDurChapterIndex(book, oldTocSize, it) }
} else { } else {
loadChapterList(book1) { upChangeDurChapterIndex(book1, oldTocSize, it) } loadChapterList(book) { upChangeDurChapterIndex(book, oldTocSize, it) }
} }
}.onFinally { }.onFinally {
postEvent(EventBus.SOURCE_CHANGED, book1.bookUrl) postEvent(EventBus.SOURCE_CHANGED, book.bookUrl)
} }
} }

@ -16,6 +16,7 @@ import io.legado.app.constant.EventBus
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.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.DialogChangeSourceBinding
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
@ -228,11 +229,16 @@ class ChangeSourceDialog : BaseDialogFragment(),
} }
private fun changeSource(searchBook: SearchBook) { private fun changeSource(searchBook: SearchBook) {
val book = searchBook.toBook() try {
book.upInfoFromOld(callBack?.oldBook) val book = searchBook.toBook()
callBack?.changeTo(book) book.upInfoFromOld(callBack?.oldBook)
searchBook.time = System.currentTimeMillis() val source = appDb.bookSourceDao.getBookSource(book.origin)
viewModel.updateSource(searchBook) callBack?.changeTo(source!!, book)
searchBook.time = System.currentTimeMillis()
viewModel.updateSource(searchBook)
} catch (e: Exception) {
toastOnUi("换源失败\n${e.localizedMessage}")
}
} }
/** /**
@ -272,7 +278,7 @@ class ChangeSourceDialog : BaseDialogFragment(),
interface CallBack { interface CallBack {
val oldBook: Book? val oldBook: Book?
fun changeTo(book: Book) fun changeTo(source: BookSource, book: Book)
} }
} }

@ -20,6 +20,7 @@ import io.legado.app.constant.Theme
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.BookChapter
import io.legado.app.data.entities.BookSource
import io.legado.app.databinding.ActivityBookInfoBinding import io.legado.app.databinding.ActivityBookInfoBinding
import io.legado.app.databinding.DialogEditTextBinding import io.legado.app.databinding.DialogEditTextBinding
import io.legado.app.help.BlurTransformation import io.legado.app.help.BlurTransformation
@ -435,9 +436,9 @@ class BookInfoActivity :
override val oldBook: Book? override val oldBook: Book?
get() = viewModel.bookData.value get() = viewModel.bookData.value
override fun changeTo(book: Book) { override fun changeTo(source: BookSource, book: Book) {
upLoading(true) upLoading(true)
viewModel.changeTo(book) viewModel.changeTo(source, book)
} }
override fun coverChangeTo(coverUrl: String) { override fun coverChangeTo(coverUrl: String) {

@ -51,7 +51,11 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
private fun setBook(book: Book) { private fun setBook(book: Book) {
durChapterIndex = book.durChapterIndex durChapterIndex = book.durChapterIndex
bookData.postValue(book) bookData.postValue(book)
initBookSource(book) bookSource = if (book.isLocalBook()) {
null
} else {
appDb.bookSourceDao.getBookSource(book.origin)
}
if (book.tocUrl.isEmpty()) { if (book.tocUrl.isEmpty()) {
loadBookInfo(book) loadBookInfo(book)
} else { } else {
@ -64,14 +68,6 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
} }
} }
private fun initBookSource(book: Book) {
bookSource = if (book.isLocalBook()) {
null
} else {
appDb.bookSourceDao.getBookSource(book.origin)
}
}
fun loadBookInfo( fun loadBookInfo(
book: Book, canReName: Boolean = true, book: Book, canReName: Boolean = true,
changeDruChapterIndex: ((chapters: List<BookChapter>) -> Unit)? = null, changeDruChapterIndex: ((chapters: List<BookChapter>) -> Unit)? = null,
@ -149,7 +145,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
} }
} }
fun changeTo(newBook: Book) { fun changeTo(source: BookSource, newBook: Book) {
execute { execute {
var oldTocSize: Int = newBook.totalChapterNum var oldTocSize: Int = newBook.totalChapterNum
if (inBookshelf) { if (inBookshelf) {
@ -159,7 +155,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
} }
} }
bookData.postValue(newBook) bookData.postValue(newBook)
initBookSource(newBook) bookSource = source
if (newBook.tocUrl.isEmpty()) { if (newBook.tocUrl.isEmpty()) {
loadBookInfo(newBook, false) { loadBookInfo(newBook, false) {
upChangeDurChapterIndex(newBook, oldTocSize, it) upChangeDurChapterIndex(newBook, oldTocSize, it)

@ -20,6 +20,7 @@ import io.legado.app.constant.Status
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.BookChapter
import io.legado.app.data.entities.BookProgress import io.legado.app.data.entities.BookProgress
import io.legado.app.data.entities.BookSource
import io.legado.app.help.ReadBookConfig import io.legado.app.help.ReadBookConfig
import io.legado.app.help.ReadTipConfig import io.legado.app.help.ReadTipConfig
import io.legado.app.help.storage.AppWebDav import io.legado.app.help.storage.AppWebDav
@ -642,8 +643,8 @@ class ReadBookActivity : ReadBookBaseActivity(),
override val oldBook: Book? override val oldBook: Book?
get() = ReadBook.book get() = ReadBook.book
override fun changeTo(book: Book) { override fun changeTo(source: BookSource, book: Book) {
viewModel.changeTo(book) viewModel.changeTo(source, book)
} }
override fun showActionMenu() { override fun showActionMenu() {

@ -8,8 +8,8 @@ import io.legado.app.base.BaseViewModel
import io.legado.app.constant.EventBus import io.legado.app.constant.EventBus
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.BookProgress import io.legado.app.data.entities.BookProgress
import io.legado.app.data.entities.BookSource
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.BookHelp import io.legado.app.help.BookHelp
import io.legado.app.help.ContentProcessor import io.legado.app.help.ContentProcessor
@ -101,26 +101,22 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
} }
} }
private fun loadBookInfo( private fun loadBookInfo(book: Book) {
book: Book,
changeDruChapterIndex: ((chapters: List<BookChapter>) -> Unit)? = null,
) {
if (book.isLocalBook()) { if (book.isLocalBook()) {
loadChapterList(book, changeDruChapterIndex) loadChapterList(book)
} else { } else {
ReadBook.bookSource?.let { ReadBook.bookSource?.let { source ->
WebBook.getBookInfo(viewModelScope, it, book, canReName = false) WebBook.getBookInfo(viewModelScope, source, book, canReName = false)
.onSuccess { .onSuccess {
loadChapterList(book, changeDruChapterIndex) loadChapterList(book)
}.onError {
ReadBook.upMsg("详情页出错: ${it.localizedMessage}")
} }
} }
} }
} }
fun loadChapterList( fun loadChapterList(book: Book) {
book: Book,
changeDruChapterIndex: ((chapters: List<BookChapter>) -> Unit)? = null,
) {
if (book.isLocalBook()) { if (book.isLocalBook()) {
execute { execute {
LocalBook.getChapterList(book).let { LocalBook.getChapterList(book).let {
@ -128,12 +124,8 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
appDb.bookChapterDao.insert(*it.toTypedArray()) appDb.bookChapterDao.insert(*it.toTypedArray())
appDb.bookDao.update(book) appDb.bookDao.update(book)
ReadBook.chapterSize = it.size ReadBook.chapterSize = it.size
if (it.isEmpty()) { ReadBook.upMsg(null)
ReadBook.upMsg(context.getString(R.string.error_load_toc)) ReadBook.loadContent(resetPageOffset = true)
} else {
ReadBook.upMsg(null)
ReadBook.loadContent(resetPageOffset = true)
}
} }
}.onError { }.onError {
ReadBook.upMsg("LoadTocError:${it.localizedMessage}") ReadBook.upMsg("LoadTocError:${it.localizedMessage}")
@ -142,19 +134,11 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
ReadBook.bookSource?.let { ReadBook.bookSource?.let {
WebBook.getChapterList(viewModelScope, it, book) WebBook.getChapterList(viewModelScope, it, book)
.onSuccess(IO) { cList -> .onSuccess(IO) { cList ->
if (cList.isNotEmpty()) { appDb.bookChapterDao.insert(*cList.toTypedArray())
if (changeDruChapterIndex == null) { appDb.bookDao.update(book)
appDb.bookChapterDao.insert(*cList.toTypedArray()) ReadBook.chapterSize = cList.size
appDb.bookDao.update(book) ReadBook.upMsg(null)
ReadBook.chapterSize = cList.size ReadBook.loadContent(resetPageOffset = true)
ReadBook.upMsg(null)
ReadBook.loadContent(resetPageOffset = true)
} else {
changeDruChapterIndex(cList)
}
} else {
ReadBook.upMsg(context.getString(R.string.error_load_toc))
}
}.onError { }.onError {
ReadBook.upMsg(context.getString(R.string.error_load_toc)) ReadBook.upMsg(context.getString(R.string.error_load_toc))
} }
@ -183,23 +167,32 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
} }
} }
fun changeTo(newBook: Book) { fun changeTo(source: BookSource, book: Book) {
execute { execute {
val oldTocSize: Int = ReadBook.book?.totalChapterNum ?: newBook.totalChapterNum ReadBook.upMsg(context.getString(R.string.loading))
ReadBook.upMsg(null) if (book.tocUrl.isEmpty()) {
ReadBook.resetData(newBook) WebBook.getBookInfoAwait(this, source, book)
ReadBook.callBack?.upContent() }
if (newBook.tocUrl.isEmpty()) { val chapters = WebBook.getChapterListAwait(this, source, book)
loadBookInfo(newBook) { ReadBook.book!!.let { oldBook ->
upChangeDurChapterIndex(newBook, oldTocSize, it) book.durChapterIndex = BookHelp.getDurChapter(
} oldBook.durChapterIndex,
} else { oldBook.totalChapterNum,
loadChapterList(newBook) { oldBook.durChapterTitle,
upChangeDurChapterIndex(newBook, oldTocSize, it) chapters
} )
book.durChapterTitle = chapters[ReadBook.durChapterIndex].title
oldBook.changeTo(book)
} }
appDb.bookChapterDao.insert(*chapters.toTypedArray())
ReadBook.resetData(book)
ReadBook.upMsg(null)
ReadBook.loadContent(resetPageOffset = true)
}.onError {
context.toastOnUi("换源失败\n${it.localizedMessage}")
ReadBook.upMsg(null)
}.onFinally { }.onFinally {
postEvent(EventBus.SOURCE_CHANGED, newBook.bookUrl) postEvent(EventBus.SOURCE_CHANGED, book.bookUrl)
} }
} }
@ -207,13 +200,10 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
if (!AppConfig.autoChangeSource) return if (!AppConfig.autoChangeSource) return
execute { execute {
val sources = appDb.bookSourceDao.allTextEnabled val sources = appDb.bookSourceDao.allTextEnabled
val book = WebBook.preciseSearch(this, sources, name, author) WebBook.preciseSearch(this, sources, name, author)?.let {
if (book != null) { it.second.upInfoFromOld(ReadBook.book)
book.upInfoFromOld(ReadBook.book) changeTo(it.first, it.second)
changeTo(book) } ?: throw Exception("自动换源失败")
} else {
throw Exception("自动换源失败")
}
}.onStart { }.onStart {
ReadBook.upMsg(context.getString(R.string.source_auto_changing)) ReadBook.upMsg(context.getString(R.string.source_auto_changing))
}.onError { }.onError {
@ -223,24 +213,6 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
} }
} }
private fun upChangeDurChapterIndex(book: Book, oldTocSize: Int, chapters: List<BookChapter>) {
execute {
ReadBook.durChapterIndex = BookHelp.getDurChapter(
book.durChapterIndex,
oldTocSize,
book.durChapterTitle,
chapters
)
book.durChapterIndex = ReadBook.durChapterIndex
book.durChapterTitle = chapters[ReadBook.durChapterIndex].title
appDb.bookDao.update(book)
appDb.bookChapterDao.insert(*chapters.toTypedArray())
ReadBook.chapterSize = chapters.size
ReadBook.upMsg(null)
ReadBook.loadContent(resetPageOffset = true)
}
}
fun openChapter(index: Int, durChapterPos: Int = 0, success: (() -> Unit)? = null) { fun openChapter(index: Int, durChapterPos: Int = 0, success: (() -> Unit)? = null) {
ReadBook.clearTextChapter() ReadBook.clearTextChapter()
ReadBook.callBack?.upContent() ReadBook.callBack?.upContent()

@ -112,7 +112,7 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application)
val name = it["name"] ?: "" val name = it["name"] ?: ""
val author = it["author"] ?: "" val author = it["author"] ?: ""
if (name.isNotEmpty() && appDb.bookDao.getBook(name, author) == null) { if (name.isNotEmpty() && appDb.bookDao.getBook(name, author) == null) {
val book = WebBook.preciseSearch(this, bookSources, name, author) val book = WebBook.preciseSearch(this, bookSources, name, author)?.second
book?.let { book?.let {
if (groupId > 0) { if (groupId > 0) {
book.group = groupId book.group = groupId

Loading…
Cancel
Save