feat: 上传功能初步完成
This commit is contained in:
@@ -2,6 +2,7 @@ package io.legado.app.ui.book.info
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
@@ -31,6 +32,7 @@ import io.legado.app.ui.book.changesource.ChangeBookSourceDialog
|
|||||||
import io.legado.app.ui.book.group.GroupSelectDialog
|
import io.legado.app.ui.book.group.GroupSelectDialog
|
||||||
import io.legado.app.ui.book.info.edit.BookInfoEditActivity
|
import io.legado.app.ui.book.info.edit.BookInfoEditActivity
|
||||||
import io.legado.app.ui.book.read.ReadBookActivity
|
import io.legado.app.ui.book.read.ReadBookActivity
|
||||||
|
import io.legado.app.ui.book.remote.manager.RemoteBookWebDav
|
||||||
import io.legado.app.ui.book.search.SearchActivity
|
import io.legado.app.ui.book.search.SearchActivity
|
||||||
import io.legado.app.ui.book.source.edit.BookSourceEditActivity
|
import io.legado.app.ui.book.source.edit.BookSourceEditActivity
|
||||||
import io.legado.app.ui.book.toc.TocActivityResult
|
import io.legado.app.ui.book.toc.TocActivityResult
|
||||||
@@ -198,6 +200,19 @@ class BookInfoActivity :
|
|||||||
item.isChecked = !item.isChecked
|
item.isChecked = !item.isChecked
|
||||||
if (!item.isChecked) longToastOnUi(R.string.need_more_time_load_content)
|
if (!item.isChecked) longToastOnUi(R.string.need_more_time_load_content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
R.id.menu_upload -> {
|
||||||
|
launch {
|
||||||
|
val uri = Uri.parse(viewModel.bookData.value?.bookUrl.toString())
|
||||||
|
RemoteBookWebDav.getFilePathFromContentUri(uri, contentResolver)
|
||||||
|
// val doc = DocumentFile.fromTreeUri(appCtx,uri)
|
||||||
|
|
||||||
|
// if (uri.isContentScheme()){
|
||||||
|
// uri.path
|
||||||
|
// }
|
||||||
|
// RemoteBookWebDav.upload()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return super.onCompatOptionsItemSelected(item)
|
return super.onCompatOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,14 @@
|
|||||||
package io.legado.app.ui.book.remote
|
package io.legado.app.ui.book.remote
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import io.legado.app.base.VMBaseActivity
|
import io.legado.app.base.VMBaseActivity
|
||||||
import io.legado.app.data.entities.Book
|
|
||||||
|
|
||||||
|
|
||||||
import io.legado.app.databinding.ActivityRemoteBookBinding
|
import io.legado.app.databinding.ActivityRemoteBookBinding
|
||||||
import io.legado.app.lib.theme.backgroundColor
|
|
||||||
import io.legado.app.utils.toastOnUi
|
|
||||||
|
|
||||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||||
import kotlinx.coroutines.flow.conflate
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,7 +46,7 @@ class RemoteBookActivity : VMBaseActivity<ActivityRemoteBookBinding,RemoteBookVi
|
|||||||
// viewModel.getRemoteBooks().observe(this, {
|
// viewModel.getRemoteBooks().observe(this, {
|
||||||
// adapter.submitList(it)
|
// adapter.submitList(it)
|
||||||
// })
|
// })
|
||||||
viewModel.loadRemoteBookList()
|
// viewModel.loadRemoteBookList()
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
viewModel.dataFlow.collect { remoteBooks ->
|
viewModel.dataFlow.collect { remoteBooks ->
|
||||||
@@ -66,6 +61,6 @@ class RemoteBookActivity : VMBaseActivity<ActivityRemoteBookBinding,RemoteBookVi
|
|||||||
|
|
||||||
|
|
||||||
override fun download(remoteBook: RemoteBook) {
|
override fun download(remoteBook: RemoteBook) {
|
||||||
viewModel.downloadRemoteBook(remoteBook.url)
|
viewModel.downloadRemoteBook(remoteBook.urlName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,8 +38,8 @@ class RemoteBookAdapter (context: Context, val callBack: CallBack) :
|
|||||||
payloads: MutableList<Any>
|
payloads: MutableList<Any>
|
||||||
) {
|
) {
|
||||||
binding.run {
|
binding.run {
|
||||||
tvName.text = item.name.substringBeforeLast(".")
|
tvName.text = item.filename
|
||||||
tvContentType.text = item.name.substringAfterLast(".")
|
tvContentType.text = item.contentType
|
||||||
tvSize.text = ConvertUtils.formatFileSize(item.size)
|
tvSize.text = ConvertUtils.formatFileSize(item.size)
|
||||||
tvDate.text = LocalDateTimeUtil.format(LocalDateTimeUtil.of(item.lastModify), "yyyy-MM-dd")
|
tvDate.text = LocalDateTimeUtil.format(LocalDateTimeUtil.of(item.lastModify), "yyyy-MM-dd")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package io.legado.app.ui.book.remote
|
||||||
|
|
||||||
|
import android.content.ContentResolver
|
||||||
|
import android.database.Cursor
|
||||||
|
import android.net.Uri
|
||||||
|
import android.provider.MediaStore
|
||||||
|
import android.provider.OpenableColumns
|
||||||
|
import android.webkit.MimeTypeMap
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
|
||||||
|
abstract class RemoteBookManager {
|
||||||
|
protected val remoteBookFolder : String = "books"
|
||||||
|
protected val contentTypeList: ArrayList<String> = arrayListOf("epub","txt")
|
||||||
|
abstract suspend fun initRemoteContext()
|
||||||
|
abstract suspend fun getRemoteBookList(): MutableList<RemoteBook>
|
||||||
|
abstract suspend fun upload(localBookUrl: String): Boolean
|
||||||
|
abstract suspend fun delete(remoteBookUrl: String): Boolean
|
||||||
|
abstract suspend fun getRemoteBook(remoteBookUrl: String): RemoteBook
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 把content uri转为 文件路径
|
||||||
|
*
|
||||||
|
* @param contentUri 要转换的content uri
|
||||||
|
* @param contentResolver 解析器
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun getFilePathFromContentUri(
|
||||||
|
contentUri: Uri,
|
||||||
|
contentResolver: ContentResolver
|
||||||
|
): String? {
|
||||||
|
val filePath: String
|
||||||
|
if (contentUri.scheme == ContentResolver.SCHEME_FILE)
|
||||||
|
return File(requireNotNull(contentUri.path)).absolutePath
|
||||||
|
else if(contentUri.scheme == ContentResolver.SCHEME_CONTENT){
|
||||||
|
val filePathColumn = arrayOf(MediaStore.MediaColumns.DATA)
|
||||||
|
val cursor: Cursor? =
|
||||||
|
contentResolver.query(contentUri, filePathColumn, null, null, null)
|
||||||
|
cursor!!.moveToFirst()
|
||||||
|
val columnIndex: Int = cursor.getColumnIndex(filePathColumn[0])
|
||||||
|
filePath = cursor.getString(columnIndex)
|
||||||
|
cursor.close()
|
||||||
|
return filePath
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
package io.legado.app.ui.book.remote
|
package io.legado.app.ui.book.remote
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.net.Uri
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import io.legado.app.base.BaseViewModel
|
import io.legado.app.base.BaseViewModel
|
||||||
import io.legado.app.constant.PreferKey
|
import io.legado.app.constant.PreferKey
|
||||||
import io.legado.app.lib.webdav.Authorization
|
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.model.localBook.LocalBook
|
||||||
|
import io.legado.app.ui.book.remote.manager.RemoteBookWebDav
|
||||||
import io.legado.app.utils.FileUtils
|
import io.legado.app.utils.FileUtils
|
||||||
import io.legado.app.utils.exists
|
|
||||||
import io.legado.app.utils.externalFiles
|
import io.legado.app.utils.externalFiles
|
||||||
import io.legado.app.utils.getPrefString
|
import io.legado.app.utils.getPrefString
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
@@ -60,35 +62,18 @@ class RemoteBookViewModel(application: Application): BaseViewModel(application){
|
|||||||
fun loadRemoteBookList() {
|
fun loadRemoteBookList() {
|
||||||
execute {
|
execute {
|
||||||
dataCallback?.clear()
|
dataCallback?.clear()
|
||||||
kotlin.runCatching {
|
RemoteBookWebDav.getRemoteBookList()
|
||||||
authorization = null
|
}
|
||||||
val account = appCtx.getPrefString(PreferKey.webDavAccount)
|
|
||||||
val password = appCtx.getPrefString(PreferKey.webDavPassword)
|
|
||||||
if (!account.isNullOrBlank() && !password.isNullOrBlank()) {
|
|
||||||
val mAuthorization = Authorization(account, password)
|
|
||||||
authorization = mAuthorization
|
|
||||||
}
|
|
||||||
}
|
|
||||||
authorization?.let { it ->
|
|
||||||
val remoteWebDavFileList = WebDav("http://txc.qianfanguojin.top/",it).listFiles()
|
|
||||||
val remoteList = remoteWebDavFileList.map {
|
|
||||||
RemoteBook(it.displayName,it.urlName,it.size,"epub",it.lastModify)
|
|
||||||
}
|
|
||||||
dataCallback?.setItems(remoteList)
|
|
||||||
}
|
|
||||||
// dataCallback?.setItems()
|
// dataCallback?.setItems()
|
||||||
}
|
}
|
||||||
// dataCallback?.setItems(listOf("1", "2", "3"))
|
// dataCallback?.setItems(listOf("1", "2", "3"))
|
||||||
}
|
|
||||||
|
|
||||||
fun downloadRemoteBook(urlName: String) {
|
fun downloadRemoteBook(urlName: String) {
|
||||||
|
val saveFolder = "${appCtx.externalFiles.absolutePath}${File.separator}${remoteBookFolderName}"
|
||||||
|
val trueCodeURLName = String(urlName.toByteArray(Charset.forName("GBK")), Charset.forName("UTF-8"))
|
||||||
|
val saveFilePath = "${saveFolder}${trueCodeURLName}"
|
||||||
execute {
|
execute {
|
||||||
// kotlin.runCatching {
|
|
||||||
// val remoteWebDavFile = WebDav("http://txc.qianfanguojin.top/",authorization!!).getFile(url)
|
|
||||||
// val remoteBook = RemoteBook(remoteWebDavFile.displayName,remoteWebDavFile.urlName,remoteWebDavFile.size,"epub",remoteWebDavFile.lastModify)
|
|
||||||
// dataCallback?.addItems(listOf(remoteBook))
|
|
||||||
// }
|
|
||||||
|
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
authorization = null
|
authorization = null
|
||||||
val account = appCtx.getPrefString(PreferKey.webDavAccount)
|
val account = appCtx.getPrefString(PreferKey.webDavAccount)
|
||||||
@@ -100,19 +85,30 @@ class RemoteBookViewModel(application: Application): BaseViewModel(application){
|
|||||||
}
|
}
|
||||||
|
|
||||||
authorization?.let { it ->
|
authorization?.let { it ->
|
||||||
Log.e("TAG", "downloadRemoteBook: 1", )
|
|
||||||
val saveFolder = "${appCtx.externalFiles.absolutePath}${File.separator}${remoteBookFolderName}"
|
|
||||||
FileUtils.createFolderIfNotExist(saveFolder).run{
|
FileUtils.createFolderIfNotExist(saveFolder).run{
|
||||||
|
withTimeout(15000L) {
|
||||||
// Log.e("TAG", "downloadRemoteBook: 2 ${appCtx.externalFiles.absoluteFile}", )
|
val webdav = WebDav(
|
||||||
val trueCodeURLName = String(urlName.toByteArray(Charset.forName("GBK")), Charset.forName("UTF-8"))
|
"http://txc.qianfanguojin.top${trueCodeURLName}",
|
||||||
withTimeout(15000L) {
|
it
|
||||||
val webdav = WebDav("http://txc.qianfanguojin.top${trueCodeURLName}", it)
|
)
|
||||||
webdav.downloadTo("${saveFolder}${trueCodeURLName}", true).apply {
|
webdav.downloadTo(saveFilePath, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}.onFinally {
|
||||||
|
addToBookshelf(hashSetOf("${saveFolder}${trueCodeURLName}")){
|
||||||
|
Log.e("TAG", "downloadRemoteBook: add", )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
fun addToBookshelf(uriList: HashSet<String>, finally: () -> Unit) {
|
||||||
|
execute {
|
||||||
|
uriList.forEach {
|
||||||
|
LocalBook.importFile(Uri.parse(it))
|
||||||
|
}
|
||||||
|
}.onFinally {
|
||||||
|
finally.invoke()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
interface DataCallback {
|
interface DataCallback {
|
||||||
@@ -127,9 +123,10 @@ class RemoteBookViewModel(application: Application): BaseViewModel(application){
|
|||||||
}
|
}
|
||||||
|
|
||||||
data class RemoteBook(
|
data class RemoteBook(
|
||||||
val name: String,
|
val filename: String,
|
||||||
val url: String,
|
val urlName: String,
|
||||||
val size: Long,
|
val size: Long,
|
||||||
val contentType: String,
|
val contentType: String,
|
||||||
val lastModify: Long
|
val lastModify: Long
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,260 @@
|
|||||||
|
package io.legado.app.ui.book.remote.manager
|
||||||
|
|
||||||
|
|
||||||
|
import io.legado.app.constant.PreferKey
|
||||||
|
|
||||||
|
import io.legado.app.exception.NoStackTraceException
|
||||||
|
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.ui.book.remote.RemoteBook
|
||||||
|
import io.legado.app.ui.book.remote.RemoteBookManager
|
||||||
|
import io.legado.app.utils.*
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import splitties.init.appCtx
|
||||||
|
import java.io.File
|
||||||
|
import java.nio.charset.Charset
|
||||||
|
|
||||||
|
object RemoteBookWebDav : RemoteBookManager() {
|
||||||
|
private const val defaultWebDavUrl = "https://dav.jianguoyun.com/dav/"
|
||||||
|
private var authorization: Authorization? = null
|
||||||
|
private val remoteBookUrl get() = "${rootWebDavUrl}${remoteBookFolder}"
|
||||||
|
|
||||||
|
init {
|
||||||
|
runBlocking {
|
||||||
|
initRemoteContext()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val rootWebDavUrl: String
|
||||||
|
get() {
|
||||||
|
val configUrl = appCtx.getPrefString(PreferKey.webDavUrl)?.trim()
|
||||||
|
var url = if (configUrl.isNullOrEmpty()) defaultWebDavUrl else configUrl
|
||||||
|
if (!url.endsWith("/")) url = "${url}/"
|
||||||
|
AppConfig.webDavDir?.trim()?.let {
|
||||||
|
if (it.isNotEmpty()) {
|
||||||
|
url = "${url}${it}/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun initRemoteContext() {
|
||||||
|
kotlin.runCatching {
|
||||||
|
authorization = null
|
||||||
|
val account = appCtx.getPrefString(PreferKey.webDavAccount)
|
||||||
|
val password = appCtx.getPrefString(PreferKey.webDavPassword)
|
||||||
|
if (!account.isNullOrBlank() && !password.isNullOrBlank()) {
|
||||||
|
val mAuthorization = Authorization(account, password)
|
||||||
|
WebDav(rootWebDavUrl, mAuthorization).makeAsDir()
|
||||||
|
WebDav(remoteBookUrl, mAuthorization).makeAsDir()
|
||||||
|
authorization = mAuthorization
|
||||||
|
}
|
||||||
|
}.onFailure {
|
||||||
|
it.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(Exception::class)
|
||||||
|
override suspend fun getRemoteBookList(): MutableList<RemoteBook> {
|
||||||
|
val remoteBooks = mutableListOf<RemoteBook>()
|
||||||
|
|
||||||
|
authorization?.let {
|
||||||
|
var remoteWebDavFileList : List<WebDavFile>? = null
|
||||||
|
kotlin.runCatching {
|
||||||
|
remoteWebDavFileList = WebDav(remoteBookUrl, it).listFiles()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
remoteWebDavFileList = remoteWebDavFileList!!.reversed()
|
||||||
|
remoteWebDavFileList!!.forEach { webDavFile ->
|
||||||
|
val webDavFileName = webDavFile.displayName
|
||||||
|
val webDavUrlName = webDavFile.urlName
|
||||||
|
|
||||||
|
// 转码
|
||||||
|
val trueFileName = String(webDavFileName.toByteArray(Charset.forName("GBK")), Charset.forName("UTF-8"))
|
||||||
|
val trueUrlName = String(webDavUrlName.toByteArray(Charset.forName("GBK")), Charset.forName("UTF-8"))
|
||||||
|
|
||||||
|
//分割文件名和后缀
|
||||||
|
val filename = trueFileName.substringBeforeLast(".")
|
||||||
|
val fileExtension = trueFileName.substringAfterLast(".")
|
||||||
|
|
||||||
|
//扩展名符合阅读的格式则认为是书籍
|
||||||
|
if (contentTypeList.contains(fileExtension)) {
|
||||||
|
remoteBooks.add(RemoteBook(filename,trueUrlName,webDavFile.size,fileExtension,webDavFile.lastModify))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ?: throw NoStackTraceException("webDav没有配置")
|
||||||
|
return remoteBooks
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getRemoteBook(remoteBookUrl: String): RemoteBook {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传本地导入的书籍到远程
|
||||||
|
*/
|
||||||
|
override suspend fun upload(localBookUrl: String): Boolean {
|
||||||
|
if (!NetworkUtils.isAvailable()) return false
|
||||||
|
val localBookName = localBookUrl.substringAfterLast(File.separator)
|
||||||
|
authorization?.let {
|
||||||
|
val putUrl = "${remoteBookUrl}${File.separator}${localBookName}"
|
||||||
|
WebDav(putUrl, it).upload(localBookUrl)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun delete(remoteBookUrl: String): Boolean {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
// suspend fun showRestoreDialog(context: Context) {
|
||||||
|
// val names = withContext(Dispatchers.IO) { getBackupNames() }
|
||||||
|
// if (names.isNotEmpty()) {
|
||||||
|
// withContext(Dispatchers.Main) {
|
||||||
|
// context.selector(
|
||||||
|
// title = context.getString(R.string.select_restore_file),
|
||||||
|
// items = names
|
||||||
|
// ) { _, index ->
|
||||||
|
// if (index in 0 until names.size) {
|
||||||
|
// Coroutine.async {
|
||||||
|
// restoreWebDav(names[index])
|
||||||
|
// }.onError {
|
||||||
|
// appCtx.toastOnUi("WebDav恢复出错\n${it.localizedMessage}")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// throw NoStackTraceException("Web dav no back up file")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Throws(WebDavException::class)
|
||||||
|
// suspend fun restoreWebDav(name: String) {
|
||||||
|
// authorization?.let {
|
||||||
|
// val webDav = WebDav(rootWebDavUrl + name, it)
|
||||||
|
// webDav.downloadTo(zipFilePath, true)
|
||||||
|
// @Suppress("BlockingMethodInNonBlockingContext")
|
||||||
|
// ZipUtils.unzipFile(zipFilePath, Backup.backupPath)
|
||||||
|
// Restore.restoreDatabase()
|
||||||
|
// Restore.restoreConfig()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// suspend fun hasBackUp(): Boolean {
|
||||||
|
// authorization?.let {
|
||||||
|
// val url = "${rootWebDavUrl}${backupFileName}"
|
||||||
|
// return WebDav(url, it).exists()
|
||||||
|
// }
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// suspend fun lastBackUp(): Result<WebDavFile?> {
|
||||||
|
// return kotlin.runCatching {
|
||||||
|
// authorization?.let {
|
||||||
|
// var lastBackupFile: WebDavFile? = null
|
||||||
|
// WebDav(rootWebDavUrl, it).listFiles().reversed().forEach { webDavFile ->
|
||||||
|
// if (webDavFile.displayName.startsWith("backup")) {
|
||||||
|
// if (lastBackupFile == null
|
||||||
|
// || webDavFile.lastModify > lastBackupFile!!.lastModify
|
||||||
|
// ) {
|
||||||
|
// lastBackupFile = webDavFile
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// lastBackupFile
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Throws(Exception::class)
|
||||||
|
// suspend fun backUpWebDav(path: String) {
|
||||||
|
// if (!NetworkUtils.isAvailable()) return
|
||||||
|
// authorization?.let {
|
||||||
|
// val paths = arrayListOf(*Backup.backupFileNames)
|
||||||
|
// for (i in 0 until paths.size) {
|
||||||
|
// paths[i] = path + File.separator + paths[i]
|
||||||
|
// }
|
||||||
|
// FileUtils.delete(zipFilePath)
|
||||||
|
// if (ZipUtils.zipFiles(paths, zipFilePath)) {
|
||||||
|
// val putUrl = "${rootWebDavUrl}${backupFileName}"
|
||||||
|
// WebDav(putUrl, it).upload(zipFilePath)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// suspend fun exportWebDav(byteArray: ByteArray, fileName: String) {
|
||||||
|
// if (!NetworkUtils.isAvailable()) return
|
||||||
|
// try {
|
||||||
|
// authorization?.let {
|
||||||
|
// // 如果导出的本地文件存在,开始上传
|
||||||
|
// val putUrl = exportsWebDavUrl + fileName
|
||||||
|
// WebDav(putUrl, it).upload(byteArray, "text/plain")
|
||||||
|
// }
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// val msg = "WebDav导出\n${e.localizedMessage}"
|
||||||
|
// AppLog.put(msg)
|
||||||
|
// appCtx.toastOnUi(msg)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun uploadBookProgress(book: Book) {
|
||||||
|
// val authorization = authorization ?: return
|
||||||
|
// if (!syncBookProgress) return
|
||||||
|
// if (!NetworkUtils.isAvailable()) return
|
||||||
|
// Coroutine.async {
|
||||||
|
// val bookProgress = BookProgress(book)
|
||||||
|
// val json = GSON.toJson(bookProgress)
|
||||||
|
// val url = getProgressUrl(book)
|
||||||
|
// WebDav(url, authorization).upload(json.toByteArray(), "application/json")
|
||||||
|
// }.onError {
|
||||||
|
// AppLog.put("上传进度失败\n${it.localizedMessage}")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private fun getProgressUrl(book: Book): String {
|
||||||
|
// return bookProgressUrl + book.name + "_" + book.author + ".json"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 获取书籍进度
|
||||||
|
// */
|
||||||
|
// suspend fun getBookProgress(book: Book): BookProgress? {
|
||||||
|
// authorization?.let {
|
||||||
|
// val url = getProgressUrl(book)
|
||||||
|
// kotlin.runCatching {
|
||||||
|
// WebDav(url, it).download().let { byteArray ->
|
||||||
|
// val json = String(byteArray)
|
||||||
|
// if (json.isJson()) {
|
||||||
|
// return GSON.fromJsonObject<BookProgress>(json).getOrNull()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return null
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// suspend fun downloadAllBookProgress() {
|
||||||
|
// authorization ?: return
|
||||||
|
// if (!NetworkUtils.isAvailable()) return
|
||||||
|
// appDb.bookDao.all.forEach { book ->
|
||||||
|
// getBookProgress(book)?.let { bookProgress ->
|
||||||
|
// if (bookProgress.durChapterIndex > book.durChapterIndex
|
||||||
|
// || (bookProgress.durChapterIndex == book.durChapterIndex
|
||||||
|
// && bookProgress.durChapterPos > book.durChapterPos)
|
||||||
|
// ) {
|
||||||
|
// book.durChapterIndex = bookProgress.durChapterIndex
|
||||||
|
// book.durChapterPos = bookProgress.durChapterPos
|
||||||
|
// book.durChapterTitle = bookProgress.durChapterTitle
|
||||||
|
// book.durChapterTime = bookProgress.durChapterTime
|
||||||
|
// appDb.bookDao.update(book)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:text="\u4e28"
|
android:text="丨"
|
||||||
android:textColor="@color/tv_text_summary"
|
android:textColor="@color/tv_text_summary"
|
||||||
android:textSize="11sp" />
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user