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

pull/2380/head
kunfei 2 years ago
parent ed8d88ffd9
commit 4c53700bb1
  1. 19
      app/src/main/java/io/legado/app/data/entities/RemoteBook.kt
  2. 7
      app/src/main/java/io/legado/app/help/book/BookExtensions.kt
  3. 9
      app/src/main/java/io/legado/app/lib/webdav/WebDav.kt
  4. 31
      app/src/main/java/io/legado/app/model/remote/RemoteBook.kt
  5. 18
      app/src/main/java/io/legado/app/model/remote/RemoteBookManager.kt
  6. 33
      app/src/main/java/io/legado/app/model/remote/RemoteBookWebDav.kt
  7. 7
      app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt
  8. 9
      app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt
  9. 2
      app/src/main/java/io/legado/app/ui/book/remote/RemoteBookActivity.kt
  10. 2
      app/src/main/java/io/legado/app/ui/book/remote/RemoteBookAdapter.kt
  11. 4
      app/src/main/java/io/legado/app/ui/book/remote/RemoteBookViewModel.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"
}
}

@ -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) {

@ -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()
}
}
/**

@ -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)
}
}
}

@ -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
}

@ -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 ->

@ -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 {

@ -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,

@ -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

@ -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

@ -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

Loading…
Cancel
Save