This commit is contained in:
Horis
2024-07-10 16:20:41 +08:00
parent 983ec96158
commit c940b51a59
14 changed files with 67 additions and 30 deletions
@@ -13,6 +13,9 @@ interface BookChapterDao {
@Query("SELECT * FROM chapters where bookUrl = :bookUrl and title like '%'||:key||'%' order by `index`") @Query("SELECT * FROM chapters where bookUrl = :bookUrl and title like '%'||:key||'%' order by `index`")
fun search(bookUrl: String, key: String): List<BookChapter> fun search(bookUrl: String, key: String): List<BookChapter>
@Query("SELECT * FROM chapters where bookUrl = :bookUrl and `index` >= :start and `index` <= :end and title like '%'||:key||'%' order by `index`")
fun search(bookUrl: String, key: String, start: Int, end: Int): List<BookChapter>
@Query("select * from chapters where bookUrl = :bookUrl order by `index`") @Query("select * from chapters where bookUrl = :bookUrl order by `index`")
fun getChapterList(bookUrl: String): List<BookChapter> fun getChapterList(bookUrl: String): List<BookChapter>
@@ -17,6 +17,7 @@ import io.legado.app.help.book.ContentProcessor
import io.legado.app.help.book.isEpub import io.legado.app.help.book.isEpub
import io.legado.app.help.book.isImage import io.legado.app.help.book.isImage
import io.legado.app.help.book.isPdf import io.legado.app.help.book.isPdf
import io.legado.app.help.book.simulatedTotalChapterNum
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
import io.legado.app.help.config.ReadBookConfig import io.legado.app.help.config.ReadBookConfig
import io.legado.app.model.ReadBook import io.legado.app.model.ReadBook
@@ -27,7 +28,6 @@ import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import java.nio.charset.Charset import java.nio.charset.Charset
import java.time.LocalDate import java.time.LocalDate
import java.time.Period.between
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@@ -160,18 +160,6 @@ data class Book(
@IgnoredOnParcel @IgnoredOnParcel
val lastChapterIndex get() = totalChapterNum - 1 val lastChapterIndex get() = totalChapterNum - 1
// 根据当前日期计算章节总数
fun simulatedTotalChapterNum(): Int {
if (config.readSimulating) {
val currentDate = LocalDate.now()
val daysPassed = between(this.config.startDate, currentDate).days + 1
// 计算当前应该解锁到哪一章
val chaptersToUnlock =
max(0, (config.startChapter ?: 0) + (daysPassed * config.dailyChapters))
return min(this.totalChapterNum, chaptersToUnlock)
} else return this.totalChapterNum
}
fun getRealAuthor() = author.replace(AppPattern.authorRegex, "") fun getRealAuthor() = author.replace(AppPattern.authorRegex, "")
fun getUnreadChapterNum() = max(simulatedTotalChapterNum() - durChapterIndex - 1, 0) fun getUnreadChapterNum() = max(simulatedTotalChapterNum() - durChapterIndex - 1, 0)
@@ -23,8 +23,12 @@ import io.legado.app.utils.isUri
import io.legado.app.utils.toastOnUi import io.legado.app.utils.toastOnUi
import splitties.init.appCtx import splitties.init.appCtx
import java.io.File import java.io.File
import java.time.LocalDate
import java.time.Period.between
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import kotlin.collections.set import kotlin.collections.set
import kotlin.math.max
import kotlin.math.min
val Book.isAudio: Boolean val Book.isAudio: Boolean
@@ -296,6 +300,20 @@ fun Book.getExportFileName(
}.getOrDefault(default) }.getOrDefault(default)
} }
// 根据当前日期计算章节总数
fun Book.simulatedTotalChapterNum(): Int {
return if (config.readSimulating) {
val currentDate = LocalDate.now()
val daysPassed = between(this.config.startDate, currentDate).days + 1
// 计算当前应该解锁到哪一章
val chaptersToUnlock =
max(0, (config.startChapter ?: 0) + (daysPassed * config.dailyChapters))
min(totalChapterNum, chaptersToUnlock)
} else {
totalChapterNum
}
}
fun tryParesExportFileName(jsStr: String): Boolean { fun tryParesExportFileName(jsStr: String): Boolean {
val bindings = SimpleBindings() val bindings = SimpleBindings()
bindings["name"] = "name" bindings["name"] = "name"
@@ -12,6 +12,7 @@ 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.help.book.ContentProcessor import io.legado.app.help.book.ContentProcessor
import io.legado.app.help.book.getBookSource import io.legado.app.help.book.getBookSource
import io.legado.app.help.book.simulatedTotalChapterNum
import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.coroutine.Coroutine
import io.legado.app.service.AudioPlayService import io.legado.app.service.AudioPlayService
import io.legado.app.utils.postEvent import io.legado.app.utils.postEvent
@@ -12,6 +12,7 @@ import io.legado.app.help.AppWebDav
import io.legado.app.help.book.BookHelp import io.legado.app.help.book.BookHelp
import io.legado.app.help.book.ContentProcessor import io.legado.app.help.book.ContentProcessor
import io.legado.app.help.book.isLocal import io.legado.app.help.book.isLocal
import io.legado.app.help.book.simulatedTotalChapterNum
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
import io.legado.app.help.config.ReadBookConfig import io.legado.app.help.config.ReadBookConfig
import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.coroutine.Coroutine
@@ -47,6 +48,7 @@ object ReadBook : CoroutineScope by MainScope() {
var inBookshelf = false var inBookshelf = false
var tocChanged = false var tocChanged = false
var chapterSize = 0 var chapterSize = 0
var simulatedChapterSize = 0
var durChapterIndex = 0 var durChapterIndex = 0
var durChapterPos = 0 var durChapterPos = 0
var isLocalBook = true var isLocalBook = true
@@ -92,6 +94,11 @@ object ReadBook : CoroutineScope by MainScope() {
readRecord.bookName = book.name readRecord.bookName = book.name
readRecord.readTime = appDb.readRecordDao.getReadTime(book.name) ?: 0 readRecord.readTime = appDb.readRecordDao.getReadTime(book.name) ?: 0
chapterSize = appDb.bookChapterDao.getChapterCount(book.bookUrl) chapterSize = appDb.bookChapterDao.getChapterCount(book.bookUrl)
simulatedChapterSize = if (book.config.readSimulating) {
book.simulatedTotalChapterNum()
} else {
chapterSize
}
contentProcessor = ContentProcessor.get(book) contentProcessor = ContentProcessor.get(book)
durChapterIndex = book.durChapterIndex durChapterIndex = book.durChapterIndex
durChapterPos = book.durChapterPos durChapterPos = book.durChapterPos
@@ -112,6 +119,11 @@ object ReadBook : CoroutineScope by MainScope() {
fun upData(book: Book) { fun upData(book: Book) {
ReadBook.book = book ReadBook.book = book
chapterSize = appDb.bookChapterDao.getChapterCount(book.bookUrl) chapterSize = appDb.bookChapterDao.getChapterCount(book.bookUrl)
simulatedChapterSize = if (book.config.readSimulating) {
book.simulatedTotalChapterNum()
} else {
chapterSize
}
if (durChapterIndex != book.durChapterIndex || tocChanged) { if (durChapterIndex != book.durChapterIndex || tocChanged) {
durChapterIndex = book.durChapterIndex durChapterIndex = book.durChapterIndex
durChapterPos = book.durChapterPos durChapterPos = book.durChapterPos
@@ -229,7 +241,7 @@ object ReadBook : CoroutineScope by MainScope() {
} }
fun moveToNextChapter(upContent: Boolean, upContentInPlace: Boolean = true): Boolean { fun moveToNextChapter(upContent: Boolean, upContentInPlace: Boolean = true): Boolean {
if (durChapterIndex < (book?.simulatedTotalChapterNum()?: chapterSize) - 1) { if (durChapterIndex < simulatedChapterSize - 1) {
durChapterPos = 0 durChapterPos = 0
durChapterIndex++ durChapterIndex++
prevTextChapter?.cancelLayout() prevTextChapter?.cancelLayout()
@@ -544,7 +556,7 @@ object ReadBook : CoroutineScope by MainScope() {
val contents = contentProcessor val contents = contentProcessor
.getContent(book, chapter, content, includeTitle = false) .getContent(book, chapter, content, includeTitle = false)
val textChapter = ChapterProvider.getTextChapterAsync( val textChapter = ChapterProvider.getTextChapterAsync(
this@ReadBook, book, chapter, displayTitle, contents, chapterSize this@ReadBook, book, chapter, displayTitle, contents, simulatedChapterSize
) )
when (val offset = chapter.index - durChapterIndex) { when (val offset = chapter.index - durChapterIndex) {
0 -> { 0 -> {
@@ -11,6 +11,7 @@ import io.legado.app.data.entities.rule.TocRule
import io.legado.app.exception.NoStackTraceException import io.legado.app.exception.NoStackTraceException
import io.legado.app.exception.TocEmptyException import io.legado.app.exception.TocEmptyException
import io.legado.app.help.book.ContentProcessor import io.legado.app.help.book.ContentProcessor
import io.legado.app.help.book.simulatedTotalChapterNum
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
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
@@ -24,6 +24,7 @@ import io.legado.app.data.entities.BookSource
import io.legado.app.databinding.ActivityAudioPlayBinding import io.legado.app.databinding.ActivityAudioPlayBinding
import io.legado.app.help.book.isAudio import io.legado.app.help.book.isAudio
import io.legado.app.help.book.removeType import io.legado.app.help.book.removeType
import io.legado.app.help.book.simulatedTotalChapterNum
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.model.AudioPlay import io.legado.app.model.AudioPlay
@@ -25,6 +25,7 @@ import io.legado.app.help.book.isLocal
import io.legado.app.help.book.isSameNameAuthor import io.legado.app.help.book.isSameNameAuthor
import io.legado.app.help.book.isWebFile import io.legado.app.help.book.isWebFile
import io.legado.app.help.book.removeType import io.legado.app.help.book.removeType
import io.legado.app.help.book.simulatedTotalChapterNum
import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.coroutine.Coroutine
import io.legado.app.lib.webdav.ObjectNotFoundException import io.legado.app.lib.webdav.ObjectNotFoundException
import io.legado.app.model.BookCover import io.legado.app.model.BookCover
@@ -251,7 +252,8 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
appDb.bookChapterDao.insert(*it.toTypedArray()) appDb.bookChapterDao.insert(*it.toTypedArray())
if (book.isSameNameAuthor(ReadBook.book)) { if (book.isSameNameAuthor(ReadBook.book)) {
ReadBook.book = book ReadBook.book = book
ReadBook.chapterSize = book.simulatedTotalChapterNum() ReadBook.chapterSize = book.totalChapterNum
ReadBook.simulatedChapterSize = book.simulatedTotalChapterNum()
} }
} }
bookData.postValue(book) bookData.postValue(book)
@@ -22,6 +22,7 @@ import io.legado.app.help.book.ContentProcessor
import io.legado.app.help.book.isLocal import io.legado.app.help.book.isLocal
import io.legado.app.help.book.isLocalModified import io.legado.app.help.book.isLocalModified
import io.legado.app.help.book.removeType import io.legado.app.help.book.removeType
import io.legado.app.help.book.simulatedTotalChapterNum
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.coroutine.Coroutine
import io.legado.app.model.ImageProvider import io.legado.app.model.ImageProvider
@@ -116,8 +117,8 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
ReadBook.loadOrUpContent() ReadBook.loadOrUpContent()
checkLocalBookFileExist(book) checkLocalBookFileExist(book)
} else { } else {
if (ReadBook.durChapterIndex > ReadBook.chapterSize - 1) { if (ReadBook.durChapterIndex > ReadBook.simulatedChapterSize - 1) {
ReadBook.durChapterIndex = ReadBook.chapterSize - 1 ReadBook.durChapterIndex = ReadBook.simulatedChapterSize - 1
} }
ReadBook.loadContent(resetPageOffset = false) ReadBook.loadContent(resetPageOffset = false)
checkLocalBookFileExist(book) checkLocalBookFileExist(book)
@@ -176,6 +177,7 @@ 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
ReadBook.simulatedChapterSize = book.simulatedTotalChapterNum()
ReadBook.upMsg(null) ReadBook.upMsg(null)
ReadBook.loadContent(resetPageOffset = true) ReadBook.loadContent(resetPageOffset = true)
} }
@@ -205,6 +207,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
appDb.bookChapterDao.delByBook(oldBook.bookUrl) appDb.bookChapterDao.delByBook(oldBook.bookUrl)
appDb.bookChapterDao.insert(*cList.toTypedArray()) appDb.bookChapterDao.insert(*cList.toTypedArray())
ReadBook.chapterSize = cList.size ReadBook.chapterSize = cList.size
ReadBook.simulatedChapterSize = book.simulatedTotalChapterNum()
ReadBook.upMsg(null) ReadBook.upMsg(null)
ReadBook.loadContent(resetPageOffset = true) ReadBook.loadContent(resetPageOffset = true)
}.onError { }.onError {
@@ -509,7 +509,7 @@ class ReadMenu @JvmOverloads constructor(
} }
upSeekBar() upSeekBar()
binding.tvPre.isEnabled = ReadBook.durChapterIndex != 0 binding.tvPre.isEnabled = ReadBook.durChapterIndex != 0
binding.tvNext.isEnabled = ReadBook.durChapterIndex != ReadBook.chapterSize - 1 binding.tvNext.isEnabled = ReadBook.durChapterIndex != ReadBook.simulatedChapterSize - 1
} ?: let { } ?: let {
binding.tvChapterName.gone() binding.tvChapterName.gone()
binding.tvChapterUrl.gone() binding.tvChapterUrl.gone()
@@ -527,7 +527,7 @@ class ReadMenu @JvmOverloads constructor(
} }
"chapter" -> { "chapter" -> {
max = ReadBook.chapterSize - 1 max = ReadBook.simulatedChapterSize - 1
progress = ReadBook.durChapterIndex progress = ReadBook.durChapterIndex
} }
} }
@@ -708,8 +708,7 @@ class ReadView(context: Context, attrs: AttributeSet) :
} }
override fun hasNextChapter(): Boolean { override fun hasNextChapter(): Boolean {
return ReadBook.durChapterIndex < ((ReadBook.book?.simulatedTotalChapterNum() return ReadBook.durChapterIndex < ReadBook.simulatedChapterSize - 1
?: ReadBook.chapterSize) - 1)
} }
override fun hasPrevChapter(): Boolean { override fun hasPrevChapter(): Boolean {
@@ -17,6 +17,7 @@ import io.legado.app.data.entities.BookChapter
import io.legado.app.databinding.FragmentChapterListBinding import io.legado.app.databinding.FragmentChapterListBinding
import io.legado.app.help.book.BookHelp import io.legado.app.help.book.BookHelp
import io.legado.app.help.book.isLocal import io.legado.app.help.book.isLocal
import io.legado.app.help.book.simulatedTotalChapterNum
import io.legado.app.lib.theme.bottomBackground import io.legado.app.lib.theme.bottomBackground
import io.legado.app.lib.theme.getPrimaryTextColor import io.legado.app.lib.theme.getPrimaryTextColor
import io.legado.app.ui.widget.recycler.UpLinearLayoutManager import io.legado.app.ui.widget.recycler.UpLinearLayoutManager
@@ -81,7 +82,7 @@ class ChapterListFragment : VMBaseFragment<TocViewModel>(R.layout.fragment_chapt
upChapterList(null) upChapterList(null)
durChapterIndex = book.durChapterIndex durChapterIndex = book.durChapterIndex
binding.tvCurrentChapterInfo.text = binding.tvCurrentChapterInfo.text =
"${book.durChapterTitle}(${book.durChapterIndex + 1}/${book.totalChapterNum})" "${book.durChapterTitle}(${book.durChapterIndex + 1}/${book.simulatedTotalChapterNum()})"
initCacheFileNames(book) initCacheFileNames(book)
} }
} }
@@ -117,12 +118,12 @@ class ChapterListFragment : VMBaseFragment<TocViewModel>(R.layout.fragment_chapt
override fun upChapterList(searchKey: String?) { override fun upChapterList(searchKey: String?) {
lifecycleScope.launch { lifecycleScope.launch {
withContext(IO) { withContext(IO) {
val end = (book?.simulatedTotalChapterNum() ?: Int.MAX_VALUE) - 1
when { when {
searchKey.isNullOrBlank() -> appDb.bookChapterDao.getChapterList( searchKey.isNullOrBlank() ->
viewModel.bookUrl appDb.bookChapterDao.getChapterList(viewModel.bookUrl, 0, end)
).take(book?.simulatedTotalChapterNum() ?: Int.MAX_VALUE)
else -> appDb.bookChapterDao.search(viewModel.bookUrl, searchKey) else -> appDb.bookChapterDao.search(viewModel.bookUrl, searchKey, 0, end)
} }
}.let { }.let {
adapter.setItems(it) adapter.setItems(it)
@@ -18,6 +18,7 @@ import io.legado.app.base.VMBaseActivity
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
import io.legado.app.databinding.ActivityChapterListBinding import io.legado.app.databinding.ActivityChapterListBinding
import io.legado.app.help.book.isLocalTxt import io.legado.app.help.book.isLocalTxt
import io.legado.app.help.book.simulatedTotalChapterNum
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
import io.legado.app.lib.theme.accentColor import io.legado.app.lib.theme.accentColor
import io.legado.app.lib.theme.primaryTextColor import io.legado.app.lib.theme.primaryTextColor
@@ -26,8 +27,12 @@ import io.legado.app.ui.about.AppLogDialog
import io.legado.app.ui.book.toc.rule.TxtTocRuleDialog import io.legado.app.ui.book.toc.rule.TxtTocRuleDialog
import io.legado.app.ui.file.HandleFileContract import io.legado.app.ui.file.HandleFileContract
import io.legado.app.ui.widget.dialog.WaitDialog import io.legado.app.ui.widget.dialog.WaitDialog
import io.legado.app.utils.* import io.legado.app.utils.applyTint
import io.legado.app.utils.gone
import io.legado.app.utils.hideSoftInput
import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
import io.legado.app.utils.visible
/** /**
* 目录 * 目录
@@ -192,7 +197,8 @@ class TocActivity : VMBaseActivity<ActivityChapterListBinding, TocViewModel>(),
ReadBook.book?.let { readBook -> ReadBook.book?.let { readBook ->
if (readBook == book) { if (readBook == book) {
ReadBook.book = book ReadBook.book = book
ReadBook.chapterSize = book.simulatedTotalChapterNum() ReadBook.chapterSize = book.totalChapterNum
ReadBook.simulatedChapterSize = book.simulatedTotalChapterNum()
ReadBook.upMsg(null) ReadBook.upMsg(null)
ReadBook.loadContent(resetPageOffset = true) ReadBook.loadContent(resetPageOffset = true)
} }
@@ -19,6 +19,7 @@ import io.legado.app.help.book.isLocal
import io.legado.app.help.book.isSameNameAuthor import io.legado.app.help.book.isSameNameAuthor
import io.legado.app.help.book.isUpError import io.legado.app.help.book.isUpError
import io.legado.app.help.book.removeType import io.legado.app.help.book.removeType
import io.legado.app.help.book.simulatedTotalChapterNum
import io.legado.app.help.book.sync import io.legado.app.help.book.sync
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
import io.legado.app.model.CacheBook import io.legado.app.model.CacheBook
@@ -163,7 +164,8 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
appDb.bookChapterDao.insert(*toc.toTypedArray()) appDb.bookChapterDao.insert(*toc.toTypedArray())
if (book.isSameNameAuthor(ReadBook.book)) { if (book.isSameNameAuthor(ReadBook.book)) {
ReadBook.book = book ReadBook.book = book
ReadBook.chapterSize = book.simulatedTotalChapterNum() ReadBook.chapterSize = book.totalChapterNum
ReadBook.simulatedChapterSize = book.simulatedTotalChapterNum()
} }
addDownload(source, book) addDownload(source, book)
}.onFailure { }.onFailure {