From 3f1c95b7beafc8fd04089de457093bc6a7e08e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A2=E6=84=8F=E5=B8=86?= <1657098617@qq.com> Date: Mon, 16 May 2022 12:50:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=8B=E8=BD=BD=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/ui/book/remote/RemoteBookActivity.kt | 16 ++- .../app/ui/book/remote/RemoteBookAdapter.kt | 27 ++++- .../app/ui/book/remote/RemoteBookViewModel.kt | 107 ++++++++++++++---- .../main/res/layout/activity_remote_book.xml | 12 +- app/src/main/res/layout/item_remote_book.xml | 5 +- 5 files changed, 129 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookActivity.kt index d6fdc428c..4f8232a91 100644 --- a/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookActivity.kt @@ -29,10 +29,13 @@ class RemoteBookActivity : VMBaseActivity + viewModel.dataFlow.collect { remoteBooks -> adapter.setItems(remoteBooks) } } // toastOnUi("1") - viewModel.loadRemoteBookList() + } - override fun showRemoteBookInfo(book: Book) { - TODO("Not yet implemented") + + + override fun download(remoteBook: RemoteBook) { + viewModel.downloadRemoteBook(remoteBook.url) } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookAdapter.kt b/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookAdapter.kt index d7f590408..99245f0f6 100644 --- a/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookAdapter.kt @@ -2,14 +2,23 @@ package io.legado.app.ui.book.remote import android.content.Context import android.view.ViewGroup +import cn.hutool.core.date.LocalDateTimeUtil import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.data.entities.Book import io.legado.app.databinding.ItemRemoteBookBinding +import io.legado.app.utils.ConvertUtils +import io.legado.app.utils.FileUtils +import io.legado.app.utils.toastOnUi +import splitties.init.appCtx +/** + * 适配器 + * @author qianfanguojin + */ class RemoteBookAdapter (context: Context, val callBack: CallBack) : - RecyclerAdapter(context){ + RecyclerAdapter(context){ override fun getViewBinding(parent: ViewGroup): ItemRemoteBookBinding { return ItemRemoteBookBinding.inflate(inflater, parent, false) @@ -25,19 +34,29 @@ class RemoteBookAdapter (context: Context, val callBack: CallBack) : override fun convert( holder: ItemViewHolder, binding: ItemRemoteBookBinding, - item: String, + item: RemoteBook, payloads: MutableList ) { binding.run { - tvName.text = item + tvName.text = item.name.substringBeforeLast(".") + tvContentType.text = item.name.substringAfterLast(".") + tvSize.text = ConvertUtils.formatFileSize(item.size) + tvDate.text = LocalDateTimeUtil.format(LocalDateTimeUtil.of(item.lastModify), "yyyy-MM-dd") } } override fun registerListener(holder: ItemViewHolder, binding: ItemRemoteBookBinding) { + binding.btnDownload.setOnClickListener { + getItem(holder.layoutPosition)?.let { + context.toastOnUi("开始下载") + callBack.download(it) + } + } + } interface CallBack { - fun showRemoteBookInfo(book: Book) + fun download(remoteBook: RemoteBook) } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookViewModel.kt b/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookViewModel.kt index 5d646b725..31cef12b0 100644 --- a/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookViewModel.kt @@ -2,36 +2,43 @@ package io.legado.app.ui.book.remote import android.app.Application import android.util.Log -import android.widget.Toast import io.legado.app.base.BaseViewModel -import io.legado.app.utils.FileDoc -import kotlinx.coroutines.Dispatchers +import io.legado.app.constant.PreferKey +import io.legado.app.lib.webdav.Authorization +import io.legado.app.lib.webdav.WebDav +import io.legado.app.utils.FileUtils +import io.legado.app.utils.exists +import io.legado.app.utils.externalFiles +import io.legado.app.utils.getPrefString +import kotlinx.coroutines.* import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.withContext +import splitties.init.appCtx +import java.io.File +import java.nio.charset.Charset import java.util.* -import kotlin.reflect.typeOf class RemoteBookViewModel(application: Application): BaseViewModel(application){ - + private val remoteBookFolderName = "book_remote" private var dataCallback : DataCallback? = null var dataFlowStart: (() -> Unit)? = null - val dataFlow = callbackFlow> { + private var authorization: Authorization? = null + + + val dataFlow = callbackFlow> { - val list = Collections.synchronizedList(ArrayList()) + val list = Collections.synchronizedList(ArrayList()) dataCallback = object : DataCallback { - override fun setItems(remoteFiles: List) { + override fun setItems(remoteFiles: List) { list.clear() list.addAll(remoteFiles) - Log.e("TAG", ": 1", ) trySend(list) } - override fun addItems(remoteFiles: List) { + override fun addItems(remoteFiles: List) { list.addAll(remoteFiles) trySend(list) } @@ -41,28 +48,88 @@ class RemoteBookViewModel(application: Application): BaseViewModel(application){ trySend(emptyList()) } } - // withContext(Dispatchers.Main) { // dataFlowStart?.invoke() // } awaitClose { - dataCallback = null +// dataCallback = null } - }.flowOn(Dispatchers.Main) + }.flowOn(Dispatchers.IO) fun loadRemoteBookList() { - Log.e("TAG", dataCallback.toString(), ) - dataCallback?.setItems(listOf("1", "2", "3")) + execute { + dataCallback?.clear() + 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) + 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(listOf("1", "2", "3")) } + fun downloadRemoteBook(urlName: String) { + 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 { + 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 -> + Log.e("TAG", "downloadRemoteBook: 1", ) + val saveFolder = "${appCtx.externalFiles.absolutePath}${File.separator}${remoteBookFolderName}" + FileUtils.createFolderIfNotExist(saveFolder).run{ + +// Log.e("TAG", "downloadRemoteBook: 2 ${appCtx.externalFiles.absoluteFile}", ) + val trueCodeURLName = String(urlName.toByteArray(Charset.forName("GBK")), Charset.forName("UTF-8")) + withTimeout(15000L) { + val webdav = WebDav("http://txc.qianfanguojin.top${trueCodeURLName}", it) + webdav.downloadTo("${saveFolder}${trueCodeURLName}", true).apply { + } + } + } + } + } + } interface DataCallback { - fun setItems(remoteFiles: List) + fun setItems(remoteFiles: List) - fun addItems(remoteFiles: List) + fun addItems(remoteFiles: List) fun clear() } -} \ No newline at end of file +} + +data class RemoteBook( + val name: String, + val url: String, + val size: Long, + val contentType: String, + val lastModify: Long +) \ No newline at end of file diff --git a/app/src/main/res/layout/activity_remote_book.xml b/app/src/main/res/layout/activity_remote_book.xml index ed942a2cc..6af80a958 100644 --- a/app/src/main/res/layout/activity_remote_book.xml +++ b/app/src/main/res/layout/activity_remote_book.xml @@ -36,9 +36,11 @@ - + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_remote_book.xml b/app/src/main/res/layout/item_remote_book.xml index 85af79d7f..ad986eaa6 100644 --- a/app/src/main/res/layout/item_remote_book.xml +++ b/app/src/main/res/layout/item_remote_book.xml @@ -55,7 +55,7 @@ android:layout_height="wrap_content" android:ellipsize="end" android:lines="1" - tools:text="\u4e28" + android:text="\u4e28" android:textColor="@color/tv_text_summary" android:textSize="11sp" /> @@ -96,10 +96,9 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toTopOf="parent" android:layout_marginTop="3dp" - android:id="@+id/tv_download" >