优化
This commit is contained in:
@@ -6,37 +6,11 @@ package io.legado.app.data.entities.rule
|
|||||||
data class ExploreKind(
|
data class ExploreKind(
|
||||||
val title: String = "",
|
val title: String = "",
|
||||||
val url: String? = null,
|
val url: String? = null,
|
||||||
val style: Style? = null
|
val style: FlexChildStyle? = null
|
||||||
) {
|
) {
|
||||||
|
|
||||||
companion object {
|
fun style(): FlexChildStyle {
|
||||||
val defaultStyle = Style()
|
return style ?: FlexChildStyle.defaultStyle
|
||||||
}
|
|
||||||
|
|
||||||
fun style(): Style {
|
|
||||||
return style ?: defaultStyle
|
|
||||||
}
|
|
||||||
|
|
||||||
data class Style(
|
|
||||||
val layout_flexGrow: Float = 0F,
|
|
||||||
val layout_flexShrink: Float = 1F,
|
|
||||||
val layout_alignSelf: String = "auto",
|
|
||||||
val layout_flexBasisPercent: Float = -1F,
|
|
||||||
val layout_wrapBefore: Boolean = false,
|
|
||||||
) {
|
|
||||||
|
|
||||||
fun alignSelf(): Int {
|
|
||||||
return when (layout_alignSelf) {
|
|
||||||
"auto" -> -1
|
|
||||||
"flex_start" -> 0
|
|
||||||
"flex_end" -> 1
|
|
||||||
"center" -> 2
|
|
||||||
"baseline" -> 3
|
|
||||||
"stretch" -> 4
|
|
||||||
else -> -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package io.legado.app.data.entities.rule
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import com.google.android.flexbox.FlexboxLayout
|
||||||
|
|
||||||
|
data class FlexChildStyle(
|
||||||
|
val layout_flexGrow: Float = 0F,
|
||||||
|
val layout_flexShrink: Float = 1F,
|
||||||
|
val layout_alignSelf: String = "auto",
|
||||||
|
val layout_flexBasisPercent: Float = -1F,
|
||||||
|
val layout_wrapBefore: Boolean = false,
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun alignSelf(): Int {
|
||||||
|
return when (layout_alignSelf) {
|
||||||
|
"auto" -> -1
|
||||||
|
"flex_start" -> 0
|
||||||
|
"flex_end" -> 1
|
||||||
|
"center" -> 2
|
||||||
|
"baseline" -> 3
|
||||||
|
"stretch" -> 4
|
||||||
|
else -> -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun apply(view: View) {
|
||||||
|
val lp = view.layoutParams as FlexboxLayout.LayoutParams
|
||||||
|
lp.flexGrow = layout_flexGrow
|
||||||
|
lp.flexShrink = layout_flexShrink
|
||||||
|
lp.alignSelf = alignSelf()
|
||||||
|
lp.flexBasisPercent = layout_flexBasisPercent
|
||||||
|
lp.isWrapBefore = layout_wrapBefore
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val defaultStyle = FlexChildStyle()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,15 +1,13 @@
|
|||||||
package io.legado.app.data.entities.rule
|
package io.legado.app.data.entities.rule
|
||||||
|
|
||||||
import android.os.Parcelable
|
|
||||||
import kotlinx.parcelize.Parcelize
|
|
||||||
|
|
||||||
@Parcelize
|
|
||||||
data class RowUi(
|
data class RowUi(
|
||||||
var name: String,
|
var name: String,
|
||||||
var type: String = "text",
|
var type: String = "text",
|
||||||
var action: String? = null
|
var action: String? = null,
|
||||||
) : Parcelable {
|
var style: FlexChildStyle? = null
|
||||||
|
) {
|
||||||
|
|
||||||
|
@Suppress("ConstPropertyName")
|
||||||
object Type {
|
object Type {
|
||||||
|
|
||||||
const val text = "text"
|
const val text = "text"
|
||||||
@@ -18,4 +16,8 @@ data class RowUi(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun style(): FlexChildStyle {
|
||||||
|
return style ?: FlexChildStyle.defaultStyle
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ object BookHelp {
|
|||||||
book.getFolderName(),
|
book.getFolderName(),
|
||||||
bookChapter.getFileName(),
|
bookChapter.getFileName(),
|
||||||
).writeText(content)
|
).writeText(content)
|
||||||
if (book.isOnLineTxt) {
|
if (book.isOnLineTxt && AppConfig.tocCountWords) {
|
||||||
bookChapter.wordCount = StringUtils.wordCountFormat(content.length)
|
bookChapter.wordCount = StringUtils.wordCountFormat(content.length)
|
||||||
appDb.bookChapterDao.update(bookChapter)
|
appDb.bookChapterDao.update(bookChapter)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -270,12 +270,15 @@ object BookChapterList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getWordCount(list: ArrayList<BookChapter>, book: Book) {
|
private fun getWordCount(list: ArrayList<BookChapter>, book: Book) {
|
||||||
|
if (!AppConfig.tocCountWords) {
|
||||||
|
return
|
||||||
|
}
|
||||||
val chapterList = appDb.bookChapterDao.getChapterList(book.bookUrl)
|
val chapterList = appDb.bookChapterDao.getChapterList(book.bookUrl)
|
||||||
if (chapterList.isNotEmpty()){
|
if (chapterList.isNotEmpty()) {
|
||||||
val map = chapterList.associateBy({ it.getFileName() }, { it.wordCount })
|
val map = chapterList.associateBy({ it.getFileName() }, { it.wordCount })
|
||||||
for (bookChapter in list) {
|
for (bookChapter in list) {
|
||||||
val wordCount = map[bookChapter.getFileName()]
|
val wordCount = map[bookChapter.getFileName()]
|
||||||
if(wordCount != null){
|
if (wordCount != null) {
|
||||||
bookChapter.wordCount = wordCount
|
bookChapter.wordCount = wordCount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,11 +35,6 @@ import kotlinx.coroutines.Dispatchers.Main
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import splitties.views.onClick
|
import splitties.views.onClick
|
||||||
import kotlin.collections.HashMap
|
|
||||||
import kotlin.collections.List
|
|
||||||
import kotlin.collections.forEachIndexed
|
|
||||||
import kotlin.collections.hashMapOf
|
|
||||||
import kotlin.collections.set
|
|
||||||
|
|
||||||
|
|
||||||
class SourceLoginDialog : BaseDialogFragment(R.layout.dialog_login, true) {
|
class SourceLoginDialog : BaseDialogFragment(R.layout.dialog_login, true) {
|
||||||
@@ -70,6 +65,7 @@ class SourceLoginDialog : BaseDialogFragment(R.layout.dialog_login, true) {
|
|||||||
it.textInputLayout.hint = rowUi.name
|
it.textInputLayout.hint = rowUi.name
|
||||||
it.editText.setText(loginInfo?.get(rowUi.name))
|
it.editText.setText(loginInfo?.get(rowUi.name))
|
||||||
}
|
}
|
||||||
|
|
||||||
RowUi.Type.password -> ItemSourceEditBinding.inflate(
|
RowUi.Type.password -> ItemSourceEditBinding.inflate(
|
||||||
layoutInflater,
|
layoutInflater,
|
||||||
binding.root,
|
binding.root,
|
||||||
@@ -82,37 +78,19 @@ class SourceLoginDialog : BaseDialogFragment(R.layout.dialog_login, true) {
|
|||||||
InputType.TYPE_TEXT_VARIATION_PASSWORD or InputType.TYPE_CLASS_TEXT
|
InputType.TYPE_TEXT_VARIATION_PASSWORD or InputType.TYPE_CLASS_TEXT
|
||||||
it.editText.setText(loginInfo?.get(rowUi.name))
|
it.editText.setText(loginInfo?.get(rowUi.name))
|
||||||
}
|
}
|
||||||
|
|
||||||
RowUi.Type.button -> ItemFilletTextBinding.inflate(
|
RowUi.Type.button -> ItemFilletTextBinding.inflate(
|
||||||
layoutInflater,
|
layoutInflater,
|
||||||
binding.root,
|
binding.root,
|
||||||
false
|
false
|
||||||
).let {
|
).let {
|
||||||
binding.flexbox.addView(it.root)
|
binding.flexbox.addView(it.root)
|
||||||
|
rowUi.style().apply(it.root)
|
||||||
it.root.id = index + 1000
|
it.root.id = index + 1000
|
||||||
it.textView.text = rowUi.name
|
it.textView.text = rowUi.name
|
||||||
it.textView.setPadding(16.dpToPx())
|
it.textView.setPadding(16.dpToPx())
|
||||||
it.root.onClick {
|
it.root.onClick {
|
||||||
Coroutine.async {
|
handleButtonClick(source, rowUi, loginUi)
|
||||||
if (rowUi.action.isAbsUrl()) {
|
|
||||||
context?.openUrl(rowUi.action!!)
|
|
||||||
} else {
|
|
||||||
// JavaScript
|
|
||||||
rowUi.action?.let { buttonFunctionJS ->
|
|
||||||
kotlin.runCatching {
|
|
||||||
source.getLoginJs()?.let { loginJS ->
|
|
||||||
source.evalJS("$loginJS\n$buttonFunctionJS") {
|
|
||||||
put("result", getLoginData(loginUi))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.onFailure { e ->
|
|
||||||
AppLog.put(
|
|
||||||
"LoginUI Button ${rowUi.name} JavaScript error",
|
|
||||||
e
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,12 +103,14 @@ class SourceLoginDialog : BaseDialogFragment(R.layout.dialog_login, true) {
|
|||||||
val loginData = getLoginData(loginUi)
|
val loginData = getLoginData(loginUi)
|
||||||
login(source, loginData)
|
login(source, loginData)
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_show_login_header -> alert {
|
R.id.menu_show_login_header -> alert {
|
||||||
setTitle(R.string.login_header)
|
setTitle(R.string.login_header)
|
||||||
source.getLoginHeader()?.let { loginHeader ->
|
source.getLoginHeader()?.let { loginHeader ->
|
||||||
setMessage(loginHeader)
|
setMessage(loginHeader)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_del_login_header -> source.removeLoginHeader()
|
R.id.menu_del_login_header -> source.removeLoginHeader()
|
||||||
R.id.menu_log -> showDialogFragment<AppLogDialog>()
|
R.id.menu_log -> showDialogFragment<AppLogDialog>()
|
||||||
}
|
}
|
||||||
@@ -138,6 +118,25 @@ class SourceLoginDialog : BaseDialogFragment(R.layout.dialog_login, true) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleButtonClick(source: BaseSource, rowUi: RowUi, loginUi: List<RowUi>) {
|
||||||
|
Coroutine.async {
|
||||||
|
if (rowUi.action.isAbsUrl()) {
|
||||||
|
context?.openUrl(rowUi.action!!)
|
||||||
|
} else if (rowUi.action != null) {
|
||||||
|
// JavaScript
|
||||||
|
val buttonFunctionJS = rowUi.action!!
|
||||||
|
val loginJS = source.getLoginJs() ?: return@async
|
||||||
|
kotlin.runCatching {
|
||||||
|
source.evalJS("$loginJS\n$buttonFunctionJS") {
|
||||||
|
put("result", getLoginData(loginUi))
|
||||||
|
}
|
||||||
|
}.onFailure { e ->
|
||||||
|
AppLog.put("LoginUI Button ${rowUi.name} JavaScript error", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getLoginData(loginUi: List<RowUi>?): HashMap<String, String> {
|
private fun getLoginData(loginUi: List<RowUi>?): HashMap<String, String> {
|
||||||
val loginData = hashMapOf<String, String>()
|
val loginData = hashMapOf<String, String>()
|
||||||
loginUi?.forEachIndexed { index, rowUi ->
|
loginUi?.forEachIndexed { index, rowUi ->
|
||||||
|
|||||||
@@ -91,14 +91,7 @@ class ExploreAdapter(context: Context, val callBack: CallBack) :
|
|||||||
val tv = getFlexboxChild(flexbox)
|
val tv = getFlexboxChild(flexbox)
|
||||||
flexbox.addView(tv)
|
flexbox.addView(tv)
|
||||||
tv.text = kind.title
|
tv.text = kind.title
|
||||||
val lp = tv.layoutParams as FlexboxLayout.LayoutParams
|
kind.style().apply(tv)
|
||||||
kind.style().let { style ->
|
|
||||||
lp.flexGrow = style.layout_flexGrow
|
|
||||||
lp.flexShrink = style.layout_flexShrink
|
|
||||||
lp.alignSelf = style.alignSelf()
|
|
||||||
lp.flexBasisPercent = style.layout_flexBasisPercent
|
|
||||||
lp.isWrapBefore = style.layout_wrapBefore
|
|
||||||
}
|
|
||||||
if (kind.url.isNullOrBlank()) {
|
if (kind.url.isNullOrBlank()) {
|
||||||
tv.setOnClickListener(null)
|
tv.setOnClickListener(null)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:orientation="vertical"
|
|
||||||
android:id="@+id/tv_chapter_item"
|
android:id="@+id/tv_chapter_item"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:orientation="vertical"
|
||||||
android:padding="12dp">
|
android:padding="12dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -14,20 +14,21 @@
|
|||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintBottom_toTopOf="@id/tv_word_count"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintRight_toLeftOf="@+id/iv_checked" />
|
app:layout_constraintRight_toLeftOf="@+id/iv_checked"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_word_count"
|
android:id="@+id/tv_word_count"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingEnd="18dp"
|
android:paddingEnd="18dp"
|
||||||
|
android:singleLine="true"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:singleLine="true"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/tv_chapter_name"
|
app:layout_constraintTop_toBottomOf="@+id/tv_chapter_name"
|
||||||
tools:ignore="RtlSymmetry" />
|
tools:ignore="RtlSymmetry" />
|
||||||
|
|
||||||
@@ -35,25 +36,25 @@
|
|||||||
android:id="@+id/tv_tag"
|
android:id="@+id/tv_tag"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:singleLine="true"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/tv_chapter_name"
|
|
||||||
app:layout_constraintLeft_toRightOf="@id/tv_word_count"
|
app:layout_constraintLeft_toRightOf="@id/tv_word_count"
|
||||||
app:layout_constraintRight_toLeftOf="@+id/iv_checked" />
|
app:layout_constraintRight_toLeftOf="@+id/iv_checked"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/tv_chapter_name" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/iv_checked"
|
android:id="@+id/iv_checked"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
|
android:contentDescription="@string/success"
|
||||||
android:padding="4dp"
|
android:padding="4dp"
|
||||||
android:src="@drawable/ic_check"
|
android:src="@drawable/ic_check"
|
||||||
android:visibility="invisible"
|
android:visibility="invisible"
|
||||||
android:contentDescription="@string/success"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:tint="@color/secondaryText"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintBottom_toBottomOf="parent" />
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:tint="@color/secondaryText" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
Reference in New Issue
Block a user