This commit is contained in:
kunfei 2023-03-02 11:10:34 +08:00
parent 323854f647
commit eb635cae15
6 changed files with 65 additions and 52 deletions

View File

@ -18,6 +18,7 @@ import io.legado.app.lib.webdav.Authorization
import io.legado.app.lib.webdav.WebDav
import io.legado.app.lib.webdav.WebDavException
import io.legado.app.lib.webdav.WebDavFile
import io.legado.app.model.remote.RemoteBookWebDav
import io.legado.app.ui.widget.dialog.WaitDialog
import io.legado.app.utils.*
import kotlinx.coroutines.Dispatchers.IO
@ -78,6 +79,13 @@ object AppWebDav {
}
}
fun getDefaultRemoteBookWebDav(): RemoteBookWebDav {
val rootUrl = "${rootWebDavUrl}books"
val authorization = AppWebDav.authorization
?: throw NoStackTraceException("webDav没有配置")
return RemoteBookWebDav(rootUrl, authorization)
}
suspend fun upConfig() {
kotlin.runCatching {
authorization = null

View File

@ -4,7 +4,6 @@ import android.net.Uri
import io.legado.app.data.entities.Book
abstract class RemoteBookManager {
protected val remoteBookFolder: String = "books"
/**
* 获取书籍列表

View File

@ -5,8 +5,8 @@ import io.legado.app.constant.AppPattern.bookFileRegex
import io.legado.app.constant.BookType
import io.legado.app.data.entities.Book
import io.legado.app.exception.NoStackTraceException
import io.legado.app.help.AppWebDav
import io.legado.app.help.config.AppConfig
import io.legado.app.lib.webdav.Authorization
import io.legado.app.lib.webdav.WebDav
import io.legado.app.lib.webdav.WebDavFile
import io.legado.app.model.localBook.LocalBook
@ -17,9 +17,8 @@ import kotlinx.coroutines.runBlocking
import splitties.init.appCtx
import java.io.File
object RemoteBookWebDav : RemoteBookManager() {
val rootBookUrl get() = "${AppWebDav.rootWebDavUrl}${remoteBookFolder}"
class RemoteBookWebDav(val rootBookUrl: String, val authorization: Authorization) :
RemoteBookManager() {
init {
runBlocking {
@ -28,69 +27,61 @@ object RemoteBookWebDav : RemoteBookManager() {
}
suspend fun initRemoteContext() {
AppWebDav.authorization?.let {
WebDav(rootBookUrl, it).makeAsDir()
}
WebDav(rootBookUrl, authorization).makeAsDir()
}
@Throws(Exception::class)
override suspend fun getRemoteBookList(path: String): MutableList<RemoteBook> {
if (!NetworkUtils.isAvailable()) throw NoStackTraceException("网络不可用")
val remoteBooks = mutableListOf<RemoteBook>()
AppWebDav.authorization?.let {
//读取文件列表
val remoteWebDavFileList: List<WebDavFile> = WebDav(path, it).listFiles()
//转化远程文件信息到本地对象
remoteWebDavFileList.forEach { webDavFile ->
if (webDavFile.isDir || bookFileRegex.matches(webDavFile.displayName)) {
//扩展名符合阅读的格式则认为是书籍
remoteBooks.add(RemoteBook(webDavFile))
}
//读取文件列表
val remoteWebDavFileList: List<WebDavFile> = WebDav(path, authorization).listFiles()
//转化远程文件信息到本地对象
remoteWebDavFileList.forEach { webDavFile ->
if (webDavFile.isDir || bookFileRegex.matches(webDavFile.displayName)) {
//扩展名符合阅读的格式则认为是书籍
remoteBooks.add(RemoteBook(webDavFile))
}
} ?: throw NoStackTraceException("webDav没有配置")
}
return remoteBooks
}
override suspend fun getRemoteBook(path: String): RemoteBook? {
AppWebDav.authorization?.let {
val webDavFile = WebDav(path, it).getWebDavFile()
?: return null
return RemoteBook(webDavFile)
} ?: throw NoStackTraceException("webDav没有配置")
if (!NetworkUtils.isAvailable()) throw NoStackTraceException("网络不可用")
val webDavFile = WebDav(path, authorization).getWebDavFile()
?: return null
return RemoteBook(webDavFile)
}
override suspend fun downloadRemoteBook(remoteBook: RemoteBook): Uri {
AppConfig.defaultBookTreeUri
?: throw NoStackTraceException("没有设置书籍保存位置!")
return AppWebDav.authorization?.let {
val webdav = WebDav(remoteBook.path, it)
webdav.downloadInputStream().let { inputStream ->
LocalBook.saveBookFile(inputStream, remoteBook.filename)
}
} ?: throw NoStackTraceException("webDav没有配置")
if (!NetworkUtils.isAvailable()) throw NoStackTraceException("网络不可用")
val webdav = WebDav(remoteBook.path, authorization)
return webdav.downloadInputStream().let { inputStream ->
LocalBook.saveBookFile(inputStream, remoteBook.filename)
}
}
override suspend fun upload(book: Book) {
if (!NetworkUtils.isAvailable()) throw NoStackTraceException("网络不可用")
val localBookUri = Uri.parse(book.bookUrl)
val putUrl = "$rootBookUrl${File.separator}${book.originName}"
AppWebDav.authorization?.let {
if (localBookUri.isContentScheme()) {
WebDav(putUrl, it).upload(
byteArray = localBookUri.readBytes(appCtx),
contentType = "application/octet-stream"
)
} else {
WebDav(putUrl, it).upload(localBookUri.path!!)
}
} ?: throw NoStackTraceException("webDav没有配置")
if (localBookUri.isContentScheme()) {
WebDav(putUrl, authorization).upload(
byteArray = localBookUri.readBytes(appCtx),
contentType = "application/octet-stream"
)
} else {
WebDav(putUrl, authorization).upload(localBookUri.path!!)
}
book.origin = BookType.webDavTag + putUrl
book.save()
}
override suspend fun delete(remoteBookUrl: String) {
AppWebDav.authorization?.let {
WebDav(remoteBookUrl, it).delete()
} ?: throw NoStackTraceException("webDav没有配置")
if (!NetworkUtils.isAvailable()) throw NoStackTraceException("网络不可用")
WebDav(remoteBookUrl, authorization).delete()
}
}

View File

@ -4,6 +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.exception.NoStackTraceException
import io.legado.app.help.AppWebDav
import io.legado.app.model.localBook.LocalBook
import io.legado.app.model.remote.RemoteBook
import io.legado.app.model.remote.RemoteBookWebDav
@ -70,17 +72,26 @@ class RemoteBookViewModel(application: Application) : BaseViewModel(application)
}
}.flowOn(Dispatchers.IO)
private var remoteBookWebDav: RemoteBookWebDav? = null
init {
execute {
RemoteBookWebDav.initRemoteContext()
val rootUrl = "${AppWebDav.rootWebDavUrl}books"
val authorization = AppWebDav.authorization
?: throw NoStackTraceException("webDav没有配置")
remoteBookWebDav = RemoteBookWebDav(rootUrl, authorization)
}.onError {
context.toastOnUi("初始化webDav出错:${it.localizedMessage}")
}
}
fun loadRemoteBookList(path: String?, loadCallback: (loading: Boolean) -> Unit) {
execute {
val bookWebDav = remoteBookWebDav
?: throw NoStackTraceException("没有配置webDav")
dataCallback?.clear()
val url = path ?: RemoteBookWebDav.rootBookUrl
val bookList = RemoteBookWebDav.getRemoteBookList(url)
val url = path ?: bookWebDav.rootBookUrl
val bookList = bookWebDav.getRemoteBookList(url)
dataCallback?.setItems(bookList)
}.onError {
AppLog.put("获取webDav书籍出错\n${it.localizedMessage}", it)
@ -95,7 +106,9 @@ class RemoteBookViewModel(application: Application) : BaseViewModel(application)
fun addToBookshelf(remoteBooks: HashSet<RemoteBook>, finally: () -> Unit) {
execute {
remoteBooks.forEach { remoteBook ->
val downloadBookPath = RemoteBookWebDav.downloadRemoteBook(remoteBook)
val bookWebDav = remoteBookWebDav
?: throw NoStackTraceException("没有配置webDav")
val downloadBookPath = bookWebDav.downloadRemoteBook(remoteBook)
downloadBookPath.let {
val localBook = LocalBook.importFile(it)
localBook.origin = BookType.webDavTag + remoteBook.path

View File

@ -19,6 +19,7 @@ import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.BookSource
import io.legado.app.databinding.ActivityBookInfoBinding
import io.legado.app.databinding.DialogEditTextBinding
import io.legado.app.help.AppWebDav
import io.legado.app.help.book.isAudio
import io.legado.app.help.book.isLocal
import io.legado.app.help.book.isLocalTxt
@ -28,7 +29,6 @@ import io.legado.app.lib.theme.backgroundColor
import io.legado.app.lib.theme.bottomBackground
import io.legado.app.lib.theme.getPrimaryTextColor
import io.legado.app.model.BookCover
import io.legado.app.model.remote.RemoteBookWebDav
import io.legado.app.ui.about.AppLogDialog
import io.legado.app.ui.association.ImportOnLineBookFileDialog
import io.legado.app.ui.book.audio.AudioPlayActivity
@ -210,7 +210,8 @@ class BookInfoActivity :
waitDialog.setText("上传中.....")
waitDialog.show()
try {
RemoteBookWebDav.upload(it)
AppWebDav.getDefaultRemoteBookWebDav()
.upload(it)
//更新书籍最后更新时间,使之比远程书籍的时间新
it.lastCheckTime = System.currentTimeMillis()
viewModel.saveBook(it)
@ -246,7 +247,7 @@ class BookInfoActivity :
private fun showCover(book: Book) {
binding.ivCover.load(book.getDisplayCover(), book.name, book.author, false, book.origin)
if(!AppConfig.isEInkMode) {
if (!AppConfig.isEInkMode) {
BookCover.loadBlur(this, book.getDisplayCover())
.into(binding.bgBook)
}

View File

@ -15,13 +15,13 @@ import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.BookSource
import io.legado.app.exception.NoStackTraceException
import io.legado.app.help.AppWebDav
import io.legado.app.help.book.*
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.lib.webdav.ObjectNotFoundException
import io.legado.app.model.BookCover
import io.legado.app.model.ReadBook
import io.legado.app.model.localBook.LocalBook
import io.legado.app.model.remote.RemoteBookWebDav
import io.legado.app.model.webBook.WebBook
import io.legado.app.utils.isContentScheme
import io.legado.app.utils.postEvent
@ -114,11 +114,12 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
if (book.isLocal) {
book.tocUrl = ""
book.getRemoteUrl()?.let {
val remoteBook = RemoteBookWebDav.getRemoteBook(it)
val bookWebDav = AppWebDav.getDefaultRemoteBookWebDav()
val remoteBook = bookWebDav.getRemoteBook(it)
if (remoteBook == null) {
book.origin = BookType.localTag
} else if (remoteBook.lastModify > book.lastCheckTime) {
val uri = RemoteBookWebDav.downloadRemoteBook(remoteBook)
val uri = bookWebDav.downloadRemoteBook(remoteBook)
book.bookUrl = if (uri.isContentScheme()) uri.toString() else uri.path!!
book.lastCheckTime = remoteBook.lastModify
}