From 360aa0806d575ab0fe125e987ee0afd29eceb171 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Fri, 13 May 2022 15:45:02 +0800 Subject: [PATCH 01/12] =?UTF-8?q?docs:=E6=9B=B4=E6=96=B0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E4=B9=A6=E6=BA=90=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/help/ruleHelp.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/assets/help/ruleHelp.md b/app/src/main/assets/help/ruleHelp.md index e3def4f4e..4c406f7e8 100644 --- a/app/src/main/assets/help/ruleHelp.md +++ b/app/src/main/assets/help/ruleHelp.md @@ -10,6 +10,9 @@ @Json: json规则,直接写时以$.开头可省略@Json : regex规则,不可省略,只可以用在书籍列表和目录列表 ``` +* 书源类型: 文件 +> 对于类似知轩藏书提供文件整合下载的网站,可以'在书源详情的目录URL规则获取文件链接,阅读会自动下载并导入 + * CookieJar > 启用后会自动保存每次返回头中的Set-Cookie中的值,适用于验证码图片一类需要session的网站 * 登录UI From 1e68ec51f28d5043a132d7cd92c3f308a4de3cec Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Fri, 13 May 2022 18:44:57 +0800 Subject: [PATCH 02/12] =?UTF-8?q?feat:=E6=96=87=E4=BB=B6=E7=B1=BB=E4=B9=A6?= =?UTF-8?q?=E6=BA=90=E8=B7=B3=E8=BF=87=E6=A0=A1=E9=AA=8C=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E6=AD=A3=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/legado/app/service/CheckSourceService.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/io/legado/app/service/CheckSourceService.kt b/app/src/main/java/io/legado/app/service/CheckSourceService.kt index a7a81b924..62637d428 100644 --- a/app/src/main/java/io/legado/app/service/CheckSourceService.kt +++ b/app/src/main/java/io/legado/app/service/CheckSourceService.kt @@ -6,6 +6,7 @@ import com.script.ScriptException import io.legado.app.R import io.legado.app.base.BaseService import io.legado.app.constant.AppConst +import io.legado.app.constant.BookType import io.legado.app.constant.EventBus import io.legado.app.constant.IntentAction import io.legado.app.data.appDb @@ -208,7 +209,9 @@ class CheckSourceService : BaseService() { mBook = WebBook.getBookInfoAwait(this, source, mBook) } //校验目录 - if (CheckSource.checkCategory) { + if (CheckSource.checkCategory && + source.bookSourceType != BookType.file + ) { val toc = WebBook.getChapterListAwait(this, source, mBook).getOrThrow() val nextChapterUrl = toc.getOrNull(1)?.url ?: toc.first().url //校验正文 From b44e0e76feb37f47118fd1bf83a62a4b2c960e9c Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Fri, 13 May 2022 21:33:10 +0800 Subject: [PATCH 03/12] =?UTF-8?q?feat:=E6=B7=BB=E5=8A=A0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=B1=BB=E4=B8=8B=E8=BD=BD=E9=93=BE=E6=8E=A5=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/help/ruleHelp.md | 2 +- .../main/java/io/legado/app/data/entities/rule/BookInfoRule.kt | 3 ++- .../legado/app/ui/book/source/edit/BookSourceEditActivity.kt | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/assets/help/ruleHelp.md b/app/src/main/assets/help/ruleHelp.md index 4c406f7e8..9d3c6ade9 100644 --- a/app/src/main/assets/help/ruleHelp.md +++ b/app/src/main/assets/help/ruleHelp.md @@ -11,7 +11,7 @@ : regex规则,不可省略,只可以用在书籍列表和目录列表 ``` * 书源类型: 文件 -> 对于类似知轩藏书提供文件整合下载的网站,可以'在书源详情的目录URL规则获取文件链接,阅读会自动下载并导入 +> 对于类似知轩藏书提供文件整合下载的网站,可以'在书源详情的下载URL规则获取文件链接,支持多个链接,阅读会自动下载并导入 * CookieJar > 启用后会自动保存每次返回头中的Set-Cookie中的值,适用于验证码图片一类需要session的网站 diff --git a/app/src/main/java/io/legado/app/data/entities/rule/BookInfoRule.kt b/app/src/main/java/io/legado/app/data/entities/rule/BookInfoRule.kt index 9f3a0c9d0..cddba2c4f 100644 --- a/app/src/main/java/io/legado/app/data/entities/rule/BookInfoRule.kt +++ b/app/src/main/java/io/legado/app/data/entities/rule/BookInfoRule.kt @@ -16,5 +16,6 @@ data class BookInfoRule( var coverUrl: String? = null, var tocUrl: String? = null, var wordCount: String? = null, - var canReName: String? = null + var canReName: String? = null, + var downloadUrls: String? = null ) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt index ab93ccc0e..ed991ff58 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt @@ -266,6 +266,7 @@ class BookSourceEditActivity : add(EditEntity("coverUrl", ir?.coverUrl, R.string.rule_cover_url)) add(EditEntity("tocUrl", ir?.tocUrl, R.string.rule_toc_url)) add(EditEntity("canReName", ir?.canReName, R.string.rule_can_re_name)) + add(EditEntity("downloadUrls", ir?.downloadUrls, R.string.download_url_rule)) } //目录页 val tr = source?.getTocRule() @@ -396,6 +397,7 @@ class BookSourceEditActivity : "tocUrl" -> bookInfoRule.tocUrl = viewModel.ruleComplete(it.value, bookInfoRule.init, 2) "canReName" -> bookInfoRule.canReName = it.value + "downloadUrls" -> bookInfoRule.downloadUrls = viewModel.ruleComplete(it.value, bookInfoRule.init) } } tocEntities.forEach { From 4fb534ccb7088b58ecc6b7814581b4a90e42a001 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Sat, 14 May 2022 06:10:00 +0800 Subject: [PATCH 04/12] =?UTF-8?q?refactor(LocalBook.kt):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../legado/app/model/localBook/LocalBook.kt | 77 ++++++++++++++----- .../io/legado/app/model/localBook/README.md | 4 +- 2 files changed, 60 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt index 9a1d57104..c5fb22f40 100644 --- a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt +++ b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt @@ -24,6 +24,10 @@ import java.io.FileNotFoundException import java.io.InputStream import java.util.regex.Pattern +/** + * 书籍文件导入 目录正文解析 + * 支持在线文件(txt epub umd 压缩文件需要用户解压) 本地文件 + */ object LocalBook { private val nameAuthorPatterns = arrayOf( @@ -84,32 +88,25 @@ object LocalBook { } } - //导入在线的文件 + /** + * 下载在线的文件并自动导入到阅读(txt umd epub) + * 压缩文件请先提示用户解压 + */ fun importFile( str: String, - fileName: String, + fileName: String? = null, source: BaseSource? = null, onLineBook: Book? = null ): Book { - val bytes = when { - str.isAbsUrl() -> AnalyzeUrl(str, source = source).getByteArray() - str.isDataUrl() -> Base64.decode(str.substringAfter("base64,"), Base64.DEFAULT) - else -> throw NoStackTraceException("在线导入书籍支持http/https/DataURL") + val fileUri = saveBookFile(str, fileName, source, onLineBook) + return importFile(fileUri).let { + mergeBook(it, onLineBook) } - val localBook = importFile(bytes, fileName) - return mergeBook(localBook, onLineBook) } - fun importFile( - bytes: ByteArray, - fileName: String - ): Book { - return saveBookFile(bytes, fileName).let { - importFile(it) - } - } - - //导入本地文件 + /** + * 导入本地文件 + */ fun importFile(uri: Uri): Book { val bookUrl: String val updateTime: Long @@ -150,6 +147,9 @@ object LocalBook { return book } + /** + * 从文件分析书籍必要信息(书名 作者等) + */ private fun analyzeNameAuthor(fileName: String): Pair { val tempFileName = fileName.substringBeforeLast(".") var name: String @@ -203,6 +203,45 @@ object LocalBook { } } + /** + * 下载在线的文件 + * fileName为空时 传入onLineBook + */ + fun saveBookFile( + str: String, + fileName: String? = null, + source: BaseSource? = null, + onLineBook: Book? = null + ): Uri { + val bytes = when { + str.isAbsUrl() -> AnalyzeUrl(str, source = source).getByteArray() + str.isDataUrl() -> Base64.decode(str.substringAfter("base64,"), Base64.DEFAULT) + else -> throw NoStackTraceException("在线导入书籍支持http/https/DataURL") + } + val mFileName = fileName ?: extractDownloadName(str, onLineBook) + return saveBookFile(bytes, mFileName) + } + + /** + * 分析下载文件类书源的下载链接 + * https://www.example.com/download/{fileName}.{type} 含有文件名和后缀 + * https://www.example.com/download/?fileid=1234, {type: "txt"} + */ + fun extractDownloadName(uri: String, onLineBook: Book?): String { + val analyzeUrl = AnalyzeUrl(uri) + val urlNoOption = analyzeUrl.url + val lastPath = urlNoOption.substringAfterLast("/") + val fileType = lastPath.substringAfterLast(".") + val type = analyzeUrl.type + val fileName = when { + onLineBook != null -> "${onLineBook.name}_${onLineBook.author}_${onLineBook.origin}" + type == null-> lastPath + else -> lastPath.substringBeforeAfter(".") + } + val fileSuffix = fileType ?: type ?: "unknown" + return "${fileName}.${fileSuffix}" + } + private fun saveBookFile( bytes: ByteArray, fileName: String @@ -232,7 +271,7 @@ object LocalBook { } //文件类书源 合并在线书籍信息 在线 > 本地 - private fun mergeBook(localBook: Book, onLineBook: Book?): Book { + fun mergeBook(localBook: Book, onLineBook: Book?): Book { onLineBook ?: return localBook val mergeBook = localBook mergeBook.name = if (onLineBook.name.isBlank()) localBook.name else onLineBook.name diff --git a/app/src/main/java/io/legado/app/model/localBook/README.md b/app/src/main/java/io/legado/app/model/localBook/README.md index 8f080b25e..04aaa6c38 100644 --- a/app/src/main/java/io/legado/app/model/localBook/README.md +++ b/app/src/main/java/io/legado/app/model/localBook/README.md @@ -1,7 +1,7 @@ -# 本地书籍解析 +# 书籍文件导入解析 * BaseLocalBookParse.kt 本地书籍解析接口 -* LocalBook.kt 总入口 +* LocalBook.kt 导入解析总入口 * TextFile.kt 解析txt * EpubFile.kt 解析epub * UmdFile.kt 解析umd \ No newline at end of file From d4adbba7766898b75dd5832e57024420fecb7979 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Sat, 14 May 2022 16:04:28 +0800 Subject: [PATCH 05/12] =?UTF-8?q?feat=EF=BC=9A=E6=B7=BB=E5=8A=A0=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E4=B9=A6=E7=B1=8D=E5=AF=B9=E8=AF=9D=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/api/controller/BookController.kt | 2 +- .../java/io/legado/app/data/entities/Book.kt | 4 + .../legado/app/model/localBook/LocalBook.kt | 4 +- .../io/legado/app/model/webBook/BookInfo.kt | 26 ++- .../association/ImportOnLineBookFileDialog.kt | 152 ++++++++++++++++++ .../ImportOnLineBookFileViewModel.kt | 112 +++++++++++++ .../app/ui/book/info/BookInfoActivity.kt | 10 +- .../app/ui/book/info/BookInfoViewModel.kt | 27 +--- .../main/res/layout/item_book_file_import.xml | 34 ++++ 9 files changed, 338 insertions(+), 33 deletions(-) create mode 100644 app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt create mode 100644 app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt create mode 100644 app/src/main/res/layout/item_book_file_import.xml diff --git a/app/src/main/java/io/legado/app/api/controller/BookController.kt b/app/src/main/java/io/legado/app/api/controller/BookController.kt index 797212544..4c8e93123 100644 --- a/app/src/main/java/io/legado/app/api/controller/BookController.kt +++ b/app/src/main/java/io/legado/app/api/controller/BookController.kt @@ -244,7 +244,7 @@ object BookController { val fileData = parameters["fileData"]?.firstOrNull() ?: return returnData.setErrorMsg("fileData 不能为空") kotlin.runCatching { - LocalBook.importFile(fileData, fileName) + LocalBook.importFileOnLine(fileData, fileName) }.onFailure { return when (it) { is SecurityException -> returnData.setErrorMsg("需重新设置书籍保存位置!") diff --git a/app/src/main/java/io/legado/app/data/entities/Book.kt b/app/src/main/java/io/legado/app/data/entities/Book.kt index 072fbe9a3..449d6eacc 100644 --- a/app/src/main/java/io/legado/app/data/entities/Book.kt +++ b/app/src/main/java/io/legado/app/data/entities/Book.kt @@ -154,6 +154,10 @@ data class Book( @IgnoredOnParcel override var tocHtml: String? = null + @Ignore + @IgnoredOnParcel + var downloadUrls: List? = null + fun getRealAuthor() = author.replace(AppPattern.authorRegex, "") fun getUnreadChapterNum() = max(totalChapterNum - durChapterIndex - 1, 0) diff --git a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt index c5fb22f40..68b95c9e3 100644 --- a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt +++ b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt @@ -92,7 +92,7 @@ object LocalBook { * 下载在线的文件并自动导入到阅读(txt umd epub) * 压缩文件请先提示用户解压 */ - fun importFile( + fun importFileOnLine( str: String, fileName: String? = null, source: BaseSource? = null, @@ -236,7 +236,7 @@ object LocalBook { val fileName = when { onLineBook != null -> "${onLineBook.name}_${onLineBook.author}_${onLineBook.origin}" type == null-> lastPath - else -> lastPath.substringBeforeAfter(".") + else -> lastPath.substringBeforeLast(".") } val fileSuffix = fileType ?: type ?: "unknown" return "${fileName}.${fileSuffix}" diff --git a/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt b/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt index 1ff5f0356..53847ea52 100644 --- a/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt +++ b/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt @@ -1,6 +1,8 @@ package io.legado.app.model.webBook +import android.text.TextUtils import io.legado.app.R +import io.legado.app.constant.BookType import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookSource import io.legado.app.exception.NoStackTraceException @@ -137,14 +139,24 @@ object BookInfo { Debug.log(bookSource.bookSourceUrl, "└${e.localizedMessage}") DebugLog.e("获取封面出错", e) } - scope.ensureActive() - Debug.log(bookSource.bookSourceUrl, "┌获取目录链接") - book.tocUrl = analyzeRule.getString(infoRule.tocUrl, isUrl = true) - if (book.tocUrl.isEmpty()) book.tocUrl = baseUrl - if (book.tocUrl == baseUrl) { - book.tocHtml = body + if (book.type != BookType.file) { + scope.ensureActive() + Debug.log(bookSource.bookSourceUrl, "┌获取目录链接") + book.tocUrl = analyzeRule.getString(infoRule.tocUrl, isUrl = true) + if (book.tocUrl.isEmpty()) book.tocUrl = baseUrl + if (book.tocUrl == baseUrl) { + book.tocHtml = body + } + Debug.log(bookSource.bookSourceUrl, "└${book.tocUrl}") + } else { + scope.ensureActive() + Debug.log(bookSource.bookSourceUrl, "┌获取文件下载链接") + book.downloadUrls = analyzeRule.getStringList(infoRule.downloadUrls, isUrl = true) + Debug.log( + bookSource.bookSourceUrl, + "└" + TextUtils.join(",\n", book.downloadUrls!!) + ) } - Debug.log(bookSource.bookSourceUrl, "└${book.tocUrl}") } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt new file mode 100644 index 000000000..bfe435c0d --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt @@ -0,0 +1,152 @@ +package io.legado.app.ui.association + +import android.annotation.SuppressLint +import android.content.Context +import android.content.DialogInterface +import android.os.Bundle +import android.view.View +import android.view.ViewGroup +import android.net.Uri +import androidx.fragment.app.viewModels +import androidx.recyclerview.widget.LinearLayoutManager +import io.legado.app.R +import io.legado.app.base.BaseDialogFragment +import io.legado.app.base.adapter.ItemViewHolder +import io.legado.app.base.adapter.RecyclerAdapter +import io.legado.app.databinding.DialogRecyclerViewBinding +import io.legado.app.databinding.ItemBookFileImportBinding +import io.legado.app.help.config.AppConfig +import io.legado.app.lib.dialogs.alert +import io.legado.app.lib.theme.primaryColor +import io.legado.app.ui.widget.dialog.WaitDialog +import io.legado.app.utils.* +import io.legado.app.utils.viewbindingdelegate.viewBinding +import splitties.views.onClick + + +/** + * 导入在线书籍文件弹出窗口 + */ +class ImportOnLineBookFileDialog() : BaseDialogFragment(R.layout.dialog_recycler_view) { + + + private val binding by viewBinding(DialogRecyclerViewBinding::bind) + private val viewModel by viewModels() + private val adapter by lazy { BookFileAdapter(requireContext()) } + + override fun onStart() { + super.onStart() + setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + } + + @SuppressLint("NotifyDataSetChanged") + override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { + val bookUrl = arguments?.getString("bookUrl") + val infoHtml = arguments?.getString("infoHtml") + viewModel.initData(bookUrl, infoHtml) + binding.toolBar.setBackgroundColor(primaryColor) + //标题 + binding.toolBar.setTitle("导入在线书籍文件") + binding.rotateLoading.show() + binding.recyclerView.layoutManager = LinearLayoutManager(requireContext()) + binding.recyclerView.adapter = adapter + binding.tvCancel.visible() + binding.tvCancel.setOnClickListener { + dismissAllowingStateLoss() + } + binding.tvOk.visible() + binding.tvOk.setOnClickListener { + val waitDialog = WaitDialog(requireContext()) + waitDialog.show() + viewModel.importSelect { + waitDialog.dismiss() + dismissAllowingStateLoss() + } + } + binding.tvFooterLeft.visible() + binding.tvFooterLeft.setOnClickListener { + val selectAll = viewModel.isSelectAll + viewModel.selectStatus.forEachIndexed { index, b -> + if (b != !selectAll) { + viewModel.selectStatus[index] = !selectAll + } + } + adapter.notifyDataSetChanged() + upSelectText() + } + adapter.setItems(viewModel.allBookFiles) + upSelectText() + } + + private fun upSelectText() { + if (viewModel.isSelectAll) { + binding.tvFooterLeft.text = getString( + R.string.select_cancel_count, + viewModel.selectCount, + viewModel.allBookFiles.size + ) + } else { + binding.tvFooterLeft.text = getString( + R.string.select_all_count, + viewModel.selectCount, + viewModel.allBookFiles.size + ) + } + } + + inner class BookFileAdapter(context: Context) : + RecyclerAdapter +, ItemBookFileImportBinding>(context) { + + override fun getViewBinding(parent: ViewGroup): ItemBookFileImportBinding { + return ItemBookFileImportBinding.inflate(inflater, parent, false) + } + + override fun convert( + holder: ItemViewHolder, + binding: ItemBookFileImportBinding, + item: Triple, + payloads: MutableList + ) { + binding.apply { + cbFileName.isChecked = viewModel.selectStatus[holder.layoutPosition] + cbFileName.text = item.second + if (item.third) { + tvOpen.invisible() + } else { + tvOpen.visible() + } + } + } + + override fun registerListener(holder: ItemViewHolder, binding: ItemBookFileImportBinding) { + binding.apply { + cbFileName.setOnCheckedChangeListener { buttonView, isChecked -> + if (buttonView.isPressed) { + val selectFile = viewModel.allBookFiles[holder.layoutPosition] + if (selectFile.third) { + viewModel.selectStatus[holder.layoutPosition] = isChecked + } else { + toastOnUi("不支持直接导入") + } + upSelectText() + } + } + root.onClick { + cbFileName.isChecked = !cbFileName.isChecked + viewModel.selectStatus[holder.layoutPosition] = cbFileName.isChecked + upSelectText() + } + tvOpen.setOnClickListener { + val bookFile = viewModel.allBookFiles[holder.layoutPosition] + //intent解压 + viewModel.downloadUrl(bookFile.first, bookFile.second) { + //openFileUri(it) + } + } + } + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt new file mode 100644 index 000000000..a05c34e93 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt @@ -0,0 +1,112 @@ +package io.legado.app.ui.association + +import android.app.Application +import android.net.Uri +import androidx.lifecycle.MutableLiveData +import io.legado.app.R +import io.legado.app.base.BaseViewModel +import io.legado.app.constant.AppPattern +import io.legado.app.constant.AppLog +import io.legado.app.data.appDb +import io.legado.app.data.entities.Book +import io.legado.app.exception.NoStackTraceException +import io.legado.app.model.analyzeRule.AnalyzeRule +import io.legado.app.model.analyzeRule.AnalyzeUrl +import io.legado.app.model.localBook.LocalBook +import io.legado.app.utils.* + +class ImportOnLineBookFileViewModel(app: Application) : BaseViewModel(app) { + + val allBookFiles = arrayListOf>() + val selectStatus = arrayListOf() + + fun initData(bookUrl: String?, infoHtml: String?) { + execute { + bookUrl ?: throw NoStackTraceException("书籍详情页链接为空") + val book = appDb.searchBookDao.getSearchBook(bookUrl)?.toBook() + ?: throw NoStackTraceException("book is null") + val bookSource = appDb.bookSourceDao.getBookSource(book.origin) + ?: throw NoStackTraceException("bookSource is null") + val ruleDownloadUrls = bookSource?.getBookInfoRule()?.downloadUrls + var content = infoHtml + if (content.isNullOrBlank()) { + content = AnalyzeUrl(bookUrl, source = bookSource).getStrResponse().body + } + val analyzeRule = AnalyzeRule(book, bookSource) + analyzeRule.setContent(content).setBaseUrl(bookUrl) + analyzeRule.getStringList(ruleDownloadUrls, isUrl = true)?.let { + it.forEach { url -> + val fileName = LocalBook.extractDownloadName(url, book) + val isSupportedFile = AppPattern.bookFileRegex.matches(fileName) + allBookFiles.add(Triple(url, fileName, isSupportedFile)) + selectStatus.add(isSupportedFile) + } + } ?: throw NoStackTraceException("下载链接规则解析为空") + }.onError { + context.toastOnUi("获取书籍下载链接失败\n${it.localizedMessage}") + } + + } + + val isSelectAll: Boolean + get() { + selectStatus.forEach { + if (!it) { + return false + } + } + return true + } + + val selectCount: Int + get() { + var count = 0 + selectStatus.forEach { + if (it) { + count++ + } + } + return count + } + + fun importSelect(success: () -> Unit) { + execute { + selectStatus.forEachIndexed { index, selected -> + if (selected) { + val selectedFile = allBookFiles[index] + val isSupportedFile = selectedFile.third + val fileUrl: String = selectedFile.first + val fileName: String = selectedFile.second + when { + isSupportedFile -> importOnLineBookFile(fileUrl, fileName) + else -> { + downloadUrl(fileUrl, fileName) { + // AppLog.putDebug("下载文件路径: ${it.toString()}") + } + } + } + } + } + }.onSuccess { + success.invoke() + }.onError { + + } + } + + + fun downloadUrl(url: String, fileName: String, success: () -> Unit) { + execute { + LocalBook.saveBookFile(url, fileName) + }.onSuccess { + success.invoke() + }.onError { + context.toastOnUi("下载书籍文件失败\n${it.localizedMessage}") + } + } + + fun importOnLineBookFile(url: String, fileName: String) { + LocalBook.importFileOnLine(url, fileName) + } + +} diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt index dfad88975..f94345da5 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt @@ -25,6 +25,7 @@ import io.legado.app.lib.theme.bottomBackground import io.legado.app.lib.theme.getPrimaryTextColor import io.legado.app.model.BookCover import io.legado.app.ui.about.AppLogDialog +import io.legado.app.ui.association.ImportOnLineBookFileDialog import io.legado.app.ui.book.audio.AudioPlayActivity import io.legado.app.ui.book.changecover.ChangeCoverDialog import io.legado.app.ui.book.changesource.ChangeBookSourceDialog @@ -278,11 +279,14 @@ class BookInfoActivity : true } tvRead.setOnClickListener { - viewModel.bookData.value?.let { + viewModel.bookData.value?.let { book -> if (viewModel.isImportBookOnLine) { - viewModel.importBookFileOnLine() + showDialogFragment { + putString("bookUrl", book.bookUrl) + putString("infoHtml", book.infoHtml) + } } else { - readBook(it) + readBook(book) } } ?: toastOnUi("Book is null") } diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt index 7a029f588..f8506ece9 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt @@ -2,6 +2,7 @@ package io.legado.app.ui.book.info import android.app.Application import android.content.Intent +import android.net.Uri import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import io.legado.app.R @@ -290,27 +291,13 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { } } - fun importBookFileOnLine() { - execute { - //下载类书源的目录链接视为文件链接 - val book = bookData.value!! - val fileUrl = book.tocUrl - //切下载链接获取文件名 - var fileName = fileUrl.substringAfterLast("/") - if (fileName.isEmpty()) { - fileName = book.name - } - LocalBook.importFile(fileUrl, fileName, bookSource, book) - }.onSuccess { - bookData.postValue(it) - LocalBook.getChapterList(it).let { toc -> - chapterListData.postValue(toc) - } - isImportBookOnLine = false - inBookshelf = true - }.onError { - context.toastOnUi("自动导入出错\n${it.localizedMessage}") + private fun changeToLocalBook(book: Book) { + bookData.postValue(book) + LocalBook.getChapterList(book).let { + chapterListData.postValue(it) } + isImportBookOnLine = false + inBookshelf = true } } \ No newline at end of file diff --git a/app/src/main/res/layout/item_book_file_import.xml b/app/src/main/res/layout/item_book_file_import.xml new file mode 100644 index 000000000..88291196c --- /dev/null +++ b/app/src/main/res/layout/item_book_file_import.xml @@ -0,0 +1,34 @@ + + + + + + + + + \ No newline at end of file From d2887c1b5d4ade5479c0f3cca2acaf0b26a9d4c1 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Sat, 14 May 2022 16:05:36 +0800 Subject: [PATCH 06/12] =?UTF-8?q?fix:=E6=96=87=E4=BB=B6=E7=B1=BB=E4=B9=A6?= =?UTF-8?q?=E6=BA=90=E8=B7=B3=E8=BF=87=E7=9B=AE=E5=BD=95=E6=AD=A3=E6=96=87?= =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/io/legado/app/model/Debug.kt | 7 ++++++- .../java/io/legado/app/model/webBook/BookInfo.kt | 13 +++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/io/legado/app/model/Debug.kt b/app/src/main/java/io/legado/app/model/Debug.kt index 9be322adc..8cab89c29 100644 --- a/app/src/main/java/io/legado/app/model/Debug.kt +++ b/app/src/main/java/io/legado/app/model/Debug.kt @@ -2,6 +2,7 @@ package io.legado.app.model import android.annotation.SuppressLint import io.legado.app.constant.AppPattern +import io.legado.app.constant.BookType import io.legado.app.data.entities.* import io.legado.app.help.coroutine.CompositeCoroutine import io.legado.app.model.rss.Rss @@ -238,7 +239,11 @@ object Debug { .onSuccess { log(debugSource, "︽详情页解析完成") log(debugSource, showTime = false) - tocDebug(scope, bookSource, book) + if (book.type != BookType.file) { + tocDebug(scope, bookSource, book) + } else { + log(debugSource, "≡文件类书源跳过解析目录", state = 1000) + } } .onError { log(debugSource, it.msg, state = -1) diff --git a/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt b/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt index 53847ea52..9595b1079 100644 --- a/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt +++ b/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt @@ -152,10 +152,15 @@ object BookInfo { scope.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取文件下载链接") book.downloadUrls = analyzeRule.getStringList(infoRule.downloadUrls, isUrl = true) - Debug.log( - bookSource.bookSourceUrl, - "└" + TextUtils.join(",\n", book.downloadUrls!!) - ) + if (book.downloadUrls == null) { + Debug.log(bookSource.bookSourceUrl, "└") + throw NoStackTraceException("下载链接为空") + } else { + Debug.log( + bookSource.bookSourceUrl, + "└" + TextUtils.join(",\n", book.downloadUrls!!) + ) + } } } From d7307c2343f63ca5c4c84fdd08fe028b1d2deda5 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Sat, 14 May 2022 16:39:10 +0800 Subject: [PATCH 07/12] =?UTF-8?q?fix:=E4=BC=98=E5=8C=96=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E5=92=8C=E8=B0=83=E6=95=B4=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/legado/app/constant/EventBus.kt | 1 + .../legado/app/model/localBook/LocalBook.kt | 31 ++--- .../association/ImportOnLineBookFileDialog.kt | 118 ++++++++---------- .../ImportOnLineBookFileViewModel.kt | 76 ++++------- .../app/ui/book/info/BookInfoActivity.kt | 7 +- .../app/ui/book/info/BookInfoViewModel.kt | 19 ++- .../main/res/layout/item_book_file_import.xml | 19 +-- app/src/main/res/values-es-rES/strings.xml | 2 + app/src/main/res/values-ja-rJP/strings.xml | 2 + app/src/main/res/values-pt-rBR/strings.xml | 2 + app/src/main/res/values-zh-rHK/strings.xml | 2 + app/src/main/res/values-zh-rTW/strings.xml | 2 + app/src/main/res/values-zh/strings.xml | 1 + app/src/main/res/values/strings.xml | 2 + 14 files changed, 117 insertions(+), 167 deletions(-) diff --git a/app/src/main/java/io/legado/app/constant/EventBus.kt b/app/src/main/java/io/legado/app/constant/EventBus.kt index 18be386c5..df3d6017a 100644 --- a/app/src/main/java/io/legado/app/constant/EventBus.kt +++ b/app/src/main/java/io/legado/app/constant/EventBus.kt @@ -28,4 +28,5 @@ object EventBus { const val TIP_COLOR = "tipColor" const val SOURCE_CHANGED = "sourceChanged" const val SEARCH_RESULT = "searchResult" + const val BOOK_URL_CHANGED = "bookUrlChanged" } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt index 68b95c9e3..0cac6f128 100644 --- a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt +++ b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt @@ -94,13 +94,11 @@ object LocalBook { */ fun importFileOnLine( str: String, - fileName: String? = null, + fileName: String, source: BaseSource? = null, - onLineBook: Book? = null ): Book { - val fileUri = saveBookFile(str, fileName, source, onLineBook) - return importFile(fileUri).let { - mergeBook(it, onLineBook) + return saveBookFile(str, fileName, source).let { + importFile(it) } } @@ -205,41 +203,32 @@ object LocalBook { /** * 下载在线的文件 - * fileName为空时 传入onLineBook */ fun saveBookFile( str: String, - fileName: String? = null, + fileName: String, source: BaseSource? = null, - onLineBook: Book? = null ): Uri { val bytes = when { str.isAbsUrl() -> AnalyzeUrl(str, source = source).getByteArray() str.isDataUrl() -> Base64.decode(str.substringAfter("base64,"), Base64.DEFAULT) else -> throw NoStackTraceException("在线导入书籍支持http/https/DataURL") } - val mFileName = fileName ?: extractDownloadName(str, onLineBook) - return saveBookFile(bytes, mFileName) + return saveBookFile(bytes, fileName) } /** - * 分析下载文件类书源的下载链接 + * 分析下载文件类书源的下载链接的文件后缀 * https://www.example.com/download/{fileName}.{type} 含有文件名和后缀 - * https://www.example.com/download/?fileid=1234, {type: "txt"} + * https://www.example.com/download/?fileid=1234, {type: "txt"} 规则设置 */ - fun extractDownloadName(uri: String, onLineBook: Book?): String { - val analyzeUrl = AnalyzeUrl(uri) + fun parseFileSuffix(url: String): String { + val analyzeUrl = AnalyzeUrl(url) val urlNoOption = analyzeUrl.url val lastPath = urlNoOption.substringAfterLast("/") val fileType = lastPath.substringAfterLast(".") val type = analyzeUrl.type - val fileName = when { - onLineBook != null -> "${onLineBook.name}_${onLineBook.author}_${onLineBook.origin}" - type == null-> lastPath - else -> lastPath.substringBeforeLast(".") - } - val fileSuffix = fileType ?: type ?: "unknown" - return "${fileName}.${fileSuffix}" + return type ?: fileType ?: "unknown" } private fun saveBookFile( diff --git a/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt index bfe435c0d..667be6b10 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt @@ -1,6 +1,5 @@ package io.legado.app.ui.association -import android.annotation.SuppressLint import android.content.Context import android.content.DialogInterface import android.os.Bundle @@ -21,7 +20,6 @@ import io.legado.app.lib.theme.primaryColor import io.legado.app.ui.widget.dialog.WaitDialog import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding -import splitties.views.onClick /** @@ -39,61 +37,50 @@ class ImportOnLineBookFileDialog() : BaseDialogFragment(R.layout.dialog_recycler setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) } - @SuppressLint("NotifyDataSetChanged") override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { val bookUrl = arguments?.getString("bookUrl") - val infoHtml = arguments?.getString("infoHtml") - viewModel.initData(bookUrl, infoHtml) + viewModel.initData(bookUrl) binding.toolBar.setBackgroundColor(primaryColor) - //标题 - binding.toolBar.setTitle("导入在线书籍文件") + binding.toolBar.setTitle(R.string.download_and_import_file) binding.rotateLoading.show() binding.recyclerView.layoutManager = LinearLayoutManager(requireContext()) binding.recyclerView.adapter = adapter - binding.tvCancel.visible() - binding.tvCancel.setOnClickListener { - dismissAllowingStateLoss() - } - binding.tvOk.visible() - binding.tvOk.setOnClickListener { - val waitDialog = WaitDialog(requireContext()) - waitDialog.show() - viewModel.importSelect { - waitDialog.dismiss() - dismissAllowingStateLoss() + viewModel.errorLiveData.observe(this) { + binding.rotateLoading.hide() + binding.tvMsg.apply { + text = it + visible() } } - binding.tvFooterLeft.visible() - binding.tvFooterLeft.setOnClickListener { - val selectAll = viewModel.isSelectAll - viewModel.selectStatus.forEachIndexed { index, b -> - if (b != !selectAll) { - viewModel.selectStatus[index] = !selectAll - } + viewModel.successLiveData.observe(this) { + binding.rotateLoading.hide() + if (it > 0) { + adapter.setItems(viewModel.allBookFiles) } - adapter.notifyDataSetChanged() - upSelectText() } - adapter.setItems(viewModel.allBookFiles) - upSelectText() + viewModel.savedFileUriData.observe(this) { + requireContext().openFileUri(it, "*/*") + } } - private fun upSelectText() { - if (viewModel.isSelectAll) { - binding.tvFooterLeft.text = getString( - R.string.select_cancel_count, - viewModel.selectCount, - viewModel.allBookFiles.size - ) - } else { - binding.tvFooterLeft.text = getString( - R.string.select_all_count, - viewModel.selectCount, - viewModel.allBookFiles.size - ) + private fun importFileAndUpdate(url: String, fileName: String) { + val waitDialog = WaitDialog(requireContext()) + waitDialog.show() + viewModel.importOnLineBookFile(url, fileName) { + waitDialog.dismiss() + dismissAllowingStateLoss() } } + private fun downloadFile(url: String, fileName: String) { + val waitDialog = WaitDialog(requireContext()) + waitDialog.show() + viewModel.downloadUrl(url, fileName) { + waitDialog.dismiss() + dismissAllowingStateLoss() + } +} + inner class BookFileAdapter(context: Context) : RecyclerAdapter , ItemBookFileImportBinding>(context) { @@ -109,39 +96,32 @@ class ImportOnLineBookFileDialog() : BaseDialogFragment(R.layout.dialog_recycler payloads: MutableList ) { binding.apply { - cbFileName.isChecked = viewModel.selectStatus[holder.layoutPosition] cbFileName.text = item.second - if (item.third) { - tvOpen.invisible() - } else { - tvOpen.visible() - } } } - override fun registerListener(holder: ItemViewHolder, binding: ItemBookFileImportBinding) { + override fun registerListener( + holder: ItemViewHolder, + binding: ItemBookFileImportBinding + ) { binding.apply { - cbFileName.setOnCheckedChangeListener { buttonView, isChecked -> - if (buttonView.isPressed) { - val selectFile = viewModel.allBookFiles[holder.layoutPosition] - if (selectFile.third) { - viewModel.selectStatus[holder.layoutPosition] = isChecked - } else { - toastOnUi("不支持直接导入") + cbFileName.setOnClickListener { + val selectFile = viewModel.allBookFiles[holder.layoutPosition] + if (selectFile.third) { + importFileAndUpdate(selectFile.first, selectFile.second) + } else { + alert( + title = getString(R.string.draw), + message = getString(R.string.file_not_supported, selectFile.second) + ) { + okButton { + importFileAndUpdate(selectFile.first, selectFile.second) + } + neutralButton(R.string.open_fun) { + downloadFile(selectFile.first, selectFile.second) + } + cancelButton() } - upSelectText() - } - } - root.onClick { - cbFileName.isChecked = !cbFileName.isChecked - viewModel.selectStatus[holder.layoutPosition] = cbFileName.isChecked - upSelectText() - } - tvOpen.setOnClickListener { - val bookFile = viewModel.allBookFiles[holder.layoutPosition] - //intent解压 - viewModel.downloadUrl(bookFile.first, bookFile.second) { - //openFileUri(it) } } } diff --git a/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt index a05c34e93..bfa3370e9 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt @@ -7,6 +7,7 @@ import io.legado.app.R import io.legado.app.base.BaseViewModel import io.legado.app.constant.AppPattern import io.legado.app.constant.AppLog +import io.legado.app.constant.EventBus import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.exception.NoStackTraceException @@ -18,9 +19,11 @@ import io.legado.app.utils.* class ImportOnLineBookFileViewModel(app: Application) : BaseViewModel(app) { val allBookFiles = arrayListOf>() - val selectStatus = arrayListOf() + val errorLiveData = MutableLiveData() + val successLiveData = MutableLiveData() + val savedFileUriData = MutableLiveData() - fun initData(bookUrl: String?, infoHtml: String?) { + fun initData(bookUrl: String?) { execute { bookUrl ?: throw NoStackTraceException("书籍详情页链接为空") val book = appDb.searchBookDao.getSearchBook(bookUrl)?.toBook() @@ -28,85 +31,48 @@ class ImportOnLineBookFileViewModel(app: Application) : BaseViewModel(app) { val bookSource = appDb.bookSourceDao.getBookSource(book.origin) ?: throw NoStackTraceException("bookSource is null") val ruleDownloadUrls = bookSource?.getBookInfoRule()?.downloadUrls - var content = infoHtml - if (content.isNullOrBlank()) { - content = AnalyzeUrl(bookUrl, source = bookSource).getStrResponse().body - } + val content = AnalyzeUrl(bookUrl, source = bookSource).getStrResponse().body val analyzeRule = AnalyzeRule(book, bookSource) analyzeRule.setContent(content).setBaseUrl(bookUrl) + val fileName = "${book.name} 作者:${book.author}" analyzeRule.getStringList(ruleDownloadUrls, isUrl = true)?.let { it.forEach { url -> - val fileName = LocalBook.extractDownloadName(url, book) val isSupportedFile = AppPattern.bookFileRegex.matches(fileName) - allBookFiles.add(Triple(url, fileName, isSupportedFile)) - selectStatus.add(isSupportedFile) + val mFileName = "${fileName}.${LocalBook.parseFileSuffix(url)}" + allBookFiles.add(Triple(url, mFileName, isSupportedFile)) } } ?: throw NoStackTraceException("下载链接规则解析为空") + }.onSuccess { + successLiveData.postValue(allBookFiles.size) }.onError { + errorLiveData.postValue(it.localizedMessage ?: "") context.toastOnUi("获取书籍下载链接失败\n${it.localizedMessage}") } } - val isSelectAll: Boolean - get() { - selectStatus.forEach { - if (!it) { - return false - } - } - return true - } - - val selectCount: Int - get() { - var count = 0 - selectStatus.forEach { - if (it) { - count++ - } - } - return count - } - - fun importSelect(success: () -> Unit) { + fun downloadUrl(url: String, fileName: String, success: () -> Unit) { execute { - selectStatus.forEachIndexed { index, selected -> - if (selected) { - val selectedFile = allBookFiles[index] - val isSupportedFile = selectedFile.third - val fileUrl: String = selectedFile.first - val fileName: String = selectedFile.second - when { - isSupportedFile -> importOnLineBookFile(fileUrl, fileName) - else -> { - downloadUrl(fileUrl, fileName) { - // AppLog.putDebug("下载文件路径: ${it.toString()}") - } - } - } - } + LocalBook.saveBookFile(url, fileName).let { + savedFileUriData.postValue(it) } }.onSuccess { success.invoke() }.onError { - + context.toastOnUi("下载书籍文件失败\n${it.localizedMessage}") } } - - fun downloadUrl(url: String, fileName: String, success: () -> Unit) { + fun importOnLineBookFile(url: String, fileName: String, success: () -> Unit) { execute { - LocalBook.saveBookFile(url, fileName) + LocalBook.importFileOnLine(url, fileName).let { + postEvent(EventBus.BOOK_URL_CHANGED, it.bookUrl) + } }.onSuccess { - success.invoke() + success.invoke() }.onError { context.toastOnUi("下载书籍文件失败\n${it.localizedMessage}") } } - fun importOnLineBookFile(url: String, fileName: String) { - LocalBook.importFileOnLine(url, fileName) - } - } diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt index f94345da5..56e2bd5d7 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt @@ -12,6 +12,7 @@ import androidx.activity.viewModels import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.BookType +import io.legado.app.constant.EventBus import io.legado.app.constant.Theme import io.legado.app.data.appDb import io.legado.app.data.entities.Book @@ -283,7 +284,6 @@ class BookInfoActivity : if (viewModel.isImportBookOnLine) { showDialogFragment { putString("bookUrl", book.bookUrl) - putString("infoHtml", book.infoHtml) } } else { readBook(book) @@ -490,4 +490,9 @@ class BookInfoActivity : } } + override fun observeLiveBus() { + observeEvent(EventBus.BOOK_URL_CHANGED) { + viewModel.changeToLocalBook(it) + } + } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt index f8506ece9..8303d8357 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt @@ -119,6 +119,9 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { WebBook.getBookInfo(this, bookSource, book, canReName = canReName) .onSuccess(IO) { bookData.postValue(book) + if (isImportBookOnLine) { + appDb.searchBookDao.update(book.toSearchBook()) + } if (inBookshelf) { appDb.bookDao.update(book) } @@ -291,13 +294,17 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { } } - private fun changeToLocalBook(book: Book) { - bookData.postValue(book) - LocalBook.getChapterList(book).let { - chapterListData.postValue(it) + fun changeToLocalBook(bookUrl: String) { + appDb.bookDao.getBook(bookUrl)?.let { localBook -> + LocalBook.mergeBook(localBook, bookData.value).let { + bookData.postValue(it) + } + LocalBook.getChapterList(localBook).let { + chapterListData.postValue(it) + } + isImportBookOnLine = false + inBookshelf = true } - isImportBookOnLine = false - inBookshelf = true } } \ No newline at end of file diff --git a/app/src/main/res/layout/item_book_file_import.xml b/app/src/main/res/layout/item_book_file_import.xml index 88291196c..8f584c1a4 100644 --- a/app/src/main/res/layout/item_book_file_import.xml +++ b/app/src/main/res/layout/item_book_file_import.xml @@ -6,11 +6,12 @@ android:layout_height="wrap_content" android:padding="8dp"> - - - - - \ No newline at end of file + diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index 030c5335e..741265978 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -981,5 +981,7 @@ CookieJar 点击阅读加载目录 清除cookie + 导入在线书籍文件 + diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index 1cfcb0d47..e24e9b362 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -984,5 +984,7 @@ CookieJar 点击阅读加载目录 清除cookie + 导入在线书籍文件 + diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 1293cedc9..95fb2ec20 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -984,5 +984,7 @@ CookieJar 点击阅读加载目录 清除cookie + 导入在线书籍文件 + diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 94805b80d..3b97eaf2b 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -981,5 +981,7 @@ CookieJar 点击阅读加载目录 清除cookie + 导入在线书籍文件 + diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 7dea2e10e..975d7dbba 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -983,5 +983,7 @@ CookieJar 点击阅读加载目录 清除cookie + 导入在线书籍文件 + diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index b20df127c..018ccb9d8 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -983,5 +983,6 @@ CookieJar 点击阅读加载目录 清除cookie + 导入在线书籍文件 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6799fca04..d582253cd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -984,5 +984,7 @@ CookieJar 点击阅读加载目录 清除cookie + 导入在线书籍文件 + From bfdd54bec0b5115b9b9d32304b74401210f0e946 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Sun, 15 May 2022 08:10:22 +0800 Subject: [PATCH 08/12] =?UTF-8?q?feat:=E5=85=B6=E4=BB=96=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=E5=A4=84=E7=90=86=E6=96=87=E4=BB=B6=E5=90=8E=E6=89=93=E5=BC=80?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9C=AC=E5=9C=B0=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/legado/app/ui/association/ImportOnLineBookFileDialog.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt index 667be6b10..6c4c3f723 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt @@ -18,6 +18,7 @@ import io.legado.app.help.config.AppConfig import io.legado.app.lib.dialogs.alert import io.legado.app.lib.theme.primaryColor import io.legado.app.ui.widget.dialog.WaitDialog +import io.legado.app.ui.book.local.ImportBookActivity import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding @@ -60,6 +61,7 @@ class ImportOnLineBookFileDialog() : BaseDialogFragment(R.layout.dialog_recycler } viewModel.savedFileUriData.observe(this) { requireContext().openFileUri(it, "*/*") + startActivity() } } From 4ac1c916c159e4939955bfe9f25ba0a60fc9ca50 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Sun, 15 May 2022 08:12:26 +0800 Subject: [PATCH 09/12] =?UTF-8?q?fix:=E4=B8=8B=E8=BD=BD=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=97=B6=E6=B7=BB=E5=8A=A0=E4=B9=A6=E6=BA=90=E7=9A=84=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E5=A4=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/ui/association/ImportOnLineBookFileViewModel.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt index bfa3370e9..3ece288ad 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt @@ -10,6 +10,7 @@ import io.legado.app.constant.AppLog import io.legado.app.constant.EventBus import io.legado.app.data.appDb import io.legado.app.data.entities.Book +import io.legado.app.data.entities.BookSource import io.legado.app.exception.NoStackTraceException import io.legado.app.model.analyzeRule.AnalyzeRule import io.legado.app.model.analyzeRule.AnalyzeUrl @@ -22,13 +23,14 @@ class ImportOnLineBookFileViewModel(app: Application) : BaseViewModel(app) { val errorLiveData = MutableLiveData() val successLiveData = MutableLiveData() val savedFileUriData = MutableLiveData() + var bookSource: BookSource? = null fun initData(bookUrl: String?) { execute { bookUrl ?: throw NoStackTraceException("书籍详情页链接为空") val book = appDb.searchBookDao.getSearchBook(bookUrl)?.toBook() ?: throw NoStackTraceException("book is null") - val bookSource = appDb.bookSourceDao.getBookSource(book.origin) + bookSource = appDb.bookSourceDao.getBookSource(book.origin) ?: throw NoStackTraceException("bookSource is null") val ruleDownloadUrls = bookSource?.getBookInfoRule()?.downloadUrls val content = AnalyzeUrl(bookUrl, source = bookSource).getStrResponse().body @@ -53,7 +55,7 @@ class ImportOnLineBookFileViewModel(app: Application) : BaseViewModel(app) { fun downloadUrl(url: String, fileName: String, success: () -> Unit) { execute { - LocalBook.saveBookFile(url, fileName).let { + LocalBook.saveBookFile(url, fileName, bookSource).let { savedFileUriData.postValue(it) } }.onSuccess { @@ -65,7 +67,7 @@ class ImportOnLineBookFileViewModel(app: Application) : BaseViewModel(app) { fun importOnLineBookFile(url: String, fileName: String, success: () -> Unit) { execute { - LocalBook.importFileOnLine(url, fileName).let { + LocalBook.importFileOnLine(url, fileName, bookSource).let { postEvent(EventBus.BOOK_URL_CHANGED, it.bookUrl) } }.onSuccess { From 6e0b2b0c5e6bf17aecd79f40c0249df0350fcaf9 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Sun, 15 May 2022 08:28:43 +0800 Subject: [PATCH 10/12] =?UTF-8?q?Revert=20"feat:=E5=85=B6=E4=BB=96?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E5=A4=84=E7=90=86=E6=96=87=E4=BB=B6=E5=90=8E?= =?UTF-8?q?=E6=89=93=E5=BC=80=E6=B7=BB=E5=8A=A0=E6=9C=AC=E5=9C=B0=E7=95=8C?= =?UTF-8?q?=E9=9D=A2"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit bfdd54bec0b5115b9b9d32304b74401210f0e946. --- .../io/legado/app/ui/association/ImportOnLineBookFileDialog.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt index 6c4c3f723..667be6b10 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileDialog.kt @@ -18,7 +18,6 @@ import io.legado.app.help.config.AppConfig import io.legado.app.lib.dialogs.alert import io.legado.app.lib.theme.primaryColor import io.legado.app.ui.widget.dialog.WaitDialog -import io.legado.app.ui.book.local.ImportBookActivity import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding @@ -61,7 +60,6 @@ class ImportOnLineBookFileDialog() : BaseDialogFragment(R.layout.dialog_recycler } viewModel.savedFileUriData.observe(this) { requireContext().openFileUri(it, "*/*") - startActivity() } } From b1ff349cc5bb698b4c099eca2adb8511a0ce4a6a Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Sun, 15 May 2022 10:07:23 +0800 Subject: [PATCH 11/12] =?UTF-8?q?fix:=E7=9B=B4=E6=8E=A5=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E7=9A=84=E6=96=87=E4=BB=B6=E7=B1=BB=E5=9E=8B=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../legado/app/ui/association/ImportOnLineBookFileViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt index 3ece288ad..d601cd20e 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportOnLineBookFileViewModel.kt @@ -39,8 +39,8 @@ class ImportOnLineBookFileViewModel(app: Application) : BaseViewModel(app) { val fileName = "${book.name} 作者:${book.author}" analyzeRule.getStringList(ruleDownloadUrls, isUrl = true)?.let { it.forEach { url -> - val isSupportedFile = AppPattern.bookFileRegex.matches(fileName) val mFileName = "${fileName}.${LocalBook.parseFileSuffix(url)}" + val isSupportedFile = AppPattern.bookFileRegex.matches(mFileName) allBookFiles.add(Triple(url, mFileName, isSupportedFile)) } } ?: throw NoStackTraceException("下载链接规则解析为空") From a6fb244b556b2377fb99c3bfe0e1d7156993333c Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Sun, 15 May 2022 10:23:06 +0800 Subject: [PATCH 12/12] =?UTF-8?q?fix:=E7=9B=AE=E5=BD=95=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E7=A9=BA=E7=99=BDbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/legado/app/ui/book/info/BookInfoViewModel.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt index 8303d8357..b60fbfa43 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt @@ -296,14 +296,12 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { fun changeToLocalBook(bookUrl: String) { appDb.bookDao.getBook(bookUrl)?.let { localBook -> + isImportBookOnLine = false + inBookshelf = true LocalBook.mergeBook(localBook, bookData.value).let { bookData.postValue(it) + loadChapter(it) } - LocalBook.getChapterList(localBook).let { - chapterListData.postValue(it) - } - isImportBookOnLine = false - inBookshelf = true } }