feat: 合并 sigma 书源编辑与 JS 扩展功能
书源编辑界面: - 新增事件监听、定制按钮 CheckBox 绑定 - 新增 callBackJs 字段接入正文规则 - 新增 menu_log 菜单项 (AppLogDialog) - 新增撤销/重做回调 (KeyboardToolPop.CallBack) - sendText() 智能滚动逻辑 - 保存时清除并发限制缓存 JS 扩展函数 (#1368): - 新增 refreshBookToc() 方法 - reLoginView() 增加 deltaUp 参数 - upLoginData() 参数类型改为 Map<String, Any?>? - SourceLoginDialog 适配新回调接口 - ExploreKindUiUseCase 适配新回调接口 BookInfo 事件监听: - BookInfoViewModel 监听 REFRESH_BOOK_INFO/REFRESH_BOOK_TOC 事件 - 书源 JS 函数可触发书籍信息和目录刷新
This commit is contained in:
@@ -35,6 +35,7 @@ object EventBus {
|
|||||||
const val UP_MANGA_CONFIG = "upMangaConfig"
|
const val UP_MANGA_CONFIG = "upMangaConfig"
|
||||||
const val PLAY_MODE_CHANGED = "playModeChanged"
|
const val PLAY_MODE_CHANGED = "playModeChanged"
|
||||||
const val REFRESH_BOOK_INFO = "refreshBookInfo"
|
const val REFRESH_BOOK_INFO = "refreshBookInfo"
|
||||||
|
const val REFRESH_BOOK_TOC = "refreshBookToc"
|
||||||
const val REFRESH_BOOK_CONTENT = "refreshBookContent"
|
const val REFRESH_BOOK_CONTENT = "refreshBookContent"
|
||||||
const val UP_TOC = "upToc"
|
const val UP_TOC = "upToc"
|
||||||
|
|
||||||
|
|||||||
@@ -72,8 +72,8 @@ class ExploreKindUiUseCase(
|
|||||||
activity = activity,
|
activity = activity,
|
||||||
source = source,
|
source = source,
|
||||||
callback = object : SourceLoginJsExtensions.Callback {
|
callback = object : SourceLoginJsExtensions.Callback {
|
||||||
override fun upUiData(data: Map<String, String?>?) = Unit
|
override fun upUiData(data: Map<String, Any?>?) = Unit
|
||||||
override fun reUiView() = onRefreshKinds()
|
override fun reUiView(deltaUp: Boolean) = onRefreshKinds()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
|
|||||||
@@ -74,6 +74,9 @@ import kotlinx.coroutines.flow.MutableSharedFlow
|
|||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asSharedFlow
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
@@ -99,6 +102,35 @@ class BookInfoViewModel(
|
|||||||
private val _effects = MutableSharedFlow<BookInfoEffect>(extraBufferCapacity = 8)
|
private val _effects = MutableSharedFlow<BookInfoEffect>(extraBufferCapacity = 8)
|
||||||
val effects = _effects.asSharedFlow()
|
val effects = _effects.asSharedFlow()
|
||||||
|
|
||||||
|
init {
|
||||||
|
collectEventBus()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun collectEventBus() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
eventFlow<Boolean>(EventBus.REFRESH_BOOK_INFO).collect {
|
||||||
|
currentBook?.let { book ->
|
||||||
|
refreshBook(book)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewModelScope.launch {
|
||||||
|
eventFlow<Boolean>(EventBus.REFRESH_BOOK_TOC).collect {
|
||||||
|
currentBook?.let { book ->
|
||||||
|
loadChapter(book)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <reified T> eventFlow(tag: String): Flow<T> = callbackFlow {
|
||||||
|
val obs = androidx.lifecycle.Observer<T> { trySend(it) }
|
||||||
|
com.jeremyliao.liveeventbus.LiveEventBus.get<T>(tag).observeForever(obs)
|
||||||
|
awaitClose {
|
||||||
|
com.jeremyliao.liveeventbus.LiveEventBus.get<T>(tag).removeObserver(obs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private var currentBook: Book? = null
|
private var currentBook: Book? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package io.legado.app.ui.book.source.edit
|
package io.legado.app.ui.book.source.edit
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
|
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
|
||||||
@@ -24,9 +26,7 @@ import io.legado.app.help.config.LocalConfig
|
|||||||
import io.legado.app.lib.dialogs.SelectItem
|
import io.legado.app.lib.dialogs.SelectItem
|
||||||
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.accentColor
|
import io.legado.app.ui.about.AppLogDialog
|
||||||
//import io.legado.app.lib.theme.backgroundColor
|
|
||||||
//import io.legado.app.lib.theme.primaryColor
|
|
||||||
import io.legado.app.ui.book.search.SearchActivity
|
import io.legado.app.ui.book.search.SearchActivity
|
||||||
import io.legado.app.ui.book.search.SearchScope
|
import io.legado.app.ui.book.search.SearchScope
|
||||||
import io.legado.app.ui.book.source.debug.BookSourceDebugActivity
|
import io.legado.app.ui.book.source.debug.BookSourceDebugActivity
|
||||||
@@ -146,6 +146,7 @@ class BookSourceEditActivity :
|
|||||||
ErrorCorrectionLevel.L
|
ErrorCorrectionLevel.L
|
||||||
)
|
)
|
||||||
|
|
||||||
|
R.id.menu_log -> showDialogFragment<AppLogDialog>()
|
||||||
R.id.menu_help -> showHelp("ruleHelp")
|
R.id.menu_help -> showHelp("ruleHelp")
|
||||||
R.id.menu_login -> viewModel.save(getSource()) { source ->
|
R.id.menu_login -> viewModel.save(getSource()) { source ->
|
||||||
startActivity<SourceLoginActivity> {
|
startActivity<SourceLoginActivity> {
|
||||||
@@ -261,6 +262,8 @@ class BookSourceEditActivity :
|
|||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
binding.cbIsEventListener.isChecked = it.eventListener
|
||||||
|
binding.cbIsCustomButton.isChecked = it.customButton
|
||||||
}
|
}
|
||||||
// 基本信息
|
// 基本信息
|
||||||
sourceEntities.clear()
|
sourceEntities.clear()
|
||||||
@@ -361,6 +364,7 @@ class BookSourceEditActivity :
|
|||||||
add(EditEntity("imageStyle", cr.imageStyle, R.string.rule_image_style))
|
add(EditEntity("imageStyle", cr.imageStyle, R.string.rule_image_style))
|
||||||
add(EditEntity("imageDecode", cr.imageDecode, R.string.rule_image_decode))
|
add(EditEntity("imageDecode", cr.imageDecode, R.string.rule_image_decode))
|
||||||
add(EditEntity("payAction", cr.payAction, R.string.rule_pay_action))
|
add(EditEntity("payAction", cr.payAction, R.string.rule_pay_action))
|
||||||
|
add(EditEntity("callBackJs", cr.callBackJs, R.string.rule_call_back))
|
||||||
}
|
}
|
||||||
|
|
||||||
// val rr = bs.getReviewRule()
|
// val rr = bs.getReviewRule()
|
||||||
@@ -392,6 +396,8 @@ class BookSourceEditActivity :
|
|||||||
1 -> BookSourceType.audio
|
1 -> BookSourceType.audio
|
||||||
else -> BookSourceType.default
|
else -> BookSourceType.default
|
||||||
}
|
}
|
||||||
|
source.eventListener = binding.cbIsEventListener.isChecked
|
||||||
|
source.customButton = binding.cbIsCustomButton.isChecked
|
||||||
val searchRule = SearchRule()
|
val searchRule = SearchRule()
|
||||||
val exploreRule = ExploreRule()
|
val exploreRule = ExploreRule()
|
||||||
val bookInfoRule = BookInfoRule()
|
val bookInfoRule = BookInfoRule()
|
||||||
@@ -559,6 +565,7 @@ class BookSourceEditActivity :
|
|||||||
"imageStyle" -> contentRule.imageStyle = it.value
|
"imageStyle" -> contentRule.imageStyle = it.value
|
||||||
"imageDecode" -> contentRule.imageDecode = it.value
|
"imageDecode" -> contentRule.imageDecode = it.value
|
||||||
"payAction" -> contentRule.payAction = it.value
|
"payAction" -> contentRule.payAction = it.value
|
||||||
|
"callBackJs" -> contentRule.callBackJs = it.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// reviewEntities.forEach {
|
// reviewEntities.forEach {
|
||||||
@@ -592,6 +599,22 @@ class BookSourceEditActivity :
|
|||||||
return source
|
return source
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.M)
|
||||||
|
override fun onUndoClicked() {
|
||||||
|
val editText = window.decorView.findFocus()
|
||||||
|
if (editText is EditText) {
|
||||||
|
editText.onTextContextMenuItem(android.R.id.undo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.M)
|
||||||
|
override fun onRedoClicked() {
|
||||||
|
val editText = window.decorView.findFocus()
|
||||||
|
if (editText is EditText) {
|
||||||
|
editText.onTextContextMenuItem(android.R.id.redo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun alertGroups() {
|
private fun alertGroups() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val groups = withContext(IO) {
|
val groups = withContext(IO) {
|
||||||
@@ -643,20 +666,46 @@ class BookSourceEditActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun sendText(text: String) {
|
override fun sendText(text: String) {
|
||||||
if (text.isBlank()) return
|
|
||||||
val view = window.decorView.findFocus()
|
val view = window.decorView.findFocus()
|
||||||
if (view is EditText) {
|
if (view is EditText) {
|
||||||
val start = view.selectionStart
|
var start = view.selectionStart
|
||||||
val end = view.selectionEnd
|
var end = view.selectionEnd
|
||||||
|
if (start > end) {
|
||||||
|
val temp = start
|
||||||
|
start = end
|
||||||
|
end = temp
|
||||||
|
}
|
||||||
|
if (text.isNotEmpty()) {
|
||||||
val edit = view.editableText//获取EditText的文字
|
val edit = view.editableText//获取EditText的文字
|
||||||
if (start < 0 || start >= edit.length) {
|
if (start < 0 || start >= edit.length) {
|
||||||
edit.append(text)
|
edit.append(text)
|
||||||
} else if (start > end) {
|
|
||||||
edit.replace(end, start, text)
|
|
||||||
} else {
|
} else {
|
||||||
edit.replace(start, end, text)//光标所在位置插入文字
|
edit.replace(start, end, text)//光标所在位置插入文字
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (adapter.editEntityMaxLine >= 999) {
|
||||||
|
view.post {
|
||||||
|
val editTextLocation = IntArray(2)
|
||||||
|
view.getLocationOnScreen(editTextLocation)
|
||||||
|
val recyclerViewLocation = IntArray(2)
|
||||||
|
binding.recyclerView.getLocationOnScreen(recyclerViewLocation)
|
||||||
|
val layout = view.layout
|
||||||
|
if (layout != null) {
|
||||||
|
val line = layout.getLineForOffset(end)
|
||||||
|
val cursorYInEditText = layout.getLineTop(line)
|
||||||
|
val cursorYOnScreen = editTextLocation[1] + cursorYInEditText
|
||||||
|
val cursorYInRecyclerView = cursorYOnScreen - recyclerViewLocation[1]
|
||||||
|
val recyclerViewBottom = binding.recyclerView.height - 120
|
||||||
|
if (cursorYInRecyclerView !in 0..recyclerViewBottom) {
|
||||||
|
val scrollDistance = cursorYInRecyclerView - recyclerViewBottom / 3
|
||||||
|
if (scrollDistance > 0 && binding.recyclerView.canScrollVertically(1) || scrollDistance < 0 && binding.recyclerView.canScrollVertically(-1)) {
|
||||||
|
binding.recyclerView.smoothScrollBy(0, scrollDistance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setSourceVariable() {
|
private fun setSourceVariable() {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ 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.exception.NoStackTraceException
|
import io.legado.app.exception.NoStackTraceException
|
||||||
|
import io.legado.app.help.ConcurrentRateLimiter.Companion.concurrentRecordMap
|
||||||
import io.legado.app.help.RuleComplete
|
import io.legado.app.help.RuleComplete
|
||||||
import io.legado.app.help.config.SourceConfig
|
import io.legado.app.help.config.SourceConfig
|
||||||
import io.legado.app.help.http.CookieStore
|
import io.legado.app.help.http.CookieStore
|
||||||
@@ -73,6 +74,7 @@ class BookSourceEditViewModel(application: Application) : BaseViewModel(applicat
|
|||||||
}
|
}
|
||||||
appDb.bookSourceDao.insert(source)
|
appDb.bookSourceDao.insert(source)
|
||||||
bookSource = source
|
bookSource = source
|
||||||
|
concurrentRecordMap.remove(source.bookSourceUrl)
|
||||||
source
|
source
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
success?.invoke(it)
|
success?.invoke(it)
|
||||||
|
|||||||
@@ -70,22 +70,22 @@ class SourceLoginDialog : BaseBottomSheetDialogFragment(R.layout.dialog_login) {
|
|||||||
viewModel.source,
|
viewModel.source,
|
||||||
viewModel.bookType,
|
viewModel.bookType,
|
||||||
callback = object : SourceLoginJsExtensions.Callback {
|
callback = object : SourceLoginJsExtensions.Callback {
|
||||||
override fun upUiData(data: Map<String, String?>?) {
|
override fun upUiData(data: Map<String, Any?>?) {
|
||||||
activity?.runOnUiThread { // 在主线程中更新 UI
|
activity?.runOnUiThread { // 在主线程中更新 UI
|
||||||
handleUpUiData(data)
|
handleUpUiData(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reUiView() {
|
override fun reUiView(deltaUp: Boolean) {
|
||||||
activity?.runOnUiThread {
|
activity?.runOnUiThread {
|
||||||
handleReUiView()
|
handleReUiView(deltaUp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleReUiView() {
|
private fun handleReUiView(deltaUp: Boolean = false) {
|
||||||
val source = viewModel.source ?: return
|
val source = viewModel.source ?: return
|
||||||
val loginUiStr = source.loginUi ?: return
|
val loginUiStr = source.loginUi ?: return
|
||||||
val codeStr = loginUiStr.let {
|
val codeStr = loginUiStr.let {
|
||||||
@@ -100,18 +100,16 @@ class SourceLoginDialog : BaseBottomSheetDialogFragment(R.layout.dialog_login) {
|
|||||||
lifecycleScope.launch(Main) {
|
lifecycleScope.launch(Main) {
|
||||||
val loginUiJson = evalUiJs(codeStr)
|
val loginUiJson = evalUiJs(codeStr)
|
||||||
rowUis = loginUi(loginUiJson)
|
rowUis = loginUi(loginUiJson)
|
||||||
binding.flexbox.removeAllViews()
|
rowUiBuilder(source, rowUis, deltaUp)
|
||||||
rowUiBuilder(source, rowUis)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rowUis = loginUi(loginUiStr)
|
rowUis = loginUi(loginUiStr)
|
||||||
binding.flexbox.removeAllViews()
|
rowUiBuilder(source, rowUis, deltaUp)
|
||||||
rowUiBuilder(source, rowUis)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
private fun handleUpUiData(data: Map<String, String?>?) {
|
private fun handleUpUiData(data: Map<String, Any?>?) {
|
||||||
hasChange = true
|
hasChange = true
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
val newLoginInfo: MutableMap<String, String> = mutableMapOf()
|
val newLoginInfo: MutableMap<String, String> = mutableMapOf()
|
||||||
@@ -163,22 +161,22 @@ class SourceLoginDialog : BaseBottomSheetDialogFragment(R.layout.dialog_login) {
|
|||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
when (val rowView = binding.root.findViewById<View>(index + 1000)) {
|
when (val rowView = binding.root.findViewById<View>(index + 1000)) {
|
||||||
is TextInputLayout -> {
|
is TextInputLayout -> {
|
||||||
val value = value ?: run {
|
val textValue = value?.toString() ?: run {
|
||||||
val rowUi = rowUis?.getOrNull(index) ?: return@forEach
|
val rowUi = rowUis?.getOrNull(index) ?: return@forEach
|
||||||
rowUi.default ?: ""
|
rowUi.default ?: ""
|
||||||
}
|
}
|
||||||
rowView.editText?.setText(value)
|
rowView.editText?.setText(textValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
is TextView -> {
|
is TextView -> {
|
||||||
val rowUi = rowUis?.getOrNull(index) ?: return@forEach
|
val rowUi = rowUis?.getOrNull(index) ?: return@forEach
|
||||||
when (rowUi.type) {
|
when (rowUi.type) {
|
||||||
Type.button -> {
|
Type.button -> {
|
||||||
rowView.text = value ?: key
|
rowView.text = value?.toString() ?: key
|
||||||
}
|
}
|
||||||
|
|
||||||
Type.toggle -> {
|
Type.toggle -> {
|
||||||
val char = value ?: run {
|
val char = value?.toString() ?: run {
|
||||||
val chars =
|
val chars =
|
||||||
rowUi.chars?.filterNotNull() ?: listOf("chars is null")
|
rowUi.chars?.filterNotNull() ?: listOf("chars is null")
|
||||||
chars.getOrNull(0) ?: ""
|
chars.getOrNull(0) ?: ""
|
||||||
@@ -194,8 +192,9 @@ class SourceLoginDialog : BaseBottomSheetDialogFragment(R.layout.dialog_login) {
|
|||||||
is LinearLayout -> {
|
is LinearLayout -> {
|
||||||
val rowUi = rowUis?.getOrNull(index) ?: return@forEach
|
val rowUi = rowUis?.getOrNull(index) ?: return@forEach
|
||||||
val items = rowUi.chars?.filterNotNull() ?: listOf("chars", "is null")
|
val items = rowUi.chars?.filterNotNull() ?: listOf("chars", "is null")
|
||||||
val index = items.indexOf(value)
|
val strValue = value?.toString()
|
||||||
loginInfo[rowUi.name] = value ?: run {
|
val index = items.indexOf(strValue)
|
||||||
|
loginInfo[rowUi.name] = strValue ?: run {
|
||||||
items.getOrNull(0) ?: ""
|
items.getOrNull(0) ?: ""
|
||||||
}
|
}
|
||||||
rowView.findViewById<AppCompatSpinner>(R.id.sp_type)
|
rowView.findViewById<AppCompatSpinner>(R.id.sp_type)
|
||||||
@@ -203,7 +202,7 @@ class SourceLoginDialog : BaseBottomSheetDialogFragment(R.layout.dialog_login) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
loginInfo[key] = value ?: ""
|
loginInfo[key] = value?.toString() ?: ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,9 +239,12 @@ class SourceLoginDialog : BaseBottomSheetDialogFragment(R.layout.dialog_login) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n", "ClickableViewAccessibility")
|
@SuppressLint("SetTextI18n", "ClickableViewAccessibility")
|
||||||
private fun rowUiBuilder(source: BaseSource, rowUis: List<RowUi>?) {
|
private fun rowUiBuilder(source: BaseSource, rowUis: List<RowUi>?, deltaUp: Boolean = false) {
|
||||||
val loginInfo = viewModel.loginInfo
|
val loginInfo = viewModel.loginInfo
|
||||||
|
if (!deltaUp) {
|
||||||
|
binding.flexbox.removeAllViews()
|
||||||
rowUiName.clear()
|
rowUiName.clear()
|
||||||
|
}
|
||||||
rowUis?.forEachIndexed { index, rowUi ->
|
rowUis?.forEachIndexed { index, rowUi ->
|
||||||
val type = rowUi.type
|
val type = rowUi.type
|
||||||
val name = rowUi.name
|
val name = rowUi.name
|
||||||
|
|||||||
@@ -27,16 +27,17 @@ class SourceLoginJsExtensions(
|
|||||||
) : RssJsExtensions(activity, source) {
|
) : RssJsExtensions(activity, source) {
|
||||||
private val callbackRef: WeakReference<Callback> = WeakReference(callback)
|
private val callbackRef: WeakReference<Callback> = WeakReference(callback)
|
||||||
interface Callback {
|
interface Callback {
|
||||||
fun upUiData(data: Map<String, String?>?)
|
fun upUiData(data: Map<String, Any?>?)
|
||||||
fun reUiView()
|
fun reUiView(deltaUp: Boolean = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun upLoginData(data: Map<String, String?>?) {
|
fun upLoginData(data: Map<String, Any?>?) {
|
||||||
callbackRef.get()?.upUiData(data)
|
callbackRef.get()?.upUiData(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reLoginView() {
|
@JvmOverloads
|
||||||
callbackRef.get()?.reUiView()
|
fun reLoginView(deltaUp: Boolean = false) {
|
||||||
|
callbackRef.get()?.reUiView(deltaUp)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshExplore() {
|
fun refreshExplore() {
|
||||||
@@ -47,6 +48,10 @@ class SourceLoginJsExtensions(
|
|||||||
postEvent(EventBus.REFRESH_BOOK_INFO, true)
|
postEvent(EventBus.REFRESH_BOOK_INFO, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun refreshBookToc() {
|
||||||
|
postEvent(EventBus.REFRESH_BOOK_TOC, true)
|
||||||
|
}
|
||||||
|
|
||||||
fun refreshContent() {
|
fun refreshContent() {
|
||||||
postEvent(EventBus.REFRESH_BOOK_CONTENT, true)
|
postEvent(EventBus.REFRESH_BOOK_CONTENT, true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,6 +175,8 @@ class KeyboardToolPop(
|
|||||||
|
|
||||||
fun sendText(text: String)
|
fun sendText(text: String)
|
||||||
|
|
||||||
|
fun onUndoClicked() {}
|
||||||
|
fun onRedoClicked() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,38 @@
|
|||||||
|
|
||||||
</HorizontalScrollView>
|
</HorizontalScrollView>
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:scrollbars="none"
|
||||||
|
android:paddingHorizontal="12dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:ignore="VisualLintBounds">
|
||||||
|
|
||||||
|
<io.legado.app.lib.theme.view.ThemeCheckBox
|
||||||
|
android:id="@+id/cb_is_event_listener"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="false"
|
||||||
|
android:text="@string/is_event_listener" />
|
||||||
|
|
||||||
|
<io.legado.app.lib.theme.view.ThemeCheckBox
|
||||||
|
android:id="@+id/cb_is_custom_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="false"
|
||||||
|
android:text="@string/custom_button" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</HorizontalScrollView>
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabLayout
|
<com.google.android.material.tabs.TabLayout
|
||||||
android:id="@+id/tab_layout"
|
android:id="@+id/tab_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -1168,6 +1168,9 @@
|
|||||||
<string name="enable_record">Enable record</string>
|
<string name="enable_record">Enable record</string>
|
||||||
<string name="copy_all">Copy all</string>
|
<string name="copy_all">Copy all</string>
|
||||||
<string name="auto_complete">Automatic completion</string>
|
<string name="auto_complete">Automatic completion</string>
|
||||||
|
<string name="is_event_listener">EventListener</string>
|
||||||
|
<string name="custom_button">Custom Button</string>
|
||||||
|
<string name="rule_call_back">callBackJs</string>
|
||||||
<string name="sort_by_size">Sort by size</string>
|
<string name="sort_by_size">Sort by size</string>
|
||||||
<string name="welcome_style">Launch interface style</string>
|
<string name="welcome_style">Launch interface style</string>
|
||||||
<string name="welcome_style_summary">Startup screen image and whether to display text, etc.</string>
|
<string name="welcome_style_summary">Startup screen image and whether to display text, etc.</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user