添加自动完成开关

pull/1660/head
kunfei 3 years ago
parent 3cbd7d0f68
commit f45aed28ac
  1. 75
      app/src/main/java/io/legado/app/help/RuleComplete.kt
  2. 57
      app/src/main/java/io/legado/app/help/ruleComplete.kt
  3. 89
      app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt
  4. 8
      app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditViewModel.kt
  5. 3
      app/src/main/res/layout/dialog_code_view.xml
  6. 16
      app/src/main/res/menu/source_edit.xml
  7. 1
      app/src/main/res/values-es-rES/strings.xml
  8. 1
      app/src/main/res/values-ja-rJP/strings.xml
  9. 1
      app/src/main/res/values-pt-rBR/strings.xml
  10. 1
      app/src/main/res/values-zh-rHK/strings.xml
  11. 1
      app/src/main/res/values-zh-rTW/strings.xml
  12. 1
      app/src/main/res/values-zh/strings.xml
  13. 1
      app/src/main/res/values/strings.xml

@ -0,0 +1,75 @@
package io.legado.app.help
object RuleComplete {
// 补全时忽略匹配规则
private val completeIgnore =
Regex(
"""\\n|##|@js:|<js>|@Json:|\$\.|(attr|text|ownText|textNodes|href|content|html|alt|all|value|src)(\(\)|##.*)?\s*$""",
RegexOption.MULTILINE
)
// 补全时忽略匹配的规则(判断列表项和详情页预处理规则生效)
private val completeIgnorePreRule = Regex("""^:|##|@js:|<js>|@Json:|\$\.""")
// 匹配从图片获取信息的规则
private val imgComplete = Regex(
"""(?<=(tag\.|[+/@~>| &]))img[@/]text(\(\))?$|^img[@/]text(\(\))?$""",
RegexOption.IGNORE_CASE
)
/**
* 对简单规则进行补全简化部分书源规则的编写
* 该方法仅对对JSOUP/XPath/CSS规则生效
* @author 希弥
* @return 补全后的规则 原规则
* @param rule 需要补全的规则
* @param preRule 预处理规则
* 用于分析详情页预处理规则
* @param type 补全结果的类型可选的值有:
* 1 文字(默认)
* 2 链接
* 3 图片
*/
fun autoComplete(
rule: String?,
preRule: String? = null,
type: Int = 1,
enable: Boolean
): String? {
if (!enable) {
return rule
}
if (rule.isNullOrEmpty() || rule.contains(completeIgnore)
|| preRule?.contains(completeIgnorePreRule) == true
) {
return rule
}
val textRule: String
val linkRule: String
val imgRule: String
val imgText: String
if (rule.contains(Regex("/[^@]+$"))) {
textRule = "/text()"
linkRule = "/@href"
imgRule = "/@src"
imgText = "img/@alt"
} else {
textRule = "@text"
linkRule = "@href"
imgRule = "@src"
imgText = "img@alt"
}
var ret: String = rule
when (type) {
1 -> ret = rule.replace(Regex("$"), textRule).replace(imgComplete, imgText)
2 -> ret = rule.replace(Regex("$"), linkRule)
3 -> ret = rule.replace(Regex("$"), imgRule)
}
return ret
}
}

@ -1,57 +0,0 @@
package io.legado.app.help
// 补全时忽略匹配规则
val completeIgnore =
Regex("""\\n|##|@js:|<js>|@Json:|\$\.|(attr|text|ownText|textNodes|href|content|html|alt|all|value|src)(\(\)|##.*)?\s*$""",RegexOption.MULTILINE)
// 补全时忽略匹配的规则(判断列表项和详情页预处理规则生效)
val completeIgnorePreRule = Regex("""^:|##|@js:|<js>|@Json:|\$\.""")
// 匹配从图片获取信息的规则
val imgComplete = Regex(
"""(?<=(tag\.|[+/@~>| &]))img[@/]text(\(\))?$|^img[@/]text(\(\))?$""",
RegexOption.IGNORE_CASE
)
/**
* 对简单规则进行补全简化部分书源规则的编写
* 该方法仅对对JSOUP/XPath/CSS规则生效
* @author 希弥
* @return 补全后的规则 原规则
* @param rule 需要补全的规则
* @param preRule 预处理规则
* 用于分析详情页预处理规则
* @param type 补全结果的类型可选的值有:
* 1 文字(默认)
* 2 链接
* 3 图片
*/
fun ruleComplete(rule: String?, preRule: String? = "", type: Int = 1): String? {
if (rule.isNullOrEmpty() || rule.contains(completeIgnore)
|| preRule?.contains(completeIgnorePreRule) == true
) {
return rule
}
val textRule: String
val linkRule: String
val imgRule: String
val imgText: String
if (rule.contains(Regex("/[^@]+$"))) {
textRule = "/text()"
linkRule = "/@href"
imgRule = "/@src"
imgText = "img/@alt"
} else {
textRule = "@text"
linkRule = "@href"
imgRule = "@src"
imgText = "img@alt"
}
var ret: String = rule
when (type) {
1 -> ret = rule.replace(Regex("$"), textRule).replace(imgComplete, imgText)
2 -> ret = rule.replace(Regex("$"), linkRule)
3 -> ret = rule.replace(Regex("$"), imgRule)
}
return ret
}

@ -21,7 +21,6 @@ import io.legado.app.data.entities.BookSource
import io.legado.app.data.entities.rule.* import io.legado.app.data.entities.rule.*
import io.legado.app.databinding.ActivityBookSourceEditBinding import io.legado.app.databinding.ActivityBookSourceEditBinding
import io.legado.app.help.LocalConfig import io.legado.app.help.LocalConfig
import io.legado.app.help.ruleComplete
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.dialogs.selector import io.legado.app.lib.dialogs.selector
import io.legado.app.lib.theme.backgroundColor import io.legado.app.lib.theme.backgroundColor
@ -90,6 +89,7 @@ class BookSourceEditActivity :
override fun onMenuOpened(featureId: Int, menu: Menu): Boolean { override fun onMenuOpened(featureId: Int, menu: Menu): Boolean {
menu.findItem(R.id.menu_login)?.isVisible = !viewModel.bookSource?.loginUrl.isNullOrBlank() menu.findItem(R.id.menu_login)?.isVisible = !viewModel.bookSource?.loginUrl.isNullOrBlank()
menu.findItem(R.id.menu_auto_complete)?.isChecked = viewModel.autoComplete
return super.onMenuOpened(featureId, menu) return super.onMenuOpened(featureId, menu)
} }
@ -112,6 +112,7 @@ class BookSourceEditActivity :
} }
} }
} }
R.id.menu_auto_complete -> viewModel.autoComplete = !viewModel.autoComplete
R.id.menu_copy_source -> sendToClip(GSON.toJson(getSource())) R.id.menu_copy_source -> sendToClip(GSON.toJson(getSource()))
R.id.menu_paste_source -> viewModel.pasteSource { upRecyclerView(it) } R.id.menu_paste_source -> viewModel.pasteSource { upRecyclerView(it) }
R.id.menu_qr_code_camera -> qrCodeResult.launch() R.id.menu_qr_code_camera -> qrCodeResult.launch()
@ -328,64 +329,86 @@ class BookSourceEditActivity :
"searchUrl" -> source.searchUrl = it.value "searchUrl" -> source.searchUrl = it.value
"checkKeyWord" -> searchRule.checkKeyWord = it.value "checkKeyWord" -> searchRule.checkKeyWord = it.value
"bookList" -> searchRule.bookList = it.value ?: "" "bookList" -> searchRule.bookList = it.value ?: ""
"name" -> searchRule.name = ruleComplete(it.value,searchRule.bookList) "name" -> searchRule.name = viewModel.ruleComplete(it.value, searchRule.bookList)
"author" -> searchRule.author = ruleComplete(it.value,searchRule.bookList) "author" -> searchRule.author =
"kind" -> searchRule.kind = ruleComplete(it.value,searchRule.bookList) viewModel.ruleComplete(it.value, searchRule.bookList)
"intro" -> searchRule.intro = ruleComplete(it.value,searchRule.bookList) "kind" -> searchRule.kind = viewModel.ruleComplete(it.value, searchRule.bookList)
"updateTime" -> searchRule.updateTime = ruleComplete(it.value,searchRule.bookList) "intro" -> searchRule.intro = viewModel.ruleComplete(it.value, searchRule.bookList)
"wordCount" -> searchRule.wordCount = ruleComplete(it.value,searchRule.bookList) "updateTime" -> searchRule.updateTime =
"lastChapter" -> searchRule.lastChapter = ruleComplete(it.value,searchRule.bookList) viewModel.ruleComplete(it.value, searchRule.bookList)
"coverUrl" -> searchRule.coverUrl = ruleComplete(it.value,searchRule.bookList,3) "wordCount" -> searchRule.wordCount =
"bookUrl" -> searchRule.bookUrl = ruleComplete(it.value,searchRule.bookList,2) viewModel.ruleComplete(it.value, searchRule.bookList)
"lastChapter" -> searchRule.lastChapter =
viewModel.ruleComplete(it.value, searchRule.bookList)
"coverUrl" -> searchRule.coverUrl =
viewModel.ruleComplete(it.value, searchRule.bookList, 3)
"bookUrl" -> searchRule.bookUrl =
viewModel.ruleComplete(it.value, searchRule.bookList, 2)
} }
} }
findEntities.forEach { findEntities.forEach {
when (it.key) { when (it.key) {
"exploreUrl" -> source.exploreUrl = it.value "exploreUrl" -> source.exploreUrl = it.value
"bookList" -> exploreRule.bookList = it.value ?: "" "bookList" -> exploreRule.bookList = it.value ?: ""
"name" -> exploreRule.name = ruleComplete(it.value,exploreRule.bookList) "name" -> exploreRule.name = viewModel.ruleComplete(it.value, exploreRule.bookList)
"author" -> exploreRule.author = ruleComplete(it.value,exploreRule.bookList) "author" -> exploreRule.author =
"kind" -> exploreRule.kind = ruleComplete(it.value,exploreRule.bookList) viewModel.ruleComplete(it.value, exploreRule.bookList)
"intro" -> exploreRule.intro = ruleComplete(it.value,exploreRule.bookList) "kind" -> exploreRule.kind = viewModel.ruleComplete(it.value, exploreRule.bookList)
"updateTime" -> exploreRule.updateTime = ruleComplete(it.value,exploreRule.bookList) "intro" -> exploreRule.intro =
"wordCount" -> exploreRule.wordCount = ruleComplete(it.value,exploreRule.bookList) viewModel.ruleComplete(it.value, exploreRule.bookList)
"lastChapter" -> exploreRule.lastChapter = ruleComplete(it.value,exploreRule.bookList) "updateTime" -> exploreRule.updateTime =
"coverUrl" -> exploreRule.coverUrl = ruleComplete(it.value,exploreRule.bookList,3) viewModel.ruleComplete(it.value, exploreRule.bookList)
"bookUrl" -> exploreRule.bookUrl = ruleComplete(it.value,exploreRule.bookList,2) "wordCount" -> exploreRule.wordCount =
viewModel.ruleComplete(it.value, exploreRule.bookList)
"lastChapter" -> exploreRule.lastChapter =
viewModel.ruleComplete(it.value, exploreRule.bookList)
"coverUrl" -> exploreRule.coverUrl =
viewModel.ruleComplete(it.value, exploreRule.bookList, 3)
"bookUrl" -> exploreRule.bookUrl =
viewModel.ruleComplete(it.value, exploreRule.bookList, 2)
} }
} }
infoEntities.forEach { infoEntities.forEach {
when (it.key) { when (it.key) {
"init" -> bookInfoRule.init = it.value ?: "" "init" -> bookInfoRule.init = it.value ?: ""
"name" -> bookInfoRule.name = ruleComplete(it.value, bookInfoRule.init) "name" -> bookInfoRule.name = viewModel.ruleComplete(it.value, bookInfoRule.init)
"author" -> bookInfoRule.author = ruleComplete(it.value, bookInfoRule.init) "author" -> bookInfoRule.author =
"kind" -> bookInfoRule.kind = ruleComplete(it.value, bookInfoRule.init) viewModel.ruleComplete(it.value, bookInfoRule.init)
"intro" -> bookInfoRule.intro = ruleComplete(it.value, bookInfoRule.init) "kind" -> bookInfoRule.kind = viewModel.ruleComplete(it.value, bookInfoRule.init)
"updateTime" -> bookInfoRule.updateTime = ruleComplete(it.value, bookInfoRule.init) "intro" -> bookInfoRule.intro = viewModel.ruleComplete(it.value, bookInfoRule.init)
"wordCount" -> bookInfoRule.wordCount = ruleComplete(it.value, bookInfoRule.init) "updateTime" -> bookInfoRule.updateTime =
viewModel.ruleComplete(it.value, bookInfoRule.init)
"wordCount" -> bookInfoRule.wordCount =
viewModel.ruleComplete(it.value, bookInfoRule.init)
"lastChapter" -> bookInfoRule.lastChapter = "lastChapter" -> bookInfoRule.lastChapter =
ruleComplete(it.value, bookInfoRule.init) viewModel.ruleComplete(it.value, bookInfoRule.init)
"coverUrl" -> bookInfoRule.coverUrl = ruleComplete(it.value, bookInfoRule.init, 3) "coverUrl" -> bookInfoRule.coverUrl =
"tocUrl" -> bookInfoRule.tocUrl = ruleComplete(it.value, bookInfoRule.init, 2) viewModel.ruleComplete(it.value, bookInfoRule.init, 3)
"tocUrl" -> bookInfoRule.tocUrl =
viewModel.ruleComplete(it.value, bookInfoRule.init, 2)
"canReName" -> bookInfoRule.canReName = it.value "canReName" -> bookInfoRule.canReName = it.value
} }
} }
tocEntities.forEach { tocEntities.forEach {
when (it.key) { when (it.key) {
"chapterList" -> tocRule.chapterList = it.value ?: "" "chapterList" -> tocRule.chapterList = it.value ?: ""
"chapterName" -> tocRule.chapterName = ruleComplete(it.value,tocRule.chapterList) "chapterName" -> tocRule.chapterName =
"chapterUrl" -> tocRule.chapterUrl = ruleComplete(it.value,tocRule.chapterList, 2) viewModel.ruleComplete(it.value, tocRule.chapterList)
"chapterUrl" -> tocRule.chapterUrl =
viewModel.ruleComplete(it.value, tocRule.chapterList, 2)
"isVolume" -> tocRule.isVolume = it.value "isVolume" -> tocRule.isVolume = it.value
"updateTime" -> tocRule.updateTime = it.value "updateTime" -> tocRule.updateTime = it.value
"isVip" -> tocRule.isVip = it.value "isVip" -> tocRule.isVip = it.value
"isPay" -> tocRule.isPay = it.value "isPay" -> tocRule.isPay = it.value
"nextTocUrl" -> tocRule.nextTocUrl = ruleComplete(it.value,tocRule.chapterList,2) "nextTocUrl" -> tocRule.nextTocUrl =
viewModel.ruleComplete(it.value, tocRule.chapterList, 2)
} }
} }
contentEntities.forEach { contentEntities.forEach {
when (it.key) { when (it.key) {
"content" -> contentRule.content = ruleComplete(it.value) "content" -> contentRule.content = viewModel.ruleComplete(it.value)
"nextContentUrl" -> contentRule.nextContentUrl = ruleComplete(it.value, type = 2) "nextContentUrl" -> contentRule.nextContentUrl =
viewModel.ruleComplete(it.value, type = 2)
"webJs" -> contentRule.webJs = it.value "webJs" -> contentRule.webJs = it.value
"sourceRegex" -> contentRule.sourceRegex = it.value "sourceRegex" -> contentRule.sourceRegex = it.value
"replaceRegex" -> contentRule.replaceRegex = it.value "replaceRegex" -> contentRule.replaceRegex = it.value

@ -5,6 +5,7 @@ import android.content.Intent
import io.legado.app.base.BaseViewModel import io.legado.app.base.BaseViewModel
import io.legado.app.data.appDb import io.legado.app.data.appDb
import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.BookSource
import io.legado.app.help.RuleComplete
import io.legado.app.help.http.newCallStrResponse import io.legado.app.help.http.newCallStrResponse
import io.legado.app.help.http.okHttpClient import io.legado.app.help.http.okHttpClient
import io.legado.app.model.NoStackTraceException import io.legado.app.model.NoStackTraceException
@ -13,7 +14,7 @@ import kotlinx.coroutines.Dispatchers
class BookSourceEditViewModel(application: Application) : BaseViewModel(application) { class BookSourceEditViewModel(application: Application) : BaseViewModel(application) {
var autoComplete = false
var bookSource: BookSource? = null var bookSource: BookSource? = null
private var oldSourceUrl: String? = null private var oldSourceUrl: String? = null
@ -95,4 +96,9 @@ class BookSourceEditViewModel(application: Application) : BaseViewModel(applicat
} }
} }
} }
fun ruleComplete(rule: String?, preRule: String? = null, type: Int = 1): String? {
return RuleComplete.autoComplete(rule, preRule, type, autoComplete)
}
} }

@ -19,8 +19,7 @@
android:id="@+id/code_view" android:id="@+id/code_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="12dp" android:padding="12dp" />
android:textIsSelectable="true" />
</LinearLayout> </LinearLayout>

@ -1,24 +1,32 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:ignore="AlwaysShowAction">
<item <item
android:id="@+id/menu_save" android:id="@+id/menu_save"
android:icon="@drawable/ic_save" android:icon="@drawable/ic_save"
android:title="@string/action_save" android:title="@string/action_save"
app:showAsAction="ifRoom" /> app:showAsAction="always" />
<item <item
android:id="@+id/menu_debug_source" android:id="@+id/menu_debug_source"
android:icon="@drawable/ic_bug_report" android:icon="@drawable/ic_bug_report"
android:title="@string/debug_source" android:title="@string/debug_source"
app:showAsAction="ifRoom" /> app:showAsAction="always" />
<item <item
android:id="@+id/menu_login" android:id="@+id/menu_login"
android:title="@string/login" android:title="@string/login"
app:showAsAction="never" /> app:showAsAction="never" />
<item
android:id="@+id/menu_auto_complete"
android:title="@string/auto_complete"
android:checkable="true"
app:showAsAction="never" />
<item <item
android:id="@+id/menu_copy_source" android:id="@+id/menu_copy_source"
android:title="@string/copy_source" android:title="@string/copy_source"

@ -944,5 +944,6 @@
<string name="sort_by_time">时间排序</string> <string name="sort_by_time">时间排序</string>
<string name="enable_record">开启记录</string> <string name="enable_record">开启记录</string>
<string name="copy_all">拷贝所有</string> <string name="copy_all">拷贝所有</string>
<string name="auto_complete">自动补全</string>
<!-- string end --> <!-- string end -->
</resources> </resources>

@ -947,5 +947,6 @@
<string name="sort_by_time">时间排序</string> <string name="sort_by_time">时间排序</string>
<string name="enable_record">开启记录</string> <string name="enable_record">开启记录</string>
<string name="copy_all">拷贝所有</string> <string name="copy_all">拷贝所有</string>
<string name="auto_complete">自动补全</string>
<!-- string end --> <!-- string end -->
</resources> </resources>

@ -947,5 +947,6 @@
<string name="sort_by_time">时间排序</string> <string name="sort_by_time">时间排序</string>
<string name="enable_record">开启记录</string> <string name="enable_record">开启记录</string>
<string name="copy_all">拷贝所有</string> <string name="copy_all">拷贝所有</string>
<string name="auto_complete">自动补全</string>
<!-- string end --> <!-- string end -->
</resources> </resources>

@ -944,5 +944,6 @@
<string name="sort_by_time">时间排序</string> <string name="sort_by_time">时间排序</string>
<string name="enable_record">开启记录</string> <string name="enable_record">开启记录</string>
<string name="copy_all">拷贝所有</string> <string name="copy_all">拷贝所有</string>
<string name="auto_complete">自动补全</string>
<!-- string end --> <!-- string end -->
</resources> </resources>

@ -946,5 +946,6 @@
<string name="sort_by_time">时间排序</string> <string name="sort_by_time">时间排序</string>
<string name="enable_record">开启记录</string> <string name="enable_record">开启记录</string>
<string name="copy_all">拷贝所有</string> <string name="copy_all">拷贝所有</string>
<string name="auto_complete">自动补全</string>
<!-- string end --> <!-- string end -->
</resources> </resources>

@ -946,5 +946,6 @@
<string name="sort_by_time">时间排序</string> <string name="sort_by_time">时间排序</string>
<string name="enable_record">开启记录</string> <string name="enable_record">开启记录</string>
<string name="copy_all">拷贝所有</string> <string name="copy_all">拷贝所有</string>
<string name="auto_complete">自动补全</string>
<!-- string end --> <!-- string end -->
</resources> </resources>

@ -947,5 +947,6 @@
<string name="sort_by_time">时间排序</string> <string name="sort_by_time">时间排序</string>
<string name="enable_record">开启记录</string> <string name="enable_record">开启记录</string>
<string name="copy_all">拷贝所有</string> <string name="copy_all">拷贝所有</string>
<string name="auto_complete">自动补全</string>
<!-- string end --> <!-- string end -->
</resources> </resources>

Loading…
Cancel
Save