|
@@ -5,7 +5,6 @@ import android.content.Intent
|
|
|
import android.net.Uri
|
|
import android.net.Uri
|
|
|
import androidx.documentfile.provider.DocumentFile
|
|
import androidx.documentfile.provider.DocumentFile
|
|
|
import androidx.lifecycle.MutableLiveData
|
|
import androidx.lifecycle.MutableLiveData
|
|
|
-import androidx.lifecycle.viewModelScope
|
|
|
|
|
import io.legado.app.R
|
|
import io.legado.app.R
|
|
|
import io.legado.app.base.BaseViewModel
|
|
import io.legado.app.base.BaseViewModel
|
|
|
import io.legado.app.constant.AppLog
|
|
import io.legado.app.constant.AppLog
|
|
@@ -40,7 +39,6 @@ import io.legado.app.utils.mapParallelSafe
|
|
|
import io.legado.app.utils.postEvent
|
|
import io.legado.app.utils.postEvent
|
|
|
import io.legado.app.utils.toStringArray
|
|
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.flow.catch
|
|
import kotlinx.coroutines.flow.catch
|
|
|
import kotlinx.coroutines.flow.collect
|
|
import kotlinx.coroutines.flow.collect
|
|
|
import kotlinx.coroutines.flow.flow
|
|
import kotlinx.coroutines.flow.flow
|
|
@@ -97,7 +95,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private fun initBook(book: Book) {
|
|
|
|
|
|
|
+ private suspend fun initBook(book: Book) {
|
|
|
val isSameBook = ReadBook.book?.bookUrl == book.bookUrl
|
|
val isSameBook = ReadBook.book?.bookUrl == book.bookUrl
|
|
|
if (isSameBook) {
|
|
if (isSameBook) {
|
|
|
ReadBook.upData(book)
|
|
ReadBook.upData(book)
|
|
@@ -105,23 +103,23 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
|
|
|
ReadBook.resetData(book)
|
|
ReadBook.resetData(book)
|
|
|
}
|
|
}
|
|
|
isInitFinish = true
|
|
isInitFinish = true
|
|
|
- if (ReadBook.chapterSize == 0) {
|
|
|
|
|
- if (book.tocUrl.isEmpty()) {
|
|
|
|
|
- loadBookInfo(book)
|
|
|
|
|
- } else {
|
|
|
|
|
- loadChapterList(book)
|
|
|
|
|
- }
|
|
|
|
|
- } else if (book.isLocalModified()) {
|
|
|
|
|
- loadChapterList(book)
|
|
|
|
|
- } else if (isSameBook) {
|
|
|
|
|
- ReadBook.loadOrUpContent()
|
|
|
|
|
- checkLocalBookFileExist(book)
|
|
|
|
|
|
|
+ if (!book.isLocal && book.tocUrl.isEmpty() && !loadBookInfo(book)) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ if (book.isLocal && !checkLocalBookFileExist(book)) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ if ((ReadBook.chapterSize == 0 || book.isLocalModified()) && !loadChapterList(book)) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ ReadBook.upMsg(null)
|
|
|
|
|
+ if (ReadBook.durChapterIndex > ReadBook.simulatedChapterSize - 1) {
|
|
|
|
|
+ ReadBook.durChapterIndex = ReadBook.simulatedChapterSize - 1
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!isSameBook) {
|
|
|
|
|
+ ReadBook.loadContent(resetPageOffset = true)
|
|
|
} else {
|
|
} else {
|
|
|
- if (ReadBook.durChapterIndex > ReadBook.simulatedChapterSize - 1) {
|
|
|
|
|
- ReadBook.durChapterIndex = ReadBook.simulatedChapterSize - 1
|
|
|
|
|
- }
|
|
|
|
|
- ReadBook.loadContent(resetPageOffset = false)
|
|
|
|
|
- checkLocalBookFileExist(book)
|
|
|
|
|
|
|
+ ReadBook.loadOrUpContent()
|
|
|
}
|
|
}
|
|
|
if (ReadBook.chapterChanged) {
|
|
if (ReadBook.chapterChanged) {
|
|
|
// 有章节跳转不同步阅读进度
|
|
// 有章节跳转不同步阅读进度
|
|
@@ -135,42 +133,38 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private fun checkLocalBookFileExist(book: Book) {
|
|
|
|
|
- if (book.isLocal) {
|
|
|
|
|
- execute {
|
|
|
|
|
- LocalBook.getBookInputStream(book)
|
|
|
|
|
- }.onError {
|
|
|
|
|
- if (it is FileNotFoundException) {
|
|
|
|
|
- permissionDenialLiveData.postValue(0)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ private fun checkLocalBookFileExist(book: Book): Boolean {
|
|
|
|
|
+ try {
|
|
|
|
|
+ LocalBook.getBookInputStream(book)
|
|
|
|
|
+ return true
|
|
|
|
|
+ } catch (e: Throwable) {
|
|
|
|
|
+ if (e is FileNotFoundException) {
|
|
|
|
|
+ permissionDenialLiveData.postValue(0)
|
|
|
}
|
|
}
|
|
|
|
|
+ return false
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 加载详情页
|
|
* 加载详情页
|
|
|
*/
|
|
*/
|
|
|
- private fun loadBookInfo(book: Book) {
|
|
|
|
|
- if (book.isLocal) {
|
|
|
|
|
- loadChapterList(book)
|
|
|
|
|
- } else {
|
|
|
|
|
- ReadBook.bookSource?.let { source ->
|
|
|
|
|
- WebBook.getBookInfo(viewModelScope, source, book, canReName = false)
|
|
|
|
|
- .onSuccess {
|
|
|
|
|
- loadChapterList(book)
|
|
|
|
|
- }.onError {
|
|
|
|
|
- ReadBook.upMsg("详情页出错: ${it.localizedMessage}")
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ private suspend fun loadBookInfo(book: Book): Boolean {
|
|
|
|
|
+ val source = ReadBook.bookSource ?: return false
|
|
|
|
|
+ try {
|
|
|
|
|
+ WebBook.getBookInfoAwait(source, book, canReName = false)
|
|
|
|
|
+ return true
|
|
|
|
|
+ } catch (e: Throwable) {
|
|
|
|
|
+ ReadBook.upMsg("详情页出错: ${e.localizedMessage}")
|
|
|
|
|
+ return false
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 加载目录
|
|
* 加载目录
|
|
|
*/
|
|
*/
|
|
|
- fun loadChapterList(book: Book) {
|
|
|
|
|
|
|
+ suspend fun loadChapterList(book: Book): Boolean {
|
|
|
if (book.isLocal) {
|
|
if (book.isLocal) {
|
|
|
- execute {
|
|
|
|
|
|
|
+ kotlin.runCatching {
|
|
|
LocalBook.getChapterList(book).let {
|
|
LocalBook.getChapterList(book).let {
|
|
|
book.latestChapterTime = System.currentTimeMillis()
|
|
book.latestChapterTime = System.currentTimeMillis()
|
|
|
appDb.bookChapterDao.delByBook(book.bookUrl)
|
|
appDb.bookChapterDao.delByBook(book.bookUrl)
|
|
@@ -178,10 +172,9 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
|
|
|
appDb.bookDao.update(book)
|
|
appDb.bookDao.update(book)
|
|
|
ReadBook.chapterSize = it.size
|
|
ReadBook.chapterSize = it.size
|
|
|
ReadBook.simulatedChapterSize = book.simulatedTotalChapterNum()
|
|
ReadBook.simulatedChapterSize = book.simulatedTotalChapterNum()
|
|
|
- ReadBook.upMsg(null)
|
|
|
|
|
- ReadBook.loadContent(resetPageOffset = true)
|
|
|
|
|
}
|
|
}
|
|
|
- }.onError {
|
|
|
|
|
|
|
+ return true
|
|
|
|
|
+ }.onFailure {
|
|
|
when (it) {
|
|
when (it) {
|
|
|
is SecurityException, is FileNotFoundException -> {
|
|
is SecurityException, is FileNotFoundException -> {
|
|
|
permissionDenialLiveData.postValue(1)
|
|
permissionDenialLiveData.postValue(1)
|
|
@@ -192,12 +185,13 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
|
|
|
ReadBook.upMsg("LoadTocError:${it.localizedMessage}")
|
|
ReadBook.upMsg("LoadTocError:${it.localizedMessage}")
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ return false
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
ReadBook.bookSource?.let {
|
|
ReadBook.bookSource?.let {
|
|
|
val oldBook = book.copy()
|
|
val oldBook = book.copy()
|
|
|
- WebBook.getChapterList(viewModelScope, it, book, true)
|
|
|
|
|
- .onSuccess(IO) { cList ->
|
|
|
|
|
|
|
+ WebBook.getChapterListAwait(it, book, true)
|
|
|
|
|
+ .onSuccess { cList ->
|
|
|
if (oldBook.bookUrl == book.bookUrl) {
|
|
if (oldBook.bookUrl == book.bookUrl) {
|
|
|
appDb.bookDao.update(book)
|
|
appDb.bookDao.update(book)
|
|
|
} else {
|
|
} else {
|
|
@@ -208,13 +202,14 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
|
|
|
appDb.bookChapterDao.insert(*cList.toTypedArray())
|
|
appDb.bookChapterDao.insert(*cList.toTypedArray())
|
|
|
ReadBook.chapterSize = cList.size
|
|
ReadBook.chapterSize = cList.size
|
|
|
ReadBook.simulatedChapterSize = book.simulatedTotalChapterNum()
|
|
ReadBook.simulatedChapterSize = book.simulatedTotalChapterNum()
|
|
|
- ReadBook.upMsg(null)
|
|
|
|
|
- ReadBook.loadContent(resetPageOffset = true)
|
|
|
|
|
- }.onError {
|
|
|
|
|
|
|
+ return true
|
|
|
|
|
+ }.onFailure {
|
|
|
ReadBook.upMsg(context.getString(R.string.error_load_toc))
|
|
ReadBook.upMsg(context.getString(R.string.error_load_toc))
|
|
|
|
|
+ return false
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ return false
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|