Merge branch 'master' into master
This commit is contained in:
@@ -7,6 +7,7 @@ import androidx.room.Ignore
|
||||
import androidx.room.Index
|
||||
import com.github.liuyueyi.quick.transfer.ChineseUtils
|
||||
import io.legado.app.R
|
||||
import io.legado.app.constant.AppLog
|
||||
import io.legado.app.constant.AppPattern
|
||||
import io.legado.app.data.appDb
|
||||
import io.legado.app.exception.RegexTimeoutException
|
||||
@@ -15,6 +16,7 @@ import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.model.analyzeRule.AnalyzeUrl
|
||||
import io.legado.app.model.analyzeRule.RuleDataInterface
|
||||
import io.legado.app.utils.*
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.parcelize.IgnoredOnParcel
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import splitties.init.appCtx
|
||||
@@ -93,7 +95,7 @@ data class BookChapter(
|
||||
2 -> displayTitle = ChineseUtils.s2t(displayTitle)
|
||||
}
|
||||
}
|
||||
if (useReplace && replaceRules != null) {
|
||||
if (useReplace && replaceRules != null) kotlin.run {
|
||||
replaceRules.forEach { item ->
|
||||
if (item.pattern.isNotEmpty()) {
|
||||
try {
|
||||
@@ -112,7 +114,10 @@ data class BookChapter(
|
||||
} catch (e: RegexTimeoutException) {
|
||||
item.isEnabled = false
|
||||
appDb.replaceRuleDao.update(item)
|
||||
} catch (e: CancellationException) {
|
||||
return@run
|
||||
} catch (e: Exception) {
|
||||
AppLog.put("${item.name}替换出错\n替换内容\n${displayTitle}", e)
|
||||
appCtx.toastOnUi("${item.name}替换出错")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import io.legado.app.help.config.ReadBookConfig
|
||||
import io.legado.app.utils.msg
|
||||
import io.legado.app.utils.replace
|
||||
import io.legado.app.utils.toastOnUi
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import splitties.init.appCtx
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
@@ -135,7 +136,7 @@ class ContentProcessor private constructor(
|
||||
var mContent = content
|
||||
getContentReplaceRules().forEach { item ->
|
||||
if (item.pattern.isNotEmpty()) {
|
||||
kotlin.runCatching {
|
||||
try {
|
||||
mContent = if (item.isRegex) {
|
||||
mContent.replace(
|
||||
item.pattern.toRegex(),
|
||||
@@ -145,18 +146,15 @@ class ContentProcessor private constructor(
|
||||
} else {
|
||||
mContent.replace(item.pattern, item.replacement)
|
||||
}
|
||||
}.onFailure {
|
||||
when (it) {
|
||||
is RegexTimeoutException -> {
|
||||
item.isEnabled = false
|
||||
appDb.replaceRuleDao.update(item)
|
||||
return item.name + it.msg
|
||||
}
|
||||
else -> {
|
||||
AppLog.put("${item.name}替换出错\n${it.localizedMessage}", it)
|
||||
appCtx.toastOnUi("${item.name}替换出错")
|
||||
}
|
||||
}
|
||||
} catch (e: RegexTimeoutException) {
|
||||
item.isEnabled = false
|
||||
appDb.replaceRuleDao.update(item)
|
||||
return item.name + e.msg
|
||||
} catch (e: CancellationException) {
|
||||
return mContent
|
||||
} catch (e: Exception) {
|
||||
AppLog.put("${item.name}替换出错\n替换内容\n${mContent}", e)
|
||||
appCtx.toastOnUi("${item.name}替换出错")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +1,47 @@
|
||||
package io.legado.app.help
|
||||
|
||||
import io.legado.app.data.entities.ReplaceRule
|
||||
import io.legado.app.exception.NoStackTraceException
|
||||
import io.legado.app.utils.*
|
||||
|
||||
object ReplaceAnalyzer {
|
||||
|
||||
fun jsonToReplaceRules(json: String): List<ReplaceRule> {
|
||||
val replaceRules = mutableListOf<ReplaceRule>()
|
||||
val items: List<Map<String, Any>> = jsonPath.parse(json).read("$")
|
||||
for (item in items) {
|
||||
val jsonItem = jsonPath.parse(item)
|
||||
jsonToReplaceRule(jsonItem.jsonString())?.let {
|
||||
if (it.isValid()) {
|
||||
replaceRules.add(it)
|
||||
fun jsonToReplaceRules(json: String): Result<MutableList<ReplaceRule>> {
|
||||
return kotlin.runCatching {
|
||||
val replaceRules = mutableListOf<ReplaceRule>()
|
||||
val items: List<Map<String, Any>> = jsonPath.parse(json).read("$")
|
||||
for (item in items) {
|
||||
val jsonItem = jsonPath.parse(item)
|
||||
jsonToReplaceRule(jsonItem.jsonString()).getOrThrow().let {
|
||||
if (it.isValid()) {
|
||||
replaceRules.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
replaceRules
|
||||
}
|
||||
return replaceRules
|
||||
}
|
||||
|
||||
private fun jsonToReplaceRule(json: String): ReplaceRule? {
|
||||
val replaceRule: ReplaceRule? = GSON.fromJsonObject<ReplaceRule>(json.trim()).getOrNull()
|
||||
runCatching {
|
||||
fun jsonToReplaceRule(json: String): Result<ReplaceRule> {
|
||||
return runCatching {
|
||||
val replaceRule: ReplaceRule? =
|
||||
GSON.fromJsonObject<ReplaceRule>(json.trim()).getOrNull()
|
||||
if (replaceRule == null || replaceRule.pattern.isBlank()) {
|
||||
val jsonItem = jsonPath.parse(json.trim())
|
||||
val rule = ReplaceRule()
|
||||
rule.id = jsonItem.readLong("$.id") ?: System.currentTimeMillis()
|
||||
rule.pattern = jsonItem.readString("$.regex") ?: ""
|
||||
if (rule.pattern.isEmpty()) return null
|
||||
if (rule.pattern.isEmpty()) throw NoStackTraceException("格式不对")
|
||||
rule.name = jsonItem.readString("$.replaceSummary") ?: ""
|
||||
rule.replacement = jsonItem.readString("$.replacement") ?: ""
|
||||
rule.isRegex = jsonItem.readBool("$.isRegex") == true
|
||||
rule.scope = jsonItem.readString("$.useTo")
|
||||
rule.isEnabled = jsonItem.readBool("$.enable") == true
|
||||
rule.order = jsonItem.readInt("$.serialNumber") ?: 0
|
||||
return rule
|
||||
return@runCatching rule
|
||||
}
|
||||
return@runCatching replaceRule
|
||||
}
|
||||
return replaceRule
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import org.apache.commons.text.StringEscapeUtils
|
||||
import splitties.init.appCtx
|
||||
import java.lang.ref.WeakReference
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.resumeWithException
|
||||
|
||||
/**
|
||||
* 后台webView
|
||||
@@ -50,14 +51,14 @@ class BackstageWebView(
|
||||
|
||||
override fun onError(error: Throwable) {
|
||||
if (!block.isCompleted)
|
||||
block.cancel(error)
|
||||
block.resumeWithException(error)
|
||||
}
|
||||
}
|
||||
runOnUI {
|
||||
try {
|
||||
load()
|
||||
} catch (error: Throwable) {
|
||||
block.cancel(error)
|
||||
block.resumeWithException(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ package io.legado.app.help.http
|
||||
import android.text.TextUtils
|
||||
import io.legado.app.data.appDb
|
||||
import io.legado.app.data.entities.Cookie
|
||||
import io.legado.app.help.http.api.CookieManager
|
||||
import io.legado.app.help.CacheManager
|
||||
import io.legado.app.help.http.api.CookieManager
|
||||
import io.legado.app.utils.NetworkUtils
|
||||
|
||||
object CookieStore : CookieManager {
|
||||
@@ -44,7 +44,7 @@ object CookieStore : CookieManager {
|
||||
CacheManager.getFromMemory("${domain}_cookie")?.let { return it }
|
||||
val cookieBean = appDb.cookieDao.get(domain)
|
||||
val cookie = cookieBean?.cookie ?: ""
|
||||
CacheManager.putMemory(url, cookie ?: "")
|
||||
CacheManager.putMemory(url, cookie)
|
||||
return cookie
|
||||
}
|
||||
|
||||
|
||||
@@ -98,9 +98,12 @@ object ImportOldData {
|
||||
}
|
||||
|
||||
private fun importOldReplaceRule(json: String): Int {
|
||||
val rules = ReplaceAnalyzer.jsonToReplaceRules(json)
|
||||
appDb.replaceRuleDao.insert(*rules.toTypedArray())
|
||||
return rules.size
|
||||
val rules = ReplaceAnalyzer.jsonToReplaceRules(json).getOrNull()
|
||||
rules?.let {
|
||||
appDb.replaceRuleDao.insert(*rules.toTypedArray())
|
||||
return rules.size
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
private fun fromOldBooks(json: String): List<Book> {
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package io.legado.app.ui.widget.prefs
|
||||
package io.legado.app.lib.prefs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
@@ -118,7 +118,7 @@ class ColorPreference(context: Context, attrs: AttributeSet) : Preference(contex
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||
val v = io.legado.app.ui.widget.prefs.Preference.bindView<ColorPanelView>(
|
||||
val v = io.legado.app.lib.prefs.Preference.bindView<ColorPanelView>(
|
||||
context, holder, icon, title, summary, widgetLayoutResource,
|
||||
io.legado.app.R.id.cpv_preference_preview_color_panel, 30, 30
|
||||
)
|
||||
@@ -0,0 +1,36 @@
|
||||
package io.legado.app.lib.prefs
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.widget.TextView
|
||||
import androidx.preference.EditTextPreference.OnBindEditTextListener
|
||||
import androidx.preference.PreferenceViewHolder
|
||||
import io.legado.app.R
|
||||
import io.legado.app.lib.theme.accentColor
|
||||
import io.legado.app.utils.applyTint
|
||||
|
||||
class EditTextPreference(context: Context, attrs: AttributeSet) :
|
||||
androidx.preference.EditTextPreference(context, attrs) {
|
||||
|
||||
private var mOnBindEditTextListener: OnBindEditTextListener? = null
|
||||
private val onBindEditTextListener = OnBindEditTextListener { editText ->
|
||||
editText.applyTint(context.accentColor)
|
||||
mOnBindEditTextListener?.onBindEditText(editText)
|
||||
}
|
||||
|
||||
init {
|
||||
// isPersistent = true
|
||||
layoutResource = R.layout.view_preference
|
||||
super.setOnBindEditTextListener(onBindEditTextListener)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||
Preference.bindView<TextView>(context, holder, icon, title, summary, null, null)
|
||||
super.onBindViewHolder(holder)
|
||||
}
|
||||
|
||||
override fun setOnBindEditTextListener(onBindEditTextListener: OnBindEditTextListener?) {
|
||||
mOnBindEditTextListener = onBindEditTextListener
|
||||
}
|
||||
|
||||
}
|
||||
+10
-1
@@ -1,9 +1,11 @@
|
||||
package io.legado.app.ui.widget.prefs
|
||||
package io.legado.app.lib.prefs
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.preference.EditTextPreferenceDialogFragmentCompat
|
||||
import androidx.preference.PreferenceDialogFragmentCompat
|
||||
import io.legado.app.lib.theme.accentColor
|
||||
import io.legado.app.lib.theme.filletBackground
|
||||
|
||||
class EditTextPreferenceDialog : EditTextPreferenceDialogFragmentCompat() {
|
||||
@@ -23,6 +25,13 @@ class EditTextPreferenceDialog : EditTextPreferenceDialogFragmentCompat() {
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val dialog = super.onCreateDialog(savedInstanceState)
|
||||
dialog.window?.setBackgroundDrawable(requireContext().filletBackground)
|
||||
dialog.window?.decorView?.post {
|
||||
(dialog as AlertDialog).run {
|
||||
getButton(AlertDialog.BUTTON_NEGATIVE)?.setTextColor(accentColor)
|
||||
getButton(AlertDialog.BUTTON_POSITIVE)?.setTextColor(accentColor)
|
||||
getButton(AlertDialog.BUTTON_NEUTRAL)?.setTextColor(accentColor)
|
||||
}
|
||||
}
|
||||
return dialog
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package io.legado.app.ui.widget.prefs
|
||||
package io.legado.app.lib.prefs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
+10
-1
@@ -1,9 +1,11 @@
|
||||
package io.legado.app.ui.widget.prefs
|
||||
package io.legado.app.lib.prefs
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.preference.ListPreferenceDialogFragmentCompat
|
||||
import androidx.preference.PreferenceDialogFragmentCompat
|
||||
import io.legado.app.lib.theme.accentColor
|
||||
import io.legado.app.lib.theme.filletBackground
|
||||
|
||||
class ListPreferenceDialog : ListPreferenceDialogFragmentCompat() {
|
||||
@@ -23,6 +25,13 @@ class ListPreferenceDialog : ListPreferenceDialogFragmentCompat() {
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val dialog = super.onCreateDialog(savedInstanceState)
|
||||
dialog.window?.setBackgroundDrawable(requireContext().filletBackground)
|
||||
dialog.window?.decorView?.post {
|
||||
(dialog as AlertDialog).run {
|
||||
getButton(AlertDialog.BUTTON_NEGATIVE)?.setTextColor(accentColor)
|
||||
getButton(AlertDialog.BUTTON_POSITIVE)?.setTextColor(accentColor)
|
||||
getButton(AlertDialog.BUTTON_NEUTRAL)?.setTextColor(accentColor)
|
||||
}
|
||||
}
|
||||
return dialog
|
||||
}
|
||||
|
||||
+10
-1
@@ -1,9 +1,11 @@
|
||||
package io.legado.app.ui.widget.prefs
|
||||
package io.legado.app.lib.prefs
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.preference.MultiSelectListPreferenceDialogFragmentCompat
|
||||
import androidx.preference.PreferenceDialogFragmentCompat
|
||||
import io.legado.app.lib.theme.accentColor
|
||||
import io.legado.app.lib.theme.filletBackground
|
||||
|
||||
class MultiSelectListPreferenceDialog : MultiSelectListPreferenceDialogFragmentCompat() {
|
||||
@@ -25,6 +27,13 @@ class MultiSelectListPreferenceDialog : MultiSelectListPreferenceDialogFragmentC
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val dialog = super.onCreateDialog(savedInstanceState)
|
||||
dialog.window?.setBackgroundDrawable(requireContext().filletBackground)
|
||||
dialog.window?.decorView?.post {
|
||||
(dialog as AlertDialog).run {
|
||||
getButton(AlertDialog.BUTTON_NEGATIVE)?.setTextColor(accentColor)
|
||||
getButton(AlertDialog.BUTTON_POSITIVE)?.setTextColor(accentColor)
|
||||
getButton(AlertDialog.BUTTON_NEUTRAL)?.setTextColor(accentColor)
|
||||
}
|
||||
}
|
||||
return dialog
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package io.legado.app.ui.widget.prefs
|
||||
package io.legado.app.lib.prefs
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package io.legado.app.ui.widget.prefs
|
||||
package io.legado.app.lib.prefs
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package io.legado.app.ui.widget.prefs
|
||||
package io.legado.app.lib.prefs
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package io.legado.app.ui.widget.prefs
|
||||
package io.legado.app.lib.prefs
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
+8
-9
@@ -1,13 +1,13 @@
|
||||
package io.legado.app.base
|
||||
package io.legado.app.lib.prefs.fragment
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.preference.*
|
||||
import io.legado.app.ui.widget.prefs.EditTextPreferenceDialog
|
||||
import io.legado.app.ui.widget.prefs.ListPreferenceDialog
|
||||
import io.legado.app.ui.widget.prefs.MultiSelectListPreferenceDialog
|
||||
import io.legado.app.lib.prefs.EditTextPreferenceDialog
|
||||
import io.legado.app.lib.prefs.ListPreferenceDialog
|
||||
import io.legado.app.lib.prefs.MultiSelectListPreferenceDialog
|
||||
|
||||
abstract class BasePreferenceFragment : PreferenceFragmentCompat() {
|
||||
abstract class PreferenceFragment : PreferenceFragmentCompat() {
|
||||
|
||||
private val dialogFragmentTag = "androidx.preference.PreferenceFragment.DIALOG"
|
||||
|
||||
@@ -34,7 +34,7 @@ abstract class BasePreferenceFragment : PreferenceFragmentCompat() {
|
||||
return
|
||||
}
|
||||
|
||||
val f: DialogFragment = when (preference) {
|
||||
val dialogFragment: DialogFragment = when (preference) {
|
||||
is EditTextPreference -> {
|
||||
EditTextPreferenceDialog.newInstance(preference.getKey())
|
||||
}
|
||||
@@ -54,10 +54,9 @@ abstract class BasePreferenceFragment : PreferenceFragmentCompat() {
|
||||
}
|
||||
}
|
||||
@Suppress("DEPRECATION")
|
||||
f.setTargetFragment(this, 0)
|
||||
dialogFragment.setTargetFragment(this, 0)
|
||||
|
||||
f.show(parentFragmentManager, dialogFragmentTag)
|
||||
dialogFragment.show(parentFragmentManager, dialogFragmentTag)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -131,9 +131,9 @@ object CacheBook {
|
||||
|
||||
class CacheBookModel(var bookSource: BookSource, var book: Book) {
|
||||
|
||||
private val waitDownloadSet = hashSetOf<Int>()
|
||||
private val onDownloadSet = hashSetOf<Int>()
|
||||
private val successDownloadSet = hashSetOf<Int>()
|
||||
private val waitDownloadSet = linkedSetOf<Int>()
|
||||
private val onDownloadSet = linkedSetOf<Int>()
|
||||
private val successDownloadSet = linkedSetOf<Int>()
|
||||
private val errorDownloadMap = hashMapOf<Int, Int>()
|
||||
|
||||
val waitCount get() = waitDownloadSet.size
|
||||
@@ -174,7 +174,7 @@ object CacheBook {
|
||||
}
|
||||
onDownloadSet.remove(index)
|
||||
//重试3次
|
||||
if (errorDownloadMap[index] ?: 0 < 3) {
|
||||
if ((errorDownloadMap[index] ?: 0) < 3) {
|
||||
waitDownloadSet.add(index)
|
||||
} else {
|
||||
AppLog.put(
|
||||
|
||||
@@ -537,8 +537,7 @@ class AnalyzeUrl(
|
||||
val cookieMap = CookieStore.cookieToMap(cookie)
|
||||
val customCookieMap = CookieStore.cookieToMap(headerMap["Cookie"] ?: "")
|
||||
cookieMap.putAll(customCookieMap)
|
||||
val newCookie = CookieStore.mapToCookie(cookieMap)
|
||||
newCookie?.let {
|
||||
CookieStore.mapToCookie(cookieMap)?.let {
|
||||
headerMap.put("Cookie", it)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,21 +61,7 @@ class ImportHttpTtsViewModel(app: Application) : BaseViewModel(app) {
|
||||
|
||||
fun importSource(text: String) {
|
||||
execute {
|
||||
val mText = text.trim()
|
||||
when {
|
||||
mText.isJsonObject() -> {
|
||||
HttpTTS.fromJson(mText).getOrThrow().let {
|
||||
allSources.add(it)
|
||||
}
|
||||
}
|
||||
mText.isJsonArray() -> HttpTTS.fromJsonArray(mText).getOrThrow().let { items ->
|
||||
allSources.addAll(items)
|
||||
}
|
||||
mText.isAbsUrl() -> {
|
||||
importSourceUrl(mText)
|
||||
}
|
||||
else -> throw NoStackTraceException(context.getString(R.string.wrong_format))
|
||||
}
|
||||
importSourceAwait(text.trim())
|
||||
}.onError {
|
||||
it.printOnDebug()
|
||||
errorLiveData.postValue(it.localizedMessage ?: "")
|
||||
@@ -84,11 +70,28 @@ class ImportHttpTtsViewModel(app: Application) : BaseViewModel(app) {
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun importSourceAwait(text: String) {
|
||||
when {
|
||||
text.isJsonObject() -> {
|
||||
HttpTTS.fromJson(text).getOrThrow().let {
|
||||
allSources.add(it)
|
||||
}
|
||||
}
|
||||
text.isJsonArray() -> HttpTTS.fromJsonArray(text).getOrThrow().let { items ->
|
||||
allSources.addAll(items)
|
||||
}
|
||||
text.isAbsUrl() -> {
|
||||
importSourceUrl(text)
|
||||
}
|
||||
else -> throw NoStackTraceException(context.getString(R.string.wrong_format))
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun importSourceUrl(url: String) {
|
||||
okHttpClient.newCallResponseBody {
|
||||
url(url)
|
||||
}.text().let {
|
||||
allSources.addAll(HttpTTS.fromJsonArray(it).getOrThrow())
|
||||
importSourceAwait(it)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,14 +88,14 @@ class ImportReplaceRuleDialog() : BaseDialogFragment(R.layout.dialog_recycler_vi
|
||||
adapter.notifyDataSetChanged()
|
||||
upSelectText()
|
||||
}
|
||||
viewModel.errorLiveData.observe(this, {
|
||||
viewModel.errorLiveData.observe(this) {
|
||||
binding.rotateLoading.hide()
|
||||
binding.tvMsg.apply {
|
||||
text = it
|
||||
visible()
|
||||
}
|
||||
})
|
||||
viewModel.successLiveData.observe(this, {
|
||||
}
|
||||
viewModel.successLiveData.observe(this) {
|
||||
binding.rotateLoading.hide()
|
||||
if (it > 0) {
|
||||
adapter.setItems(viewModel.allRules)
|
||||
@@ -106,7 +106,7 @@ class ImportReplaceRuleDialog() : BaseDialogFragment(R.layout.dialog_recycler_vi
|
||||
visible()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
val source = arguments?.getString("source")
|
||||
if (source.isNullOrEmpty()) {
|
||||
dismiss()
|
||||
|
||||
@@ -6,12 +6,15 @@ import io.legado.app.base.BaseViewModel
|
||||
import io.legado.app.constant.AppPattern
|
||||
import io.legado.app.data.appDb
|
||||
import io.legado.app.data.entities.ReplaceRule
|
||||
import io.legado.app.exception.NoStackTraceException
|
||||
import io.legado.app.help.ReplaceAnalyzer
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.help.http.newCallResponseBody
|
||||
import io.legado.app.help.http.okHttpClient
|
||||
import io.legado.app.help.http.text
|
||||
import io.legado.app.utils.isAbsUrl
|
||||
import io.legado.app.utils.isJsonArray
|
||||
import io.legado.app.utils.isJsonObject
|
||||
import io.legado.app.utils.splitNotBlank
|
||||
|
||||
class ImportReplaceRuleViewModel(app: Application) : BaseViewModel(app) {
|
||||
@@ -83,17 +86,7 @@ class ImportReplaceRuleViewModel(app: Application) : BaseViewModel(app) {
|
||||
|
||||
fun import(text: String) {
|
||||
execute {
|
||||
if (text.isAbsUrl()) {
|
||||
okHttpClient.newCallResponseBody {
|
||||
url(text)
|
||||
}.text("utf-8").let {
|
||||
val rules = ReplaceAnalyzer.jsonToReplaceRules(it)
|
||||
allRules.addAll(rules)
|
||||
}
|
||||
} else {
|
||||
val rules = ReplaceAnalyzer.jsonToReplaceRules(text)
|
||||
allRules.addAll(rules)
|
||||
}
|
||||
importAwait(text.trim())
|
||||
}.onError {
|
||||
errorLiveData.postValue(it.localizedMessage ?: "ERROR")
|
||||
}.onSuccess {
|
||||
@@ -101,6 +94,29 @@ class ImportReplaceRuleViewModel(app: Application) : BaseViewModel(app) {
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun importAwait(text: String) {
|
||||
when {
|
||||
text.isAbsUrl() -> importUrl(text)
|
||||
text.isJsonArray() -> {
|
||||
val rules = ReplaceAnalyzer.jsonToReplaceRules(text).getOrThrow()
|
||||
allRules.addAll(rules)
|
||||
}
|
||||
text.isJsonObject() -> {
|
||||
val rule = ReplaceAnalyzer.jsonToReplaceRule(text).getOrThrow()
|
||||
allRules.add(rule)
|
||||
}
|
||||
else -> throw NoStackTraceException("格式不对")
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun importUrl(url: String) {
|
||||
okHttpClient.newCallResponseBody {
|
||||
url(url)
|
||||
}.text("utf-8").let {
|
||||
importAwait(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun comparisonSource() {
|
||||
execute {
|
||||
allRules.forEach {
|
||||
|
||||
@@ -9,10 +9,10 @@ import android.widget.LinearLayout
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.preference.Preference
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.BasePreferenceFragment
|
||||
import io.legado.app.constant.EventBus
|
||||
import io.legado.app.constant.PreferKey
|
||||
import io.legado.app.help.config.ReadBookConfig
|
||||
import io.legado.app.lib.prefs.fragment.PreferenceFragment
|
||||
import io.legado.app.lib.theme.bottomBackground
|
||||
import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.model.ReadBook
|
||||
@@ -67,7 +67,7 @@ class MoreConfigDialog : DialogFragment() {
|
||||
(activity as ReadBookActivity).bottomDialog--
|
||||
}
|
||||
|
||||
class ReadPreferenceFragment : BasePreferenceFragment(),
|
||||
class ReadPreferenceFragment : PreferenceFragment(),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
|
||||
@@ -10,12 +10,12 @@ import androidx.fragment.app.DialogFragment
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.BasePreferenceFragment
|
||||
import io.legado.app.constant.EventBus
|
||||
import io.legado.app.constant.PreferKey
|
||||
import io.legado.app.data.appDb
|
||||
import io.legado.app.help.IntentHelp
|
||||
import io.legado.app.lib.dialogs.SelectItem
|
||||
import io.legado.app.lib.prefs.fragment.PreferenceFragment
|
||||
import io.legado.app.lib.theme.backgroundColor
|
||||
import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.model.ReadAloud
|
||||
@@ -54,7 +54,7 @@ class ReadAloudConfigDialog : DialogFragment() {
|
||||
.commit()
|
||||
}
|
||||
|
||||
class ReadAloudPreferenceFragment : BasePreferenceFragment(),
|
||||
class ReadAloudPreferenceFragment : PreferenceFragment(),
|
||||
SpeakEngineDialog.CallBack,
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
|
||||
@@ -19,8 +19,10 @@ import io.legado.app.utils.gone
|
||||
import io.legado.app.utils.longToastOnUi
|
||||
import io.legado.app.utils.visible
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.Dispatchers.Main
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
class ChapterListAdapter(context: Context, val callback: Callback) :
|
||||
@@ -54,17 +56,10 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
|
||||
|
||||
}
|
||||
|
||||
private val replaceRules
|
||||
get() = callback.book?.let {
|
||||
ContentProcessor.get(it.name, it.origin).getTitleReplaceRules()
|
||||
}
|
||||
private val useReplace
|
||||
get() = AppConfig.tocUiUseReplace && callback.book?.getUseReplaceRule() == true
|
||||
private var upDisplayTileJob: Coroutine<*>? = null
|
||||
|
||||
override fun onCurrentListChanged() {
|
||||
super.onCurrentListChanged()
|
||||
upDisplayTitle()
|
||||
callback.onListChanged()
|
||||
}
|
||||
|
||||
@@ -73,38 +68,52 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
|
||||
displayTitleMap.clear()
|
||||
}
|
||||
|
||||
fun upDisplayTitle() {
|
||||
fun upDisplayTitles(startIndex: Int) {
|
||||
upDisplayTileJob?.cancel()
|
||||
upDisplayTileJob = Coroutine.async(callback.scope) {
|
||||
val replaceRules = replaceRules
|
||||
val useReplace = useReplace
|
||||
getItems().forEach {
|
||||
if (!isActive) {
|
||||
return@async
|
||||
val book = callback.book ?: return@async
|
||||
val replaceRules = ContentProcessor.get(book.name, book.origin).getTitleReplaceRules()
|
||||
val useReplace = AppConfig.tocUiUseReplace && book.getUseReplaceRule()
|
||||
val items = getItems()
|
||||
async {
|
||||
for (i in startIndex until items.size) {
|
||||
val item = items[i]
|
||||
if (displayTitleMap[item.title] == null) {
|
||||
ensureActive()
|
||||
val displayTitle = item.getDisplayTitle(replaceRules, useReplace)
|
||||
ensureActive()
|
||||
displayTitleMap[item.title] = displayTitle
|
||||
withContext(Main) {
|
||||
notifyItemChanged(i, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (displayTitleMap[it.title] == null) {
|
||||
displayTitleMap[it.title] = it.getDisplayTitle(replaceRules, useReplace)
|
||||
}.start()
|
||||
async {
|
||||
for (i in startIndex downTo 0) {
|
||||
val item = items[i]
|
||||
if (displayTitleMap[item.title] == null) {
|
||||
ensureActive()
|
||||
val displayTitle = item.getDisplayTitle(replaceRules, useReplace)
|
||||
ensureActive()
|
||||
displayTitleMap[item.title] = displayTitle
|
||||
withContext(Main) {
|
||||
notifyItemChanged(i, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDisplayTitle(chapter: BookChapter): String {
|
||||
return displayTitleMap[chapter.title] ?: chapter.title
|
||||
}
|
||||
|
||||
override fun getViewBinding(parent: ViewGroup): ItemChapterListBinding {
|
||||
return ItemChapterListBinding.inflate(inflater, parent, false)
|
||||
}
|
||||
|
||||
private fun getDisplayTile(chapter: BookChapter): String {
|
||||
var displayTitle = displayTitleMap[chapter.title]
|
||||
if (displayTitle != null) {
|
||||
return displayTitle
|
||||
}
|
||||
displayTitle = runBlocking {
|
||||
chapter.getDisplayTitle(replaceRules, useReplace)
|
||||
}
|
||||
displayTitleMap[chapter.title] = displayTitle
|
||||
return displayTitle
|
||||
}
|
||||
|
||||
override fun convert(
|
||||
holder: ItemViewHolder,
|
||||
binding: ItemChapterListBinding,
|
||||
@@ -120,7 +129,7 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
|
||||
} else {
|
||||
tvChapterName.setTextColor(context.getCompatColor(R.color.primaryText))
|
||||
}
|
||||
tvChapterName.text = getDisplayTile(item)
|
||||
tvChapterName.text = getDisplayTitle(item)
|
||||
if (item.isVolume) {
|
||||
//卷名,如第一卷 突出显示
|
||||
tvChapterItem.setBackgroundColor(context.getCompatColor(R.color.btn_bg_press))
|
||||
@@ -138,6 +147,7 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
|
||||
}
|
||||
upHasCache(binding, isDur, cached)
|
||||
} else {
|
||||
tvChapterName.text = getDisplayTitle(item)
|
||||
upHasCache(binding, isDur, cached)
|
||||
}
|
||||
}
|
||||
@@ -150,8 +160,8 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
|
||||
}
|
||||
}
|
||||
holder.itemView.setOnLongClickListener {
|
||||
getItem(holder.layoutPosition)?.let {
|
||||
context.longToastOnUi(getDisplayTile(it))
|
||||
getItem(holder.layoutPosition)?.let { item ->
|
||||
context.longToastOnUi(getDisplayTitle(item))
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
@@ -97,7 +97,15 @@ class ChapterListFragment : VMBaseFragment<TocViewModel>(R.layout.fragment_chapt
|
||||
viewModel.bookData.value?.bookUrl?.let { bookUrl ->
|
||||
if (chapter.bookUrl == bookUrl) {
|
||||
adapter.cacheFileNames.add(chapter.getFileName())
|
||||
adapter.notifyItemChanged(chapter.index, true)
|
||||
if (viewModel.searchKey.isNullOrEmpty()) {
|
||||
adapter.notifyItemChanged(chapter.index, true)
|
||||
} else {
|
||||
adapter.getItems().forEachIndexed { index, bookChapter ->
|
||||
if (bookChapter.index == chapter.index) {
|
||||
adapter.notifyItemChanged(index, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,12 +136,13 @@ class ChapterListFragment : VMBaseFragment<TocViewModel>(R.layout.fragment_chapt
|
||||
}
|
||||
}
|
||||
mLayoutManager.scrollToPositionWithOffset(scrollPos, 0)
|
||||
adapter.upDisplayTitles(scrollPos)
|
||||
}
|
||||
}
|
||||
|
||||
override fun clearDisplayTitle() {
|
||||
adapter.clearDisplayTitle()
|
||||
adapter.upDisplayTitle()
|
||||
adapter.upDisplayTitles(mLayoutManager.findFirstVisibleItemPosition())
|
||||
}
|
||||
|
||||
override val scope: CoroutineScope
|
||||
|
||||
@@ -59,10 +59,12 @@ class TocActivity : VMBaseActivity<ActivityChapterListBinding, TocViewModel>() {
|
||||
setOnSearchClickListener { tabLayout.gone() }
|
||||
setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query: String): Boolean {
|
||||
viewModel.searchKey = query
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onQueryTextChange(newText: String): Boolean {
|
||||
viewModel.searchKey = newText
|
||||
if (tabLayout.selectedTabPosition == 1) {
|
||||
viewModel.startBookmarkSearch(newText)
|
||||
} else {
|
||||
|
||||
@@ -12,6 +12,7 @@ class TocViewModel(application: Application) : BaseViewModel(application) {
|
||||
var bookData = MutableLiveData<Book>()
|
||||
var chapterListCallBack: ChapterListCallBack? = null
|
||||
var bookMarkCallBack: BookmarkCallBack? = null
|
||||
var searchKey: String? = null
|
||||
|
||||
fun initBook(bookUrl: String) {
|
||||
this.bookUrl = bookUrl
|
||||
|
||||
@@ -15,7 +15,6 @@ import androidx.preference.EditTextPreference
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.BasePreferenceFragment
|
||||
import io.legado.app.constant.AppLog
|
||||
import io.legado.app.constant.PreferKey
|
||||
import io.legado.app.help.config.AppConfig
|
||||
@@ -25,7 +24,7 @@ import io.legado.app.help.storage.*
|
||||
import io.legado.app.lib.dialogs.alert
|
||||
import io.legado.app.lib.permission.Permissions
|
||||
import io.legado.app.lib.permission.PermissionsCompat
|
||||
import io.legado.app.lib.theme.accentColor
|
||||
import io.legado.app.lib.prefs.fragment.PreferenceFragment
|
||||
import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.ui.document.HandleFileContract
|
||||
import io.legado.app.ui.widget.dialog.TextDialog
|
||||
@@ -34,7 +33,7 @@ import kotlinx.coroutines.Dispatchers.Main
|
||||
import kotlinx.coroutines.launch
|
||||
import splitties.init.appCtx
|
||||
|
||||
class BackupConfigFragment : BasePreferenceFragment(),
|
||||
class BackupConfigFragment : PreferenceFragment(),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private val viewModel by activityViewModels<ConfigViewModel>()
|
||||
@@ -100,34 +99,18 @@ class BackupConfigFragment : BasePreferenceFragment(),
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_config_backup)
|
||||
findPreference<EditTextPreference>(PreferKey.webDavUrl)?.let {
|
||||
it.setOnBindEditTextListener { editText ->
|
||||
editText.applyTint(requireContext().accentColor)
|
||||
}
|
||||
}
|
||||
findPreference<EditTextPreference>(PreferKey.webDavAccount)?.let {
|
||||
it.setOnBindEditTextListener { editText ->
|
||||
editText.applyTint(requireContext().accentColor)
|
||||
}
|
||||
}
|
||||
findPreference<EditTextPreference>(PreferKey.webDavPassword)?.let {
|
||||
it.setOnBindEditTextListener { editText ->
|
||||
editText.applyTint(requireContext().accentColor)
|
||||
editText.inputType =
|
||||
InputType.TYPE_TEXT_VARIATION_PASSWORD or InputType.TYPE_CLASS_TEXT
|
||||
}
|
||||
}
|
||||
findPreference<EditTextPreference>(PreferKey.webDavDir)?.let {
|
||||
it.setOnBindEditTextListener { editText ->
|
||||
editText.applyTint(requireContext().accentColor)
|
||||
}
|
||||
}
|
||||
upPreferenceSummary(PreferKey.webDavUrl, getPrefString(PreferKey.webDavUrl))
|
||||
upPreferenceSummary(PreferKey.webDavAccount, getPrefString(PreferKey.webDavAccount))
|
||||
upPreferenceSummary(PreferKey.webDavPassword, getPrefString(PreferKey.webDavPassword))
|
||||
upPreferenceSummary(PreferKey.webDavDir, AppConfig.webDavDir)
|
||||
upPreferenceSummary(PreferKey.backupPath, getPrefString(PreferKey.backupPath))
|
||||
findPreference<io.legado.app.ui.widget.prefs.Preference>("web_dav_restore")
|
||||
findPreference<io.legado.app.lib.prefs.Preference>("web_dav_restore")
|
||||
?.onLongClick { restoreDir.launch(); true }
|
||||
}
|
||||
|
||||
|
||||
@@ -7,16 +7,16 @@ import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.preference.Preference
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.BasePreferenceFragment
|
||||
import io.legado.app.constant.PreferKey
|
||||
import io.legado.app.lib.dialogs.selector
|
||||
import io.legado.app.lib.prefs.SwitchPreference
|
||||
import io.legado.app.lib.prefs.fragment.PreferenceFragment
|
||||
import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.model.BookCover
|
||||
import io.legado.app.ui.widget.prefs.SwitchPreference
|
||||
import io.legado.app.utils.*
|
||||
import java.io.FileOutputStream
|
||||
|
||||
class CoverConfigFragment : BasePreferenceFragment(),
|
||||
class CoverConfigFragment : PreferenceFragment(),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private val requestCodeCover = 111
|
||||
|
||||
@@ -10,12 +10,12 @@ import androidx.fragment.app.activityViewModels
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.BasePreferenceFragment
|
||||
import io.legado.app.constant.EventBus
|
||||
import io.legado.app.constant.PreferKey
|
||||
import io.legado.app.databinding.DialogEditTextBinding
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.lib.dialogs.alert
|
||||
import io.legado.app.lib.prefs.fragment.PreferenceFragment
|
||||
import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.model.CheckSource
|
||||
import io.legado.app.receiver.SharedReceiverActivity
|
||||
@@ -26,7 +26,7 @@ import io.legado.app.utils.*
|
||||
import splitties.init.appCtx
|
||||
|
||||
|
||||
class OtherConfigFragment : BasePreferenceFragment(),
|
||||
class OtherConfigFragment : PreferenceFragment(),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private val viewModel by activityViewModels<ConfigViewModel>()
|
||||
|
||||
@@ -13,7 +13,6 @@ import android.widget.SeekBar
|
||||
import androidx.preference.Preference
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.AppContextWrapper
|
||||
import io.legado.app.base.BasePreferenceFragment
|
||||
import io.legado.app.constant.AppConst
|
||||
import io.legado.app.constant.EventBus
|
||||
import io.legado.app.constant.PreferKey
|
||||
@@ -24,16 +23,17 @@ import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.help.config.ThemeConfig
|
||||
import io.legado.app.lib.dialogs.alert
|
||||
import io.legado.app.lib.dialogs.selector
|
||||
import io.legado.app.lib.prefs.ColorPreference
|
||||
import io.legado.app.lib.prefs.fragment.PreferenceFragment
|
||||
import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.ui.widget.number.NumberPickerDialog
|
||||
import io.legado.app.ui.widget.prefs.ColorPreference
|
||||
import io.legado.app.ui.widget.seekbar.SeekBarChangeListener
|
||||
import io.legado.app.utils.*
|
||||
import java.io.FileOutputStream
|
||||
|
||||
|
||||
@Suppress("SameParameterValue")
|
||||
class ThemeConfigFragment : BasePreferenceFragment(),
|
||||
class ThemeConfigFragment : PreferenceFragment(),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private val requestCodeBgLight = 121
|
||||
|
||||
@@ -7,15 +7,15 @@ import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.preference.Preference
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.BasePreferenceFragment
|
||||
import io.legado.app.constant.PreferKey
|
||||
import io.legado.app.lib.dialogs.selector
|
||||
import io.legado.app.lib.prefs.fragment.PreferenceFragment
|
||||
import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.model.BookCover
|
||||
import io.legado.app.utils.*
|
||||
import java.io.FileOutputStream
|
||||
|
||||
class WelcomeConfigFragment : BasePreferenceFragment(),
|
||||
class WelcomeConfigFragment : PreferenceFragment(),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private val requestWelcomeImage = 221
|
||||
|
||||
@@ -8,13 +8,16 @@ import android.view.View
|
||||
import androidx.preference.Preference
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.BaseFragment
|
||||
import io.legado.app.base.BasePreferenceFragment
|
||||
import io.legado.app.constant.EventBus
|
||||
import io.legado.app.constant.PreferKey
|
||||
import io.legado.app.databinding.FragmentMyConfigBinding
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.help.config.ThemeConfig
|
||||
import io.legado.app.lib.dialogs.selector
|
||||
import io.legado.app.lib.prefs.NameListPreference
|
||||
import io.legado.app.lib.prefs.PreferenceCategory
|
||||
import io.legado.app.lib.prefs.SwitchPreference
|
||||
import io.legado.app.lib.prefs.fragment.PreferenceFragment
|
||||
import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.service.WebService
|
||||
import io.legado.app.ui.about.AboutActivity
|
||||
@@ -26,9 +29,6 @@ import io.legado.app.ui.config.ConfigActivity
|
||||
import io.legado.app.ui.config.ConfigTag
|
||||
import io.legado.app.ui.replace.ReplaceRuleActivity
|
||||
import io.legado.app.ui.widget.dialog.TextDialog
|
||||
import io.legado.app.ui.widget.prefs.NameListPreference
|
||||
import io.legado.app.ui.widget.prefs.PreferenceCategory
|
||||
import io.legado.app.ui.widget.prefs.SwitchPreference
|
||||
import io.legado.app.utils.*
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
|
||||
@@ -40,7 +40,7 @@ class MyFragment : BaseFragment(R.layout.fragment_my_config) {
|
||||
setSupportToolbar(binding.titleBar.toolbar)
|
||||
val fragmentTag = "prefFragment"
|
||||
var preferenceFragment = childFragmentManager.findFragmentByTag(fragmentTag)
|
||||
if (preferenceFragment == null) preferenceFragment = PreferenceFragment()
|
||||
if (preferenceFragment == null) preferenceFragment = MyPreferenceFragment()
|
||||
childFragmentManager.beginTransaction()
|
||||
.replace(R.id.pre_fragment, preferenceFragment, fragmentTag).commit()
|
||||
}
|
||||
@@ -61,7 +61,7 @@ class MyFragment : BaseFragment(R.layout.fragment_my_config) {
|
||||
/**
|
||||
* 配置
|
||||
*/
|
||||
class PreferenceFragment : BasePreferenceFragment(),
|
||||
class MyPreferenceFragment : PreferenceFragment(),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import io.legado.app.base.VMBaseActivity
|
||||
import io.legado.app.databinding.ActivityRssArtivlesBinding
|
||||
import io.legado.app.databinding.DialogEditTextBinding
|
||||
import io.legado.app.lib.dialogs.alert
|
||||
import io.legado.app.lib.theme.accentColor
|
||||
import io.legado.app.ui.login.SourceLoginActivity
|
||||
import io.legado.app.ui.rss.source.edit.RssSourceEditActivity
|
||||
import io.legado.app.utils.StartActivityContract
|
||||
@@ -45,9 +46,10 @@ class RssSortActivity : VMBaseActivity<ActivityRssArtivlesBinding, RssSortViewMo
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
binding.viewPager.adapter = adapter
|
||||
binding.tabLayout.setupWithViewPager(binding.viewPager)
|
||||
viewModel.titleLiveData.observe(this, {
|
||||
binding.tabLayout.setSelectedTabIndicatorColor(accentColor)
|
||||
viewModel.titleLiveData.observe(this) {
|
||||
binding.titleBar.title = it
|
||||
})
|
||||
}
|
||||
viewModel.initData(intent) {
|
||||
upFragments()
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
package io.legado.app.ui.widget.prefs
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.widget.TextView
|
||||
import androidx.preference.PreferenceViewHolder
|
||||
import io.legado.app.R
|
||||
|
||||
class EditTextPreference(context: Context, attrs: AttributeSet) :
|
||||
androidx.preference.EditTextPreference(context, attrs) {
|
||||
|
||||
init {
|
||||
// isPersistent = true
|
||||
layoutResource = R.layout.view_preference
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||
Preference.bindView<TextView>(context, holder, icon, title, summary, null, null)
|
||||
super.onBindViewHolder(holder)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import splitties.init.appCtx
|
||||
import kotlin.concurrent.thread
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.resumeWithException
|
||||
|
||||
/**
|
||||
* 带有超时检测的正则替换
|
||||
@@ -19,7 +20,7 @@ suspend fun CharSequence.replace(regex: Regex, replacement: String, timeout: Lon
|
||||
val result = regex.replace(charSequence, replacement)
|
||||
block.resume(result)
|
||||
} catch (e: Exception) {
|
||||
block.cancel(e)
|
||||
block.resumeWithException(e)
|
||||
}
|
||||
}
|
||||
mainHandler.postDelayed({
|
||||
|
||||
Reference in New Issue
Block a user