优化
This commit is contained in:
@@ -18,6 +18,7 @@ import io.legado.app.lib.webdav.Authorization
|
|||||||
import io.legado.app.lib.webdav.WebDav
|
import io.legado.app.lib.webdav.WebDav
|
||||||
import io.legado.app.lib.webdav.WebDavException
|
import io.legado.app.lib.webdav.WebDavException
|
||||||
import io.legado.app.lib.webdav.WebDavFile
|
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.ui.widget.dialog.WaitDialog
|
||||||
import io.legado.app.utils.*
|
import io.legado.app.utils.*
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
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() {
|
suspend fun upConfig() {
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
authorization = null
|
authorization = null
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import android.net.Uri
|
|||||||
import io.legado.app.data.entities.Book
|
import io.legado.app.data.entities.Book
|
||||||
|
|
||||||
abstract class RemoteBookManager {
|
abstract class RemoteBookManager {
|
||||||
protected val remoteBookFolder: String = "books"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取书籍列表
|
* 获取书籍列表
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import io.legado.app.constant.AppPattern.bookFileRegex
|
|||||||
import io.legado.app.constant.BookType
|
import io.legado.app.constant.BookType
|
||||||
import io.legado.app.data.entities.Book
|
import io.legado.app.data.entities.Book
|
||||||
import io.legado.app.exception.NoStackTraceException
|
import io.legado.app.exception.NoStackTraceException
|
||||||
import io.legado.app.help.AppWebDav
|
|
||||||
import io.legado.app.help.config.AppConfig
|
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.WebDav
|
||||||
import io.legado.app.lib.webdav.WebDavFile
|
import io.legado.app.lib.webdav.WebDavFile
|
||||||
import io.legado.app.model.localBook.LocalBook
|
import io.legado.app.model.localBook.LocalBook
|
||||||
@@ -17,9 +17,8 @@ import kotlinx.coroutines.runBlocking
|
|||||||
import splitties.init.appCtx
|
import splitties.init.appCtx
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
object RemoteBookWebDav : RemoteBookManager() {
|
class RemoteBookWebDav(val rootBookUrl: String, val authorization: Authorization) :
|
||||||
|
RemoteBookManager() {
|
||||||
val rootBookUrl get() = "${AppWebDav.rootWebDavUrl}${remoteBookFolder}"
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
@@ -28,69 +27,61 @@ object RemoteBookWebDav : RemoteBookManager() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun initRemoteContext() {
|
suspend fun initRemoteContext() {
|
||||||
AppWebDav.authorization?.let {
|
WebDav(rootBookUrl, authorization).makeAsDir()
|
||||||
WebDav(rootBookUrl, it).makeAsDir()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
override suspend fun getRemoteBookList(path: String): MutableList<RemoteBook> {
|
override suspend fun getRemoteBookList(path: String): MutableList<RemoteBook> {
|
||||||
|
if (!NetworkUtils.isAvailable()) throw NoStackTraceException("网络不可用")
|
||||||
val remoteBooks = mutableListOf<RemoteBook>()
|
val remoteBooks = mutableListOf<RemoteBook>()
|
||||||
AppWebDav.authorization?.let {
|
//读取文件列表
|
||||||
//读取文件列表
|
val remoteWebDavFileList: List<WebDavFile> = WebDav(path, authorization).listFiles()
|
||||||
val remoteWebDavFileList: List<WebDavFile> = WebDav(path, it).listFiles()
|
//转化远程文件信息到本地对象
|
||||||
//转化远程文件信息到本地对象
|
remoteWebDavFileList.forEach { webDavFile ->
|
||||||
remoteWebDavFileList.forEach { webDavFile ->
|
if (webDavFile.isDir || bookFileRegex.matches(webDavFile.displayName)) {
|
||||||
if (webDavFile.isDir || bookFileRegex.matches(webDavFile.displayName)) {
|
//扩展名符合阅读的格式则认为是书籍
|
||||||
//扩展名符合阅读的格式则认为是书籍
|
remoteBooks.add(RemoteBook(webDavFile))
|
||||||
remoteBooks.add(RemoteBook(webDavFile))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} ?: throw NoStackTraceException("webDav没有配置")
|
}
|
||||||
return remoteBooks
|
return remoteBooks
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getRemoteBook(path: String): RemoteBook? {
|
override suspend fun getRemoteBook(path: String): RemoteBook? {
|
||||||
AppWebDav.authorization?.let {
|
if (!NetworkUtils.isAvailable()) throw NoStackTraceException("网络不可用")
|
||||||
val webDavFile = WebDav(path, it).getWebDavFile()
|
val webDavFile = WebDav(path, authorization).getWebDavFile()
|
||||||
?: return null
|
?: return null
|
||||||
return RemoteBook(webDavFile)
|
return RemoteBook(webDavFile)
|
||||||
} ?: throw NoStackTraceException("webDav没有配置")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun downloadRemoteBook(remoteBook: RemoteBook): Uri {
|
override suspend fun downloadRemoteBook(remoteBook: RemoteBook): Uri {
|
||||||
AppConfig.defaultBookTreeUri
|
AppConfig.defaultBookTreeUri
|
||||||
?: throw NoStackTraceException("没有设置书籍保存位置!")
|
?: throw NoStackTraceException("没有设置书籍保存位置!")
|
||||||
return AppWebDav.authorization?.let {
|
if (!NetworkUtils.isAvailable()) throw NoStackTraceException("网络不可用")
|
||||||
val webdav = WebDav(remoteBook.path, it)
|
val webdav = WebDav(remoteBook.path, authorization)
|
||||||
webdav.downloadInputStream().let { inputStream ->
|
return webdav.downloadInputStream().let { inputStream ->
|
||||||
LocalBook.saveBookFile(inputStream, remoteBook.filename)
|
LocalBook.saveBookFile(inputStream, remoteBook.filename)
|
||||||
}
|
}
|
||||||
} ?: throw NoStackTraceException("webDav没有配置")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun upload(book: Book) {
|
override suspend fun upload(book: Book) {
|
||||||
if (!NetworkUtils.isAvailable()) throw NoStackTraceException("网络不可用")
|
if (!NetworkUtils.isAvailable()) throw NoStackTraceException("网络不可用")
|
||||||
val localBookUri = Uri.parse(book.bookUrl)
|
val localBookUri = Uri.parse(book.bookUrl)
|
||||||
val putUrl = "$rootBookUrl${File.separator}${book.originName}"
|
val putUrl = "$rootBookUrl${File.separator}${book.originName}"
|
||||||
AppWebDav.authorization?.let {
|
if (localBookUri.isContentScheme()) {
|
||||||
if (localBookUri.isContentScheme()) {
|
WebDav(putUrl, authorization).upload(
|
||||||
WebDav(putUrl, it).upload(
|
byteArray = localBookUri.readBytes(appCtx),
|
||||||
byteArray = localBookUri.readBytes(appCtx),
|
contentType = "application/octet-stream"
|
||||||
contentType = "application/octet-stream"
|
)
|
||||||
)
|
} else {
|
||||||
} else {
|
WebDav(putUrl, authorization).upload(localBookUri.path!!)
|
||||||
WebDav(putUrl, it).upload(localBookUri.path!!)
|
}
|
||||||
}
|
|
||||||
} ?: throw NoStackTraceException("webDav没有配置")
|
|
||||||
book.origin = BookType.webDavTag + putUrl
|
book.origin = BookType.webDavTag + putUrl
|
||||||
book.save()
|
book.save()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun delete(remoteBookUrl: String) {
|
override suspend fun delete(remoteBookUrl: String) {
|
||||||
AppWebDav.authorization?.let {
|
if (!NetworkUtils.isAvailable()) throw NoStackTraceException("网络不可用")
|
||||||
WebDav(remoteBookUrl, it).delete()
|
WebDav(remoteBookUrl, authorization).delete()
|
||||||
} ?: throw NoStackTraceException("webDav没有配置")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import android.app.Application
|
|||||||
import io.legado.app.base.BaseViewModel
|
import io.legado.app.base.BaseViewModel
|
||||||
import io.legado.app.constant.AppLog
|
import io.legado.app.constant.AppLog
|
||||||
import io.legado.app.constant.BookType
|
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.localBook.LocalBook
|
||||||
import io.legado.app.model.remote.RemoteBook
|
import io.legado.app.model.remote.RemoteBook
|
||||||
import io.legado.app.model.remote.RemoteBookWebDav
|
import io.legado.app.model.remote.RemoteBookWebDav
|
||||||
@@ -70,17 +72,26 @@ class RemoteBookViewModel(application: Application) : BaseViewModel(application)
|
|||||||
}
|
}
|
||||||
}.flowOn(Dispatchers.IO)
|
}.flowOn(Dispatchers.IO)
|
||||||
|
|
||||||
|
private var remoteBookWebDav: RemoteBookWebDav? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
execute {
|
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) {
|
fun loadRemoteBookList(path: String?, loadCallback: (loading: Boolean) -> Unit) {
|
||||||
execute {
|
execute {
|
||||||
|
val bookWebDav = remoteBookWebDav
|
||||||
|
?: throw NoStackTraceException("没有配置webDav")
|
||||||
dataCallback?.clear()
|
dataCallback?.clear()
|
||||||
val url = path ?: RemoteBookWebDav.rootBookUrl
|
val url = path ?: bookWebDav.rootBookUrl
|
||||||
val bookList = RemoteBookWebDav.getRemoteBookList(url)
|
val bookList = bookWebDav.getRemoteBookList(url)
|
||||||
dataCallback?.setItems(bookList)
|
dataCallback?.setItems(bookList)
|
||||||
}.onError {
|
}.onError {
|
||||||
AppLog.put("获取webDav书籍出错\n${it.localizedMessage}", it)
|
AppLog.put("获取webDav书籍出错\n${it.localizedMessage}", it)
|
||||||
@@ -95,7 +106,9 @@ class RemoteBookViewModel(application: Application) : BaseViewModel(application)
|
|||||||
fun addToBookshelf(remoteBooks: HashSet<RemoteBook>, finally: () -> Unit) {
|
fun addToBookshelf(remoteBooks: HashSet<RemoteBook>, finally: () -> Unit) {
|
||||||
execute {
|
execute {
|
||||||
remoteBooks.forEach { remoteBook ->
|
remoteBooks.forEach { remoteBook ->
|
||||||
val downloadBookPath = RemoteBookWebDav.downloadRemoteBook(remoteBook)
|
val bookWebDav = remoteBookWebDav
|
||||||
|
?: throw NoStackTraceException("没有配置webDav")
|
||||||
|
val downloadBookPath = bookWebDav.downloadRemoteBook(remoteBook)
|
||||||
downloadBookPath.let {
|
downloadBookPath.let {
|
||||||
val localBook = LocalBook.importFile(it)
|
val localBook = LocalBook.importFile(it)
|
||||||
localBook.origin = BookType.webDavTag + remoteBook.path
|
localBook.origin = BookType.webDavTag + remoteBook.path
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import io.legado.app.data.entities.BookChapter
|
|||||||
import io.legado.app.data.entities.BookSource
|
import io.legado.app.data.entities.BookSource
|
||||||
import io.legado.app.databinding.ActivityBookInfoBinding
|
import io.legado.app.databinding.ActivityBookInfoBinding
|
||||||
import io.legado.app.databinding.DialogEditTextBinding
|
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.isAudio
|
||||||
import io.legado.app.help.book.isLocal
|
import io.legado.app.help.book.isLocal
|
||||||
import io.legado.app.help.book.isLocalTxt
|
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.bottomBackground
|
||||||
import io.legado.app.lib.theme.getPrimaryTextColor
|
import io.legado.app.lib.theme.getPrimaryTextColor
|
||||||
import io.legado.app.model.BookCover
|
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.about.AppLogDialog
|
||||||
import io.legado.app.ui.association.ImportOnLineBookFileDialog
|
import io.legado.app.ui.association.ImportOnLineBookFileDialog
|
||||||
import io.legado.app.ui.book.audio.AudioPlayActivity
|
import io.legado.app.ui.book.audio.AudioPlayActivity
|
||||||
@@ -210,7 +210,8 @@ class BookInfoActivity :
|
|||||||
waitDialog.setText("上传中.....")
|
waitDialog.setText("上传中.....")
|
||||||
waitDialog.show()
|
waitDialog.show()
|
||||||
try {
|
try {
|
||||||
RemoteBookWebDav.upload(it)
|
AppWebDav.getDefaultRemoteBookWebDav()
|
||||||
|
.upload(it)
|
||||||
//更新书籍最后更新时间,使之比远程书籍的时间新
|
//更新书籍最后更新时间,使之比远程书籍的时间新
|
||||||
it.lastCheckTime = System.currentTimeMillis()
|
it.lastCheckTime = System.currentTimeMillis()
|
||||||
viewModel.saveBook(it)
|
viewModel.saveBook(it)
|
||||||
@@ -246,7 +247,7 @@ class BookInfoActivity :
|
|||||||
|
|
||||||
private fun showCover(book: Book) {
|
private fun showCover(book: Book) {
|
||||||
binding.ivCover.load(book.getDisplayCover(), book.name, book.author, false, book.origin)
|
binding.ivCover.load(book.getDisplayCover(), book.name, book.author, false, book.origin)
|
||||||
if(!AppConfig.isEInkMode) {
|
if (!AppConfig.isEInkMode) {
|
||||||
BookCover.loadBlur(this, book.getDisplayCover())
|
BookCover.loadBlur(this, book.getDisplayCover())
|
||||||
.into(binding.bgBook)
|
.into(binding.bgBook)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ import io.legado.app.data.entities.Book
|
|||||||
import io.legado.app.data.entities.BookChapter
|
import io.legado.app.data.entities.BookChapter
|
||||||
import io.legado.app.data.entities.BookSource
|
import io.legado.app.data.entities.BookSource
|
||||||
import io.legado.app.exception.NoStackTraceException
|
import io.legado.app.exception.NoStackTraceException
|
||||||
|
import io.legado.app.help.AppWebDav
|
||||||
import io.legado.app.help.book.*
|
import io.legado.app.help.book.*
|
||||||
import io.legado.app.help.coroutine.Coroutine
|
import io.legado.app.help.coroutine.Coroutine
|
||||||
import io.legado.app.lib.webdav.ObjectNotFoundException
|
import io.legado.app.lib.webdav.ObjectNotFoundException
|
||||||
import io.legado.app.model.BookCover
|
import io.legado.app.model.BookCover
|
||||||
import io.legado.app.model.ReadBook
|
import io.legado.app.model.ReadBook
|
||||||
import io.legado.app.model.localBook.LocalBook
|
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.model.webBook.WebBook
|
||||||
import io.legado.app.utils.isContentScheme
|
import io.legado.app.utils.isContentScheme
|
||||||
import io.legado.app.utils.postEvent
|
import io.legado.app.utils.postEvent
|
||||||
@@ -114,11 +114,12 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
if (book.isLocal) {
|
if (book.isLocal) {
|
||||||
book.tocUrl = ""
|
book.tocUrl = ""
|
||||||
book.getRemoteUrl()?.let {
|
book.getRemoteUrl()?.let {
|
||||||
val remoteBook = RemoteBookWebDav.getRemoteBook(it)
|
val bookWebDav = AppWebDav.getDefaultRemoteBookWebDav()
|
||||||
|
val remoteBook = bookWebDav.getRemoteBook(it)
|
||||||
if (remoteBook == null) {
|
if (remoteBook == null) {
|
||||||
book.origin = BookType.localTag
|
book.origin = BookType.localTag
|
||||||
} else if (remoteBook.lastModify > book.lastCheckTime) {
|
} 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.bookUrl = if (uri.isContentScheme()) uri.toString() else uri.path!!
|
||||||
book.lastCheckTime = remoteBook.lastModify
|
book.lastCheckTime = remoteBook.lastModify
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user