mirror of
https://github.com/gedoor/legado.git
synced 2025-01-07 03:06:58 +08:00
优化
This commit is contained in:
parent
f1eeec99e8
commit
612227502a
@ -19,6 +19,7 @@ import androidx.lifecycle.LifecycleRegistry
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.VMBaseActivity
|
||||
@ -49,6 +50,7 @@ import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
|
||||
import io.legado.app.ui.widget.recycler.ItemTouchCallback
|
||||
import io.legado.app.ui.widget.recycler.VerticalDivider
|
||||
import io.legado.app.utils.ACache
|
||||
import io.legado.app.utils.NetworkUtils
|
||||
import io.legado.app.utils.applyTint
|
||||
import io.legado.app.utils.cnCompare
|
||||
import io.legado.app.utils.dpToPx
|
||||
@ -103,6 +105,11 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
||||
override var sortAscending = true
|
||||
private set
|
||||
private var snackBar: Snackbar? = null
|
||||
private var showDuplicationSource = false
|
||||
private val bookSourceDecoration by lazy {
|
||||
BookSourceDecoration(adapter)
|
||||
}
|
||||
private val hostMap = hashMapOf<String, String>()
|
||||
private val qrResult = registerForActivityResult(QrCodeResult()) {
|
||||
it ?: return@registerForActivityResult
|
||||
showDialogFragment(ImportBookSourceDialog(it))
|
||||
@ -265,6 +272,11 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
||||
searchView.setQuery(getString(R.string.disabled_explore), true)
|
||||
}
|
||||
|
||||
R.id.menu_show_same_source -> {
|
||||
item.isChecked = !item.isChecked
|
||||
toggleDuplicationSourceView(item.isChecked)
|
||||
}
|
||||
|
||||
R.id.menu_help -> showHelp("SourceMBookHelp")
|
||||
}
|
||||
if (item.groupId == R.id.source_group) {
|
||||
@ -335,7 +347,12 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
||||
appDb.bookSourceDao.flowSearch(searchKey)
|
||||
}
|
||||
}.map { data ->
|
||||
if (sortAscending) {
|
||||
hostMap.clear()
|
||||
if (showDuplicationSource) {
|
||||
data.sortedWith(
|
||||
compareBy<BookSourcePart> { getSourceHost(it.bookSourceUrl) == "#" }
|
||||
.thenBy { getSourceHost(it.bookSourceUrl) })
|
||||
} else if (sortAscending) {
|
||||
when (sort) {
|
||||
BookSourceSort.Weight -> data.sortedBy { it.weight }
|
||||
BookSourceSort.Name -> data.sortedWith { o1, o2 ->
|
||||
@ -383,7 +400,8 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
||||
AppLog.put("书源界面更新书源出错", it)
|
||||
}.flowOn(IO).conflate().collect { data ->
|
||||
adapter.setItems(data, adapter.diffItemCallback, !Debug.isChecking)
|
||||
itemTouchCallback.isCanDrag = sort == BookSourceSort.Default
|
||||
itemTouchCallback.isCanDrag =
|
||||
sort == BookSourceSort.Default && !showDuplicationSource
|
||||
delay(500)
|
||||
}
|
||||
}
|
||||
@ -667,6 +685,21 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleDuplicationSourceView(enable: Boolean) {
|
||||
showDuplicationSource = enable
|
||||
adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
|
||||
override fun onChanged() {
|
||||
if (enable) {
|
||||
binding.recyclerView.addItemDecoration(bookSourceDecoration)
|
||||
} else {
|
||||
binding.recyclerView.removeItemDecoration(bookSourceDecoration)
|
||||
}
|
||||
adapter.unregisterAdapterDataObserver(this)
|
||||
}
|
||||
})
|
||||
upBookSource(searchView.query?.toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* 保持亮屏
|
||||
*/
|
||||
@ -686,6 +719,12 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
|
||||
.upCountView(adapter.selection.size, adapter.itemCount)
|
||||
}
|
||||
|
||||
override fun getSourceHost(origin: String): String {
|
||||
return hostMap.getOrPut(origin) {
|
||||
NetworkUtils.getSubDomainOrNull(origin) ?: "#"
|
||||
}
|
||||
}
|
||||
|
||||
override fun onQueryTextChange(newText: String?): Boolean {
|
||||
newText?.let {
|
||||
upBookSource(it)
|
||||
|
@ -272,6 +272,18 @@ class BookSourceAdapter(context: Context, val callBack: CallBack) :
|
||||
callBack.upCountView()
|
||||
}
|
||||
|
||||
fun getHeaderText(position: Int): String {
|
||||
val source = getItem(position)!!
|
||||
return callBack.getSourceHost(source.bookSourceUrl)
|
||||
}
|
||||
|
||||
fun isItemHeader(position: Int): Boolean {
|
||||
if (position == 0) return true
|
||||
val lastHost = getHeaderText(position - 1)
|
||||
val curHost = getHeaderText(position)
|
||||
return lastHost != curHost
|
||||
}
|
||||
|
||||
override fun swap(srcPosition: Int, targetPosition: Int): Boolean {
|
||||
val srcItem = getItem(srcPosition)
|
||||
val targetItem = getItem(targetPosition)
|
||||
@ -344,5 +356,6 @@ class BookSourceAdapter(context: Context, val callBack: CallBack) :
|
||||
fun enable(enable: Boolean, bookSource: BookSourcePart)
|
||||
fun enableExplore(enable: Boolean, bookSource: BookSourcePart)
|
||||
fun upCountView()
|
||||
fun getSourceHost(origin: String): String
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,69 @@
|
||||
package io.legado.app.ui.book.source.manage
|
||||
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Rect
|
||||
import android.text.TextPaint
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.legado.app.lib.theme.accentColor
|
||||
import io.legado.app.lib.theme.backgroundColor
|
||||
import io.legado.app.utils.dpToPx
|
||||
import io.legado.app.utils.spToPx
|
||||
import splitties.init.appCtx
|
||||
|
||||
class BookSourceDecoration(val adapter: BookSourceAdapter): RecyclerView.ItemDecoration() {
|
||||
|
||||
private val headerLeft = 16f.dpToPx()
|
||||
private val headerHeight = 32f.dpToPx()
|
||||
|
||||
private val headerPaint = Paint().apply {
|
||||
color = appCtx.backgroundColor
|
||||
}
|
||||
private val textPaint = TextPaint().apply {
|
||||
textSize = 16f.spToPx()
|
||||
color = appCtx.accentColor
|
||||
isAntiAlias = true
|
||||
}
|
||||
private val textRect = Rect()
|
||||
|
||||
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
|
||||
val count = parent.childCount
|
||||
for (i in 0 until count) {
|
||||
val view = parent.getChildAt(i)
|
||||
val position = parent.getChildLayoutPosition(view)
|
||||
val isHeader = adapter.isItemHeader(position)
|
||||
if (isHeader) {
|
||||
c.drawRect(
|
||||
0f,
|
||||
view.top - headerHeight,
|
||||
parent.width.toFloat(),
|
||||
view.top.toFloat(),
|
||||
headerPaint
|
||||
)
|
||||
val headerText = adapter.getHeaderText(position)
|
||||
textPaint.getTextBounds(headerText, 0, headerText.length, textRect)
|
||||
c.drawText(
|
||||
headerText,
|
||||
headerLeft,
|
||||
(view.top - headerHeight) + headerHeight / 2 + textRect.height() / 2,
|
||||
textPaint
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemOffsets(
|
||||
outRect: Rect,
|
||||
view: View,
|
||||
parent: RecyclerView,
|
||||
state: RecyclerView.State
|
||||
) {
|
||||
val position = parent.getChildLayoutPosition(view)
|
||||
val isHeader = adapter.isItemHeader(position)
|
||||
if (isHeader) {
|
||||
outRect.top = headerHeight.toInt()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -178,6 +178,19 @@ object NetworkUtils {
|
||||
}.getOrDefault(baseUrl)
|
||||
}
|
||||
|
||||
fun getSubDomainOrNull(url: String): String? {
|
||||
val baseUrl = getBaseUrl(url) ?: return null
|
||||
return kotlin.runCatching {
|
||||
val mURL = URL(baseUrl)
|
||||
val host: String = mURL.host
|
||||
//mURL.scheme https/http
|
||||
//判断是否为ip
|
||||
if (isIPAddress(host)) return host
|
||||
//PublicSuffixDatabase处理域名
|
||||
PublicSuffixDatabase.get().getEffectiveTldPlusOne(host) ?: host
|
||||
}.getOrDefault(null)
|
||||
}
|
||||
|
||||
fun getDomain(url: String): String {
|
||||
val baseUrl = getBaseUrl(url) ?: return url
|
||||
return kotlin.runCatching {
|
||||
@ -219,14 +232,17 @@ object NetworkUtils {
|
||||
* @return True if the input parameter is a valid IPv4 address.
|
||||
*/
|
||||
fun isIPv4Address(input: String?): Boolean {
|
||||
return input != null && Validator.isIpv4(input)
|
||||
return input != null && input.isNotEmpty()
|
||||
&& input[0] in '1'..'9'
|
||||
&& input.count { it == '.' } == 3
|
||||
&& Validator.isIpv4(input)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if valid IPV6 address.
|
||||
*/
|
||||
fun isIPv6Address(input: String?): Boolean {
|
||||
return input != null && Validator.isIpv6(input)
|
||||
return input != null && input.contains(":") && Validator.isIpv6(input)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,6 +132,12 @@
|
||||
android:title="@string/import_by_qr_code"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_show_same_source"
|
||||
android:checkable="true"
|
||||
android:title="@string/show_same_source"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_help"
|
||||
android:icon="@drawable/ic_help"
|
||||
|
@ -1174,4 +1174,5 @@
|
||||
<string name="read_aloud_read_phone_state_permission_rationale">阅读需要读取手机状态实现来电期间暂停朗读功能</string>
|
||||
<string name="read_aloud_by_media_button_title">耳机按键启动朗读</string>
|
||||
<string name="read_aloud_by_media_button_summary">通过耳机按键来启动朗读</string>
|
||||
<string name="show_same_source">显示重复书源</string>
|
||||
</resources>
|
||||
|
@ -1177,4 +1177,5 @@
|
||||
<string name="read_aloud_read_phone_state_permission_rationale">阅读需要读取手机状态实现来电期间暂停朗读功能</string>
|
||||
<string name="read_aloud_by_media_button_title">耳机按键启动朗读</string>
|
||||
<string name="read_aloud_by_media_button_summary">通过耳机按键来启动朗读</string>
|
||||
<string name="show_same_source">显示重复书源</string>
|
||||
</resources>
|
||||
|
@ -1177,4 +1177,5 @@
|
||||
<string name="read_aloud_read_phone_state_permission_rationale">阅读需要读取手机状态实现来电期间暂停朗读功能</string>
|
||||
<string name="read_aloud_by_media_button_title">耳机按键启动朗读</string>
|
||||
<string name="read_aloud_by_media_button_summary">通过耳机按键来启动朗读</string>
|
||||
<string name="show_same_source">显示重复书源</string>
|
||||
</resources>
|
||||
|
4
app/src/main/res/values-v24/strings.xml
Normal file
4
app/src/main/res/values-v24/strings.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="show_same_source">显示重复书源</string>
|
||||
</resources>
|
@ -1173,4 +1173,5 @@ Còn </string>
|
||||
<string name="read_aloud_read_phone_state_permission_rationale">阅读需要读取手机状态实现来电期间暂停朗读功能</string>
|
||||
<string name="read_aloud_by_media_button_title">耳机按键启动朗读</string>
|
||||
<string name="read_aloud_by_media_button_summary">通过耳机按键来启动朗读</string>
|
||||
<string name="show_same_source">显示重复书源</string>
|
||||
</resources>
|
||||
|
@ -1174,4 +1174,5 @@
|
||||
<string name="read_aloud_read_phone_state_permission_rationale">阅读需要读取手机状态实现来电期间暂停朗读功能</string>
|
||||
<string name="read_aloud_by_media_button_title">耳机按键启动朗读</string>
|
||||
<string name="read_aloud_by_media_button_summary">通过耳机按键来启动朗读</string>
|
||||
<string name="show_same_source">显示重复书源</string>
|
||||
</resources>
|
||||
|
@ -1176,4 +1176,5 @@
|
||||
<string name="read_aloud_read_phone_state_permission_rationale">阅读需要读取手机状态实现来电期间暂停朗读功能</string>
|
||||
<string name="read_aloud_by_media_button_title">耳机按键启动朗读</string>
|
||||
<string name="read_aloud_by_media_button_summary">通过耳机按键来启动朗读</string>
|
||||
<string name="show_same_source">显示重复书源</string>
|
||||
</resources>
|
||||
|
@ -1176,4 +1176,5 @@
|
||||
<string name="read_aloud_read_phone_state_permission_rationale">阅读需要读取手机状态实现来电期间暂停朗读功能</string>
|
||||
<string name="read_aloud_by_media_button_title">耳机按键启动朗读</string>
|
||||
<string name="read_aloud_by_media_button_summary">通过耳机按键来启动朗读</string>
|
||||
<string name="show_same_source">显示重复书源</string>
|
||||
</resources>
|
||||
|
@ -1177,4 +1177,5 @@
|
||||
<string name="read_aloud_read_phone_state_permission_rationale">阅读需要读取手机状态实现来电期间暂停朗读功能</string>
|
||||
<string name="read_aloud_by_media_button_title">耳机按键启动朗读</string>
|
||||
<string name="read_aloud_by_media_button_summary">通过耳机按键来启动朗读</string>
|
||||
<string name="show_same_source">显示重复书源</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user