diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index f3d242231..bea3064fa 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -3,7 +3,7 @@ * 关注合作公众号 **[小说拾遗]()** 获取好看的小说。 * 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。 -**2020/11/06** +**2020/11/07** * 详情页菜单添加拷贝URL * 解决一些书名太长缓存报错的bug * 添加备份搜索记录 diff --git a/app/src/main/java/io/legado/app/help/AppConfig.kt b/app/src/main/java/io/legado/app/help/AppConfig.kt index 82afe6a8b..e2831a80f 100644 --- a/app/src/main/java/io/legado/app/help/AppConfig.kt +++ b/app/src/main/java/io/legado/app/help/AppConfig.kt @@ -131,5 +131,8 @@ object AppConfig { App.INSTANCE.getPrefBoolean(PreferKey.replaceEnableDefault, true) } + val changeSourceLoadInfo get() = App.INSTANCE.getPrefBoolean(PreferKey.changeSourceLoadToc) + + val changeSourceLoadToc get() = App.INSTANCE.getPrefBoolean(PreferKey.changeSourceLoadToc) } diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt index 0d13ee94d..5296196ce 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt @@ -17,8 +17,7 @@ import javax.script.SimpleBindings import kotlin.collections.HashMap /** - * Created by REFGD. - * 统一解析接口 + * 解析规则获取结果 */ @Keep @Suppress("unused", "RegExpRedundantEscape") @@ -38,11 +37,11 @@ class AnalyzeRule(var book: BaseBook? = null) : JsExtensions { private var objectChangedJS = false private var objectChangedJP = false - @Throws(Exception::class) - fun setContent(content: Any?): AnalyzeRule { + fun setContent(content: Any?, baseUrl: String? = null): AnalyzeRule { if (content == null) throw AssertionError("Content cannot be null") - isJSON = content.toString().isJson() this.content = content + setBaseUrl(baseUrl) + isJSON = content.toString().isJson() objectChangedXP = true objectChangedJS = true objectChangedJP = true @@ -50,8 +49,8 @@ class AnalyzeRule(var book: BaseBook? = null) : JsExtensions { } fun setBaseUrl(baseUrl: String?): AnalyzeRule { - this.baseUrl = baseUrl baseUrl?.let { + this.baseUrl = baseUrl try { baseURL = URL(baseUrl.substringBefore(",")) } catch (e: Exception) { @@ -118,7 +117,6 @@ class AnalyzeRule(var book: BaseBook? = null) : JsExtensions { /** * 获取文本列表 */ - @Throws(Exception::class) @JvmOverloads fun getStringList(rule: String?, isUrl: Boolean = false): List? { if (rule.isNullOrEmpty()) return null @@ -126,7 +124,6 @@ class AnalyzeRule(var book: BaseBook? = null) : JsExtensions { return getStringList(ruleList, isUrl) } - @Throws(Exception::class) fun getStringList(ruleList: List, isUrl: Boolean = false): List? { var result: Any? = null val content = this.content @@ -184,14 +181,12 @@ class AnalyzeRule(var book: BaseBook? = null) : JsExtensions { /** * 获取文本 */ - @Throws(Exception::class) fun getString(ruleStr: String?, isUrl: Boolean = false): String { if (TextUtils.isEmpty(ruleStr)) return "" val ruleList = splitSourceRule(ruleStr) return getString(ruleList, isUrl) } - @Throws(Exception::class) @JvmOverloads fun getString(ruleList: List, isUrl: Boolean = false): String { var result: Any? = null @@ -244,7 +239,6 @@ class AnalyzeRule(var book: BaseBook? = null) : JsExtensions { /** * 获取Element */ - @Throws(Exception::class) fun getElement(ruleStr: String): Any? { if (TextUtils.isEmpty(ruleStr)) return null var result: Any? = null @@ -278,7 +272,6 @@ class AnalyzeRule(var book: BaseBook? = null) : JsExtensions { * 获取列表 */ @Suppress("UNCHECKED_CAST") - @Throws(Exception::class) fun getElements(ruleStr: String): List { var result: Any? = null val ruleList = splitSourceRule(ruleStr) @@ -313,7 +306,6 @@ class AnalyzeRule(var book: BaseBook? = null) : JsExtensions { /** * 保存变量 */ - @Throws(Exception::class) private fun putRule(map: Map) { for ((key, value) in map) { put(key, getString(value)) @@ -323,7 +315,6 @@ class AnalyzeRule(var book: BaseBook? = null) : JsExtensions { /** * 分离put规则 */ - @Throws(Exception::class) private fun splitPutRule(ruleStr: String, putMap: HashMap): String { var vRuleStr = ruleStr val putMatcher = putPattern.matcher(vRuleStr) @@ -359,7 +350,6 @@ class AnalyzeRule(var book: BaseBook? = null) : JsExtensions { /** * 分解规则生成规则列表 */ - @Throws(Exception::class) fun splitSourceRule(ruleStr: String?, mode: Mode = Mode.Default): List { var vRuleStr = ruleStr val ruleList = ArrayList() 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 24dd869e6..48b57a7b4 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 @@ -29,7 +29,7 @@ object BookInfo { val analyzeRule = AnalyzeRule(book) analyzeRule.setContent(body).setBaseUrl(baseUrl) infoRule.init?.let { - if (it.isNotEmpty()) { + if (it.isNotBlank()) { Debug.log(bookSource.bookSourceUrl, "≡执行详情页初始化规则") analyzeRule.setContent(analyzeRule.getElement(it)) } diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceDialog.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceDialog.kt index 6cd88dad1..17ab34970 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceDialog.kt @@ -16,9 +16,13 @@ import io.legado.app.base.BaseDialogFragment import io.legado.app.constant.PreferKey import io.legado.app.data.entities.Book import io.legado.app.data.entities.SearchBook +import io.legado.app.help.AppConfig import io.legado.app.lib.theme.primaryColor import io.legado.app.ui.widget.recycler.VerticalDivider -import io.legado.app.utils.* +import io.legado.app.utils.applyTint +import io.legado.app.utils.getSize +import io.legado.app.utils.getViewModel +import io.legado.app.utils.putPrefBoolean import kotlinx.android.synthetic.main.dialog_change_source.* @@ -81,10 +85,8 @@ class ChangeSourceDialog : BaseDialogFragment(), tool_bar.inflateMenu(R.menu.change_source) tool_bar.menu.applyTint(requireContext()) tool_bar.setOnMenuItemClickListener(this) - tool_bar.menu.findItem(R.id.menu_load_toc)?.isChecked = - getPrefBoolean(PreferKey.changeSourceLoadToc) - tool_bar.menu.findItem(R.id.menu_load_info)?.isChecked = - getPrefBoolean(PreferKey.changeSourceLoadInfo) + tool_bar.menu.findItem(R.id.menu_load_info)?.isChecked = AppConfig.changeSourceLoadInfo + tool_bar.menu.findItem(R.id.menu_load_toc)?.isChecked = AppConfig.changeSourceLoadToc } private fun initRecyclerView() { diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceViewModel.kt index 979fbc8c7..1ed25cdfe 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceViewModel.kt @@ -23,7 +23,6 @@ import kotlinx.coroutines.asCoroutineDispatcher import org.jetbrains.anko.debug import java.util.concurrent.CopyOnWriteArraySet import java.util.concurrent.Executors -import kotlin.math.min class ChangeSourceViewModel(application: Application) : BaseViewModel(application) { private val threadCount = AppConfig.threadCount @@ -39,6 +38,7 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio private val searchBooks = CopyOnWriteArraySet() private var postTime = 0L private val sendRunnable = Runnable { upAdapter() } + @Volatile private var searchIndex = -1 @@ -113,80 +113,73 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio return } searchIndex++ - val source = bookSourceList[searchIndex] - val variableBook = SearchBook() - val task = WebBook(source) - .searchBook(name, variableBook = variableBook, scope = this, context = searchPool!!) - .timeout(60000L) - .onSuccess(IO) { - it.forEach { searchBook -> - if (searchBook.name == name && searchBook.author == author) { - if (searchBook.latestChapterTitle.isNullOrEmpty()) { - if (context.getPrefBoolean(PreferKey.changeSourceLoadInfo) || context.getPrefBoolean(PreferKey.changeSourceLoadToc)) { - loadBookInfo(searchBook.toBook()) - } else { - searchFinish(searchBook) - } + } + val source = bookSourceList[searchIndex] + val variableBook = SearchBook() + val webBook = WebBook(source) + val task = webBook + .searchBook(name, variableBook = variableBook, scope = this, context = searchPool!!) + .timeout(60000L) + .onSuccess(IO) { + it.forEach { searchBook -> + if (searchBook.name == name && searchBook.author == author) { + if (searchBook.latestChapterTitle.isNullOrEmpty()) { + if (AppConfig.changeSourceLoadInfo || AppConfig.changeSourceLoadToc) { + loadBookInfo(webBook, searchBook.toBook()) } else { searchFinish(searchBook) } - return@forEach + } else { + searchFinish(searchBook) } + return@onSuccess } } - .onFinally { - synchronized(this) { - if (searchIndex < bookSourceList.lastIndex) { - search() - } else { - searchIndex++ - } - if (searchIndex >= bookSourceList.lastIndex + min(bookSourceList.size, - threadCount) - ) { - searchStateData.postValue(false) - } + } + .onFinally { + synchronized(this) { + if (searchIndex < bookSourceList.lastIndex) { + search() + } else { + searchIndex++ + } + if (searchIndex >= bookSourceList.lastIndex + bookSourceList.size + || searchIndex >= bookSourceList.lastIndex + threadCount + ) { + searchStateData.postValue(false) } } - tasks.add(task) - } + } + tasks.add(task) } - private fun loadBookInfo(book: Book) { - execute { - App.db.bookSourceDao().getBookSource(book.origin)?.let { bookSource -> - WebBook(bookSource).getBookInfo(book, this) - .onSuccess { - if (context.getPrefBoolean(PreferKey.changeSourceLoadToc)) { - loadChapter(it) - } else { - //从详情页里获取最新章节 - book.latestChapterTitle = it.latestChapterTitle - val searchBook = book.toSearchBook() - searchFinish(searchBook) - } - }.onError { - debug { context.getString(R.string.error_get_book_info) } - } - } ?: debug { context.getString(R.string.error_no_source) } - } + private fun loadBookInfo(webBook: WebBook, book: Book) { + webBook.getBookInfo(book, this) + .onSuccess { + if (context.getPrefBoolean(PreferKey.changeSourceLoadToc)) { + loadChapter(webBook, book) + } else { + //从详情页里获取最新章节 + book.latestChapterTitle = it.latestChapterTitle + val searchBook = book.toSearchBook() + searchFinish(searchBook) + } + }.onError { + debug { context.getString(R.string.error_get_book_info) } + } } - private fun loadChapter(book: Book) { - execute { - App.db.bookSourceDao().getBookSource(book.origin)?.let { bookSource -> - WebBook(bookSource).getChapterList(book, this) - .onSuccess(IO) { chapters -> - if (chapters.isNotEmpty()) { - book.latestChapterTitle = chapters.last().title - val searchBook: SearchBook = book.toSearchBook() - searchFinish(searchBook) - } - }.onError { - debug { context.getString(R.string.error_get_chapter_list) } - } - } ?: debug { R.string.error_no_source } - } + private fun loadChapter(webBook: WebBook, book: Book) { + webBook.getChapterList(book, this) + .onSuccess(IO) { chapters -> + if (chapters.isNotEmpty()) { + book.latestChapterTitle = chapters.last().title + val searchBook: SearchBook = book.toSearchBook() + searchFinish(searchBook) + } + }.onError { + debug { context.getString(R.string.error_get_chapter_list) } + } } /** diff --git a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesFragment.kt b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesFragment.kt index f9b684592..00efa768b 100644 --- a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesFragment.kt +++ b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesFragment.kt @@ -103,14 +103,14 @@ class RssArticlesFragment : VMBaseFragment(R.layout.fragme } override fun observeLiveBus() { - viewModel.loadFinally.observe(viewLifecycleOwner, { + viewModel.loadFinally.observe(viewLifecycleOwner) { refresh_recycler_view.stopLoading() if (it) { loadMoreView.startLoad() } else { loadMoreView.noMore() } - }) + } } override fun readRss(rssArticle: RssArticle) { diff --git a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesViewModel.kt b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesViewModel.kt index 44f125ef2..c5648fdd6 100644 --- a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesViewModel.kt @@ -49,6 +49,7 @@ class RssArticlesViewModel(application: Application) : BaseViewModel(application isLoading = false } }.onError { + loadFinally.postValue(false) it.printStackTrace() toast(it.localizedMessage) } diff --git a/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditActivity.kt b/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditActivity.kt index 34b795a2b..cf21ca604 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditActivity.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditActivity.kt @@ -136,7 +136,7 @@ class RssSourceEditActivity : } private fun getRssSource(): RssSource { - val source = viewModel.rssSource?.copy() ?: RssSource() + val source = viewModel.rssSource source.enabled = cb_is_enable.isChecked source.enableJs = cb_enable_js.isChecked source.loadWithBaseUrl = cb_enable_base_url.isChecked diff --git a/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditViewModel.kt b/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditViewModel.kt index 88a9a78dd..04e0da7c0 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditViewModel.kt @@ -8,24 +8,23 @@ import io.legado.app.data.entities.RssSource import io.legado.app.utils.GSON import io.legado.app.utils.fromJsonObject import io.legado.app.utils.getClipText +import io.legado.app.utils.msg import kotlinx.coroutines.Dispatchers class RssSourceEditViewModel(application: Application) : BaseViewModel(application) { - var rssSource: RssSource? = null - private var oldSourceUrl: String? = null + var rssSource: RssSource = RssSource() + private var oldSourceUrl: String = "" fun initData(intent: Intent, onFinally: () -> Unit) { execute { val key = intent.getStringExtra("data") - var source: RssSource? = null if (key != null) { - source = App.db.rssSourceDao().getByKey(key) - } - source?.let { - oldSourceUrl = it.sourceUrl - rssSource = it + App.db.rssSourceDao().getByKey(key)?.let { + rssSource = it + } } + oldSourceUrl = rssSource.sourceUrl }.onFinally { onFinally() } @@ -33,14 +32,11 @@ class RssSourceEditViewModel(application: Application) : BaseViewModel(applicati fun save(source: RssSource, success: (() -> Unit)) { execute { - oldSourceUrl?.let { - if (oldSourceUrl != source.sourceUrl) { - App.db.rssSourceDao().delete(it) - } + if (oldSourceUrl != source.sourceUrl) { + App.db.rssSourceDao().delete(oldSourceUrl) + oldSourceUrl = source.sourceUrl } - oldSourceUrl = source.sourceUrl App.db.rssSourceDao().insert(source) - rssSource = source }.onSuccess { success() }.onError { @@ -74,7 +70,7 @@ class RssSourceEditViewModel(application: Application) : BaseViewModel(applicati finally.invoke(it) } }.onError { - toast(it.localizedMessage ?: "Error") + toast(it.msg) } } diff --git a/app/src/main/res/menu/change_source.xml b/app/src/main/res/menu/change_source.xml index dd2deae1b..277f93911 100644 --- a/app/src/main/res/menu/change_source.xml +++ b/app/src/main/res/menu/change_source.xml @@ -19,14 +19,14 @@ tools:ignore="AlwaysShowAction" />