diff --git a/app/src/main/java/io/legado/app/constant/IntentAction.kt b/app/src/main/java/io/legado/app/constant/IntentAction.kt index 6e91cf97e..e4ec2d265 100644 --- a/app/src/main/java/io/legado/app/constant/IntentAction.kt +++ b/app/src/main/java/io/legado/app/constant/IntentAction.kt @@ -1,5 +1,6 @@ package io.legado.app.constant +@Suppress("ConstPropertyName") object IntentAction { const val start = "start" const val play = "play" diff --git a/app/src/main/java/io/legado/app/constant/NotificationId.kt b/app/src/main/java/io/legado/app/constant/NotificationId.kt index 33c0be044..377e3c13e 100644 --- a/app/src/main/java/io/legado/app/constant/NotificationId.kt +++ b/app/src/main/java/io/legado/app/constant/NotificationId.kt @@ -3,6 +3,7 @@ package io.legado.app.constant /** * 通知ID不能重复,统一规划通知ID */ +@Suppress("ConstPropertyName") object NotificationId { const val ReadAloudService = 101 diff --git a/app/src/main/java/io/legado/app/data/entities/Book.kt b/app/src/main/java/io/legado/app/data/entities/Book.kt index 03a043f59..2ce1909b8 100644 --- a/app/src/main/java/io/legado/app/data/entities/Book.kt +++ b/app/src/main/java/io/legado/app/data/entities/Book.kt @@ -1,12 +1,22 @@ package io.legado.app.data.entities import android.os.Parcelable -import androidx.room.* +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.Ignore +import androidx.room.Index +import androidx.room.PrimaryKey +import androidx.room.TypeConverter +import androidx.room.TypeConverters import io.legado.app.constant.AppPattern import io.legado.app.constant.BookType import io.legado.app.constant.PageAnim import io.legado.app.data.appDb -import io.legado.app.help.book.* +import io.legado.app.help.book.BookHelp +import io.legado.app.help.book.ContentProcessor +import io.legado.app.help.book.isEpub +import io.legado.app.help.book.isImage +import io.legado.app.help.book.isPdf import io.legado.app.help.config.AppConfig import io.legado.app.help.config.ReadBookConfig import io.legado.app.model.ReadBook @@ -144,6 +154,10 @@ data class Book( @IgnoredOnParcel private var folderName: String? = null + @get:Ignore + @IgnoredOnParcel + val lastChapterIndex get() = totalChapterNum - 1 + fun getRealAuthor() = author.replace(AppPattern.authorRegex, "") fun getUnreadChapterNum() = max(totalChapterNum - durChapterIndex - 1, 0) diff --git a/app/src/main/java/io/legado/app/service/CacheBookService.kt b/app/src/main/java/io/legado/app/service/CacheBookService.kt index e646d0683..7dcb9c278 100644 --- a/app/src/main/java/io/legado/app/service/CacheBookService.kt +++ b/app/src/main/java/io/legado/app/service/CacheBookService.kt @@ -103,30 +103,34 @@ class CacheBookService : BaseService() { execute { val cacheBook = CacheBook.getOrCreate(bookUrl) ?: return@execute val chapterCount = appDb.bookChapterDao.getChapterCount(bookUrl) + val book = cacheBook.book if (chapterCount == 0) { - val name = cacheBook.book.name - if (cacheBook.book.tocUrl.isEmpty()) { + val name = book.name + if (book.tocUrl.isEmpty()) { kotlin.runCatching { - WebBook.getBookInfoAwait(cacheBook.bookSource, cacheBook.book) + WebBook.getBookInfoAwait(cacheBook.bookSource, book) }.onFailure { val msg = "《$name》目录为空且加载详情页失败\n${it.localizedMessage}" AppLog.put(msg, it, true) return@execute } } - WebBook.getChapterListAwait(cacheBook.bookSource, cacheBook.book).onFailure { - cacheBook.book.totalChapterNum = 0 + WebBook.getChapterListAwait(cacheBook.bookSource, book).onFailure { + if (book.totalChapterNum > 0) { + book.totalChapterNum = 0 + book.save() + } AppLog.put("《$name》目录为空且加载目录失败\n${it.localizedMessage}", it, true) return@execute }.getOrNull()?.let { toc -> appDb.bookChapterDao.insert(*toc.toTypedArray()) } - cacheBook.book.save() + book.save() } - val end2 = if (end == 0) { - appDb.bookChapterDao.getChapterCount(bookUrl) + val end2 = if (end < 0) { + book.lastChapterIndex } else { - end + min(end, book.lastChapterIndex) } cacheBook.addDownload(start, end2) notificationContent = CacheBook.downloadSummary diff --git a/app/src/main/java/io/legado/app/service/ExportBookService.kt b/app/src/main/java/io/legado/app/service/ExportBookService.kt index 13f76073e..66299cc70 100644 --- a/app/src/main/java/io/legado/app/service/ExportBookService.kt +++ b/app/src/main/java/io/legado/app/service/ExportBookService.kt @@ -29,8 +29,10 @@ import io.legado.app.help.AppWebDav import io.legado.app.help.book.BookHelp import io.legado.app.help.book.ContentProcessor import io.legado.app.help.book.getExportFileName +import io.legado.app.help.book.isLocal import io.legado.app.help.config.AppConfig import io.legado.app.help.coroutine.OrderCoroutine +import io.legado.app.model.localBook.LocalBook import io.legado.app.ui.book.cache.CacheActivity import io.legado.app.utils.DocumentUtils import io.legado.app.utils.FileUtils @@ -177,6 +179,7 @@ class ExportBookService : BaseService() { val book = appDb.bookDao.getBook(bookUrl) try { book ?: throw NoStackTraceException("获取${bookUrl}书籍出错") + refreshChapterList(book) notificationContentText = getString( R.string.export_book_notification_content, book.name, @@ -207,6 +210,22 @@ class ExportBookService : BaseService() { } } + private fun refreshChapterList(book: Book) { + if (!book.isLocal) { + return + } + if (LocalBook.getLastModified(book).getOrDefault(0L) < book.latestChapterTime) { + return + } + kotlin.runCatching { + LocalBook.getChapterList(book) + }.onSuccess { + book.latestChapterTime = System.currentTimeMillis() + appDb.bookChapterDao.delByBook(book.bookUrl) + appDb.bookChapterDao.insert(*it.toTypedArray()) + } + } + private data class SrcData( val chapterTitle: String, val index: Int, diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt index a2b0c4573..a777ddd44 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt @@ -34,13 +34,27 @@ import io.legado.app.model.CacheBook import io.legado.app.service.ExportBookService import io.legado.app.ui.about.AppLogDialog import io.legado.app.ui.file.HandleFileContract -import io.legado.app.utils.* +import io.legado.app.utils.ACache +import io.legado.app.utils.FileDoc +import io.legado.app.utils.applyTint +import io.legado.app.utils.checkWrite +import io.legado.app.utils.cnCompare +import io.legado.app.utils.enableCustomExport +import io.legado.app.utils.isContentScheme +import io.legado.app.utils.observeEvent +import io.legado.app.utils.parseToUri +import io.legado.app.utils.showDialogFragment +import io.legado.app.utils.startService +import io.legado.app.utils.toastOnUi +import io.legado.app.utils.verificationField import io.legado.app.utils.viewbindingdelegate.viewBinding import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Job -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.conflate +import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import kotlin.math.max /** * cache/download 缓存界面 @@ -146,7 +160,7 @@ class CacheActivity : VMBaseActivity() this@CacheActivity, book, book.durChapterIndex, - book.totalChapterNum + book.lastChapterIndex ) } } else { @@ -198,6 +212,10 @@ class CacheActivity : VMBaseActivity() } 3 -> booksDownload.sortedBy { it.order } + 4 -> booksDownload.sortedByDescending { + max(it.latestChapterTime, it.durChapterTime) + } + else -> booksDownload.sortedByDescending { it.durChapterTime } } }.conflate().collect { books -> diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt index 320f1af2f..f6e947010 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt @@ -71,10 +71,10 @@ class CacheAdapter(context: Context, private val callBack: CallBack) : if (!it.isStop()) { CacheBook.remove(context, book.bookUrl) } else { - CacheBook.start(context, book, 0, book.totalChapterNum) + CacheBook.start(context, book, 0, book.lastChapterIndex) } } ?: let { - CacheBook.start(context, book, 0, book.totalChapterNum) + CacheBook.start(context, book, 0, book.lastChapterIndex) } } } diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt index 25ae5abf9..2453879c0 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt @@ -10,13 +10,6 @@ import io.legado.app.help.book.isLocal import io.legado.app.help.coroutine.Coroutine import io.legado.app.utils.sendValue import kotlinx.coroutines.ensureActive -import kotlin.collections.HashSet -import kotlin.collections.List -import kotlin.collections.contains -import kotlin.collections.forEach -import kotlin.collections.hashMapOf -import kotlin.collections.hashSetOf -import kotlin.collections.isNotEmpty import kotlin.collections.set @@ -34,7 +27,9 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { val chapterCaches = hashSetOf() val cacheNames = BookHelp.getChapterFiles(book) if (cacheNames.isNotEmpty()) { - appDb.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter -> + appDb.bookChapterDao.getChapterList(book.bookUrl).also { + book.totalChapterNum = it.size + }.forEach { chapter -> if (cacheNames.contains(chapter.getFileName()) || chapter.isVolume) { chapterCaches.add(chapter.url) } diff --git a/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageActivity.kt b/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageActivity.kt index f70717a02..0d85ed18f 100644 --- a/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageActivity.kt @@ -39,7 +39,15 @@ import io.legado.app.ui.widget.dialog.WaitDialog import io.legado.app.ui.widget.recycler.DragSelectTouchHelper import io.legado.app.ui.widget.recycler.ItemTouchCallback import io.legado.app.ui.widget.recycler.VerticalDivider -import io.legado.app.utils.* +import io.legado.app.utils.applyTint +import io.legado.app.utils.cnCompare +import io.legado.app.utils.dpToPx +import io.legado.app.utils.hideSoftInput +import io.legado.app.utils.isAbsUrl +import io.legado.app.utils.sendToClip +import io.legado.app.utils.setEdgeEffectColor +import io.legado.app.utils.showDialogFragment +import io.legado.app.utils.startActivity import io.legado.app.utils.viewbindingdelegate.viewBinding import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Job @@ -308,6 +316,7 @@ class BookshelfManageActivity : R.id.menu_add_to_group -> selectGroup(addToGroupRequestCode, 0) R.id.menu_change_source -> showDialogFragment() + R.id.menu_clear_cache -> viewModel.clearCache(adapter.selection) R.id.menu_check_selected_interval -> adapter.checkSelectedInterval() } return false diff --git a/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageViewModel.kt b/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageViewModel.kt index 294d40006..8a74fed8c 100644 --- a/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageViewModel.kt @@ -2,12 +2,14 @@ package io.legado.app.ui.book.manage import android.app.Application import androidx.lifecycle.MutableLiveData +import io.legado.app.R import io.legado.app.base.BaseViewModel import io.legado.app.constant.AppLog import io.legado.app.constant.BookType import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookSource +import io.legado.app.help.book.BookHelp import io.legado.app.help.book.isLocal import io.legado.app.help.book.removeType import io.legado.app.help.config.AppConfig @@ -108,4 +110,14 @@ class BookshelfManageViewModel(application: Application) : BaseViewModel(applica } } + fun clearCache(books: List) { + execute { + books.forEach { + BookHelp.clearCache(it) + } + }.onSuccess { + context.toastOnUi(R.string.clear_cache_success) + } + } + } \ No newline at end of file diff --git a/app/src/main/res/menu/bookshelf_menage_sel.xml b/app/src/main/res/menu/bookshelf_menage_sel.xml index 859fdabbc..290f38fd9 100644 --- a/app/src/main/res/menu/bookshelf_menage_sel.xml +++ b/app/src/main/res/menu/bookshelf_menage_sel.xml @@ -21,6 +21,10 @@ android:id="@+id/menu_change_source" android:title="@string/change_source_batch" /> + +