Kaynağa Gözat

更新时检测webDav书籍是否比本地新,自动重新下载

kunfei 4 yıl önce
ebeveyn
işleme
43295cf7a3

+ 0 - 19
app/src/main/java/io/legado/app/data/entities/RemoteBook.kt

@@ -1,19 +0,0 @@
-package io.legado.app.data.entities
-
-import com.android.tools.r8.Keep
-
-@Keep
-data class RemoteBook(
-    val filename: String,
-    val path: String,
-    val size: Long,
-    val contentType: String,
-    val lastModify: Long,
-    var isOnBookShelf: Boolean = false
-) {
-
-    val isDir by lazy {
-        contentType == "folder"
-    }
-
-}

+ 7 - 0
app/src/main/java/io/legado/app/help/book/BookExtensions.kt

@@ -44,6 +44,13 @@ val Book.isOnLineTxt: Boolean
         return !isLocal && type and BookType.text > 0
     }
 
+fun Book.getRemoteUrl(): String? {
+    if (origin.startsWith(BookType.webDavTag)) {
+        return origin.substring(8)
+    }
+    return null
+}
+
 fun Book.upType() {
     if (type < 8) {
         type = when (type) {

+ 4 - 5
app/src/main/java/io/legado/app/lib/webdav/WebDav.kt

@@ -92,12 +92,11 @@ open class WebDav(val path: String, val authorization: Authorization) {
     /**
      * 获取当前url文件信息
      */
+    @Throws(WebDavException::class)
     suspend fun getWebDavFile(): WebDavFile? {
-        return kotlin.runCatching {
-            propFindResponse(depth = 0)?.let {
-                return parseBody(it).firstOrNull()
-            }
-        }.getOrNull()
+        return propFindResponse(depth = 0)?.let {
+            parseBody(it).firstOrNull()
+        }
     }
 
     /**

+ 31 - 0
app/src/main/java/io/legado/app/model/remote/RemoteBook.kt

@@ -0,0 +1,31 @@
+package io.legado.app.model.remote
+
+import com.android.tools.r8.Keep
+import io.legado.app.lib.webdav.WebDavFile
+import io.legado.app.model.localBook.LocalBook
+
+@Keep
+data class RemoteBook(
+    val filename: String,
+    val path: String,
+    val size: Long,
+    val lastModify: Long,
+    var contentType: String = "folder",
+    var isOnBookShelf: Boolean = false
+) {
+
+    val isDir get() = contentType == "folder"
+
+    constructor(webDavFile: WebDavFile) : this(
+        webDavFile.displayName,
+        webDavFile.path,
+        webDavFile.size,
+        webDavFile.lastModify
+    ) {
+        if (!webDavFile.isDir) {
+            contentType = webDavFile.displayName.substringAfterLast(".")
+            isOnBookShelf = LocalBook.isOnBookShelf(webDavFile.displayName)
+        }
+    }
+
+}

+ 12 - 6
app/src/main/java/io/legado/app/model/remote/RemoteBookManager.kt

@@ -2,7 +2,6 @@ package io.legado.app.model.remote
 
 import android.net.Uri
 import io.legado.app.data.entities.Book
-import io.legado.app.data.entities.RemoteBook
 
 abstract class RemoteBookManager {
     protected val remoteBookFolder: String = "books"
@@ -15,6 +14,18 @@ abstract class RemoteBookManager {
     @Throws(Exception::class)
     abstract suspend fun getRemoteBookList(path: String): MutableList<RemoteBook>
 
+    /**
+     * 根据书籍地址获取书籍信息
+     */
+    @Throws(Exception::class)
+    abstract suspend fun getRemoteBook(path: String): RemoteBook
+
+    /**
+     * @return Uri:下载到本地的路径
+     */
+    @Throws(Exception::class)
+    abstract suspend fun downloadRemoteBook(remoteBook: RemoteBook): Uri
+
     /**
      * 上传书籍
      */
@@ -27,9 +38,4 @@ abstract class RemoteBookManager {
     @Throws(Exception::class)
     abstract suspend fun delete(remoteBookUrl: String)
 
-    /**
-     * @return Uri:下载到本地的路径
-     */
-    @Throws(Exception::class)
-    abstract suspend fun getRemoteBook(remoteBook: RemoteBook): Uri
 }

+ 11 - 22
app/src/main/java/io/legado/app/model/remote/RemoteBookWebDav.kt

@@ -4,7 +4,6 @@ import android.net.Uri
 import io.legado.app.constant.AppPattern.bookFileRegex
 import io.legado.app.constant.BookType
 import io.legado.app.data.entities.Book
-import io.legado.app.data.entities.RemoteBook
 import io.legado.app.exception.NoStackTraceException
 import io.legado.app.help.AppWebDav
 import io.legado.app.lib.webdav.WebDav
@@ -40,34 +39,24 @@ object RemoteBookWebDav : RemoteBookManager() {
             val remoteWebDavFileList: List<WebDavFile> = WebDav(path, it).listFiles()
             //转化远程文件信息到本地对象
             remoteWebDavFileList.forEach { webDavFile ->
-                if (webDavFile.isDir) {
-                    remoteBooks.add(
-                        RemoteBook(
-                            webDavFile.displayName, webDavFile.path, webDavFile.size,
-                            "folder", webDavFile.lastModify
-                        )
-                    )
-                } else {
-                    //分割后缀
-                    val fileExtension = webDavFile.displayName.substringAfterLast(".")
-
+                if (webDavFile.isDir || bookFileRegex.matches(webDavFile.displayName)) {
                     //扩展名符合阅读的格式则认为是书籍
-                    if (bookFileRegex.matches(webDavFile.displayName)) {
-                        val isOnBookShelf = LocalBook.isOnBookShelf(webDavFile.displayName)
-                        remoteBooks.add(
-                            RemoteBook(
-                                webDavFile.displayName, webDavFile.path, webDavFile.size,
-                                fileExtension, webDavFile.lastModify, isOnBookShelf
-                            )
-                        )
-                    }
+                    remoteBooks.add(RemoteBook(webDavFile))
                 }
             }
         } ?: throw NoStackTraceException("webDav没有配置")
         return remoteBooks
     }
 
-    override suspend fun getRemoteBook(remoteBook: RemoteBook): Uri {
+    override suspend fun getRemoteBook(path: String): RemoteBook {
+        AppWebDav.authorization?.let {
+            val webDavFile = WebDav(path, it).getWebDavFile()
+                ?: throw NoStackTraceException("远程书籍不存在")
+            return RemoteBook(webDavFile)
+        } ?: throw NoStackTraceException("webDav没有配置")
+    }
+
+    override suspend fun downloadRemoteBook(remoteBook: RemoteBook): Uri {
         return AppWebDav.authorization?.let {
             val webdav = WebDav(remoteBook.path, it)
             webdav.downloadInputStream().let { inputStream ->

+ 2 - 5
app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt

@@ -81,7 +81,7 @@ class BookInfoActivity :
     private val readBookResult = registerForActivityResult(
         ActivityResultContracts.StartActivityForResult()
     ) {
-        viewModel.refreshData(intent)
+        viewModel.upBook(intent)
         if (it.resultCode == RESULT_OK) {
             viewModel.inBookshelf = true
             upTvBookshelf()
@@ -162,10 +162,7 @@ class BookInfoActivity :
             R.id.menu_refresh -> {
                 upLoading(true)
                 viewModel.bookData.value?.let {
-                    if (it.isLocal) {
-                        it.tocUrl = ""
-                    }
-                    viewModel.loadBookInfo(it, false)
+                    viewModel.refreshBook(it)
                 }
             }
             R.id.menu_login -> viewModel.bookSource?.let {

+ 8 - 1
app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt

@@ -62,7 +62,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
         }
     }
 
-    fun refreshData(intent: Intent) {
+    fun upBook(intent: Intent) {
         execute {
             val name = intent.getStringExtra("name") ?: ""
             val author = intent.getStringExtra("author") ?: ""
@@ -107,6 +107,13 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
         }
     }
 
+    fun refreshBook(book: Book) {
+        if (book.isLocal) {
+            book.tocUrl = ""
+        }
+        loadBookInfo(book, false)
+    }
+
     fun loadBookInfo(
         book: Book,
         canReName: Boolean = true,

+ 1 - 1
app/src/main/java/io/legado/app/ui/book/remote/RemoteBookActivity.kt

@@ -10,9 +10,9 @@ import androidx.core.view.isGone
 import androidx.recyclerview.widget.LinearLayoutManager
 import io.legado.app.R
 import io.legado.app.base.VMBaseActivity
-import io.legado.app.data.entities.RemoteBook
 import io.legado.app.databinding.ActivityImportBookBinding
 import io.legado.app.lib.theme.backgroundColor
+import io.legado.app.model.remote.RemoteBook
 import io.legado.app.ui.about.AppLogDialog
 import io.legado.app.ui.widget.SelectActionBar
 import io.legado.app.ui.widget.dialog.WaitDialog

+ 1 - 1
app/src/main/java/io/legado/app/ui/book/remote/RemoteBookAdapter.kt

@@ -7,8 +7,8 @@ import io.legado.app.R
 import io.legado.app.base.adapter.ItemViewHolder
 import io.legado.app.base.adapter.RecyclerAdapter
 import io.legado.app.constant.AppConst
-import io.legado.app.data.entities.RemoteBook
 import io.legado.app.databinding.ItemImportBookBinding
+import io.legado.app.model.remote.RemoteBook
 import io.legado.app.utils.ConvertUtils
 import io.legado.app.utils.gone
 import io.legado.app.utils.invisible

+ 2 - 2
app/src/main/java/io/legado/app/ui/book/remote/RemoteBookViewModel.kt

@@ -4,8 +4,8 @@ import android.app.Application
 import io.legado.app.base.BaseViewModel
 import io.legado.app.constant.AppLog
 import io.legado.app.constant.BookType
-import io.legado.app.data.entities.RemoteBook
 import io.legado.app.model.localBook.LocalBook
+import io.legado.app.model.remote.RemoteBook
 import io.legado.app.model.remote.RemoteBookWebDav
 import io.legado.app.utils.toastOnUi
 import kotlinx.coroutines.Dispatchers
@@ -95,7 +95,7 @@ class RemoteBookViewModel(application: Application) : BaseViewModel(application)
     fun addToBookshelf(remoteBooks: HashSet<RemoteBook>, finally: () -> Unit) {
         execute {
             remoteBooks.forEach { remoteBook ->
-                val downloadBookPath = RemoteBookWebDav.getRemoteBook(remoteBook)
+                val downloadBookPath = RemoteBookWebDav.downloadRemoteBook(remoteBook)
                 downloadBookPath.let {
                     val localBook = LocalBook.importFile(it)
                     localBook.origin = BookType.webDavTag + remoteBook.path