Horis 2 lat temu
rodzic
commit
24d487c493

+ 1 - 0
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"

+ 1 - 0
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

+ 16 - 2
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)

+ 13 - 9
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

+ 19 - 0
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,

+ 21 - 3
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<ActivityCacheBookBinding, CacheViewModel>()
                             this@CacheActivity,
                             book,
                             book.durChapterIndex,
-                            book.totalChapterNum
+                            book.lastChapterIndex
                         )
                     }
                 } else {
@@ -198,6 +212,10 @@ class CacheActivity : VMBaseActivity<ActivityCacheBookBinding, CacheViewModel>()
                     }
 
                     3 -> booksDownload.sortedBy { it.order }
+                    4 -> booksDownload.sortedByDescending {
+                        max(it.latestChapterTime, it.durChapterTime)
+                    }
+
                     else -> booksDownload.sortedByDescending { it.durChapterTime }
                 }
             }.conflate().collect { books ->

+ 2 - 2
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)
                     }
                 }
             }

+ 3 - 8
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<String>()
                     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)
                             }

+ 10 - 1
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<SourcePickerDialog>()
+            R.id.menu_clear_cache -> viewModel.clearCache(adapter.selection)
             R.id.menu_check_selected_interval -> adapter.checkSelectedInterval()
         }
         return false

+ 12 - 0
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<Book>) {
+        execute {
+            books.forEach {
+                BookHelp.clearCache(it)
+            }
+        }.onSuccess {
+            context.toastOnUi(R.string.clear_cache_success)
+        }
+    }
+
 }

+ 4 - 0
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" />
 
+    <item
+        android:id="@+id/menu_clear_cache"
+        android:title="@string/clear_cache" />
+
     <item
         android:id="@+id/menu_check_selected_interval"
         android:title="@string/check_selected_interval" />