fix auto proxy scroll
This commit is contained in:
4 files changed
+47
-28
No files matched your search
@@ -10,6 +10,7 @@ import com.github.kr328.clash.adapter.ProxyAdapter
|
||||
import com.github.kr328.clash.adapter.ProxyChipAdapter
|
||||
import com.github.kr328.clash.core.model.General
|
||||
import com.github.kr328.clash.core.model.Proxy
|
||||
import com.github.kr328.clash.core.utils.Log
|
||||
import com.github.kr328.clash.preference.UiPreferences
|
||||
import com.github.kr328.clash.remote.withClash
|
||||
import com.github.kr328.clash.utils.PrefixMerger
|
||||
@@ -75,7 +76,7 @@ class ProxiesActivity : BaseActivity(), ScrollBinding.Callback {
|
||||
chipList.itemAnimator?.changeDuration = 0
|
||||
|
||||
launch {
|
||||
mainList.addOnScrollListener(object: RecyclerView.OnScrollListener(){
|
||||
mainList.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
scrollBinding.sendMasterScrolled()
|
||||
}
|
||||
@@ -318,24 +319,25 @@ class ProxiesActivity : BaseActivity(), ScrollBinding.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getCurrentMasterToken(): String {
|
||||
override fun getCurrentMasterToken(): String {
|
||||
return mainListAdapter.getCurrentGroup()
|
||||
}
|
||||
|
||||
override suspend fun onMasterTokenChanged(token: String) {
|
||||
override fun onMasterTokenChanged(token: String) {
|
||||
chipListAdapter.selected = token
|
||||
val position = chipListAdapter.chips.indexOf(token)
|
||||
|
||||
if (position < 0)
|
||||
return
|
||||
|
||||
chipList.scrollToPosition(position)
|
||||
chipList.smoothScrollToPosition(position)
|
||||
}
|
||||
|
||||
override suspend fun getMasterTokenPosition(token: String): Int {
|
||||
override fun getMasterTokenPosition(token: String): Int {
|
||||
return mainListAdapter.getGroupPosition(token)
|
||||
}
|
||||
|
||||
override suspend fun doMasterScroll(scroller: LinearSmoothScroller) {
|
||||
override fun doMasterScroll(scroller: LinearSmoothScroller) {
|
||||
mainListAdapter.layoutManager.startSmoothScroll(scroller)
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ class ProxyAdapter(
|
||||
private val context: Context,
|
||||
val onSelect: (String, String) -> Unit,
|
||||
val onUrlTest: (String) -> Unit
|
||||
): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
companion object {
|
||||
const val DEFAULT_SPAN_COUNT = 2
|
||||
}
|
||||
@@ -66,7 +66,8 @@ class ProxyAdapter(
|
||||
private var rootMutex = Mutex()
|
||||
private var urlTesting: Set<String> = emptySet()
|
||||
private var renderList = mutableListOf<RenderInfo>()
|
||||
private val activeList: MutableMap<String, Int> = mutableMapOf()
|
||||
private var activeList: MutableMap<String, Int> = mutableMapOf()
|
||||
private var groupPosition: MutableMap<String, Int> = mutableMapOf()
|
||||
@ColorInt
|
||||
private val colorSurface: Int
|
||||
@ColorInt
|
||||
@@ -132,25 +133,34 @@ class ProxyAdapter(
|
||||
override fun getNewListSize(): Int = newRenderList.size
|
||||
})
|
||||
|
||||
val groupCache: MutableMap<String, Int> = mutableMapOf()
|
||||
val activeCache: MutableMap<String, Int> = mutableMapOf()
|
||||
|
||||
newRenderList.forEachIndexed { index, it ->
|
||||
when ( it ) {
|
||||
is ProxyGroupRenderInfo ->
|
||||
groupCache[it.name] = index
|
||||
is ProxyRenderInfo -> {
|
||||
if ( it.info.active )
|
||||
activeCache[it.name] = index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
root = newList
|
||||
renderList = newRenderList.toMutableList()
|
||||
urlTesting = testing
|
||||
groupPosition = groupCache
|
||||
activeList = activeCache
|
||||
result.dispatchUpdatesTo(this@ProxyAdapter)
|
||||
}
|
||||
|
||||
rootMutex.unlock()
|
||||
}
|
||||
|
||||
suspend fun getGroupPosition(name: String): Int {
|
||||
return withContext(Dispatchers.Default) {
|
||||
renderList.mapIndexed { index, p ->
|
||||
if (p is ProxyGroupRenderInfo && p.name == name)
|
||||
index
|
||||
else
|
||||
-1
|
||||
}.singleOrNull() ?: -1
|
||||
}
|
||||
fun getGroupPosition(name: String): Int {
|
||||
return groupPosition[name] ?: -1
|
||||
}
|
||||
|
||||
fun getCurrentGroup(): String {
|
||||
@@ -183,6 +193,8 @@ class ProxyAdapter(
|
||||
is ProxyGroupHeader -> {
|
||||
val current = renderList[position] as ProxyGroupRenderInfo
|
||||
|
||||
groupPosition[current.name] = position
|
||||
|
||||
holder.name.text = current.info.name
|
||||
holder.urlTest.setOnClickListener {
|
||||
holder.urlTest.visibility = View.GONE
|
||||
@@ -191,11 +203,10 @@ class ProxyAdapter(
|
||||
onUrlTest(current.name)
|
||||
}
|
||||
|
||||
if ( urlTesting.contains(current.name) ) {
|
||||
if (urlTesting.contains(current.name)) {
|
||||
holder.urlTest.visibility = View.GONE
|
||||
holder.urlTestProgress.visibility = View.VISIBLE
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
holder.urlTest.visibility = View.VISIBLE
|
||||
holder.urlTestProgress.visibility = View.GONE
|
||||
}
|
||||
@@ -209,7 +220,7 @@ class ProxyAdapter(
|
||||
if (current.info.delay > 0)
|
||||
holder.delay.text = current.info.delay.toString()
|
||||
else
|
||||
holder.delay.text = ""
|
||||
holder.delay.text = if (current.info.selectable) "" else "N/A"
|
||||
|
||||
if (current.info.active) {
|
||||
activeList[current.group] = position
|
||||
|
||||
@@ -17,7 +17,7 @@ class ClashClient(private val service: IClashManager) {
|
||||
|
||||
suspend fun startHealthCheck(group: String) = withContext(Dispatchers.IO) {
|
||||
CompletableDeferred<Unit>().apply {
|
||||
service.startHealthCheck(group, object: IStreamCallback.Stub() {
|
||||
service.startHealthCheck(group, object : IStreamCallback.Stub() {
|
||||
override fun complete() {
|
||||
this@apply.complete(Unit)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.github.kr328.clash.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.util.DisplayMetrics
|
||||
import androidx.recyclerview.widget.LinearSmoothScroller
|
||||
import com.github.kr328.clash.core.utils.Log
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
@@ -10,10 +12,10 @@ class ScrollBinding(
|
||||
private val callback: Callback
|
||||
) {
|
||||
interface Callback {
|
||||
suspend fun getCurrentMasterToken(): String
|
||||
suspend fun onMasterTokenChanged(token: String)
|
||||
suspend fun getMasterTokenPosition(token: String): Int
|
||||
suspend fun doMasterScroll(scroller: LinearSmoothScroller)
|
||||
fun getCurrentMasterToken(): String
|
||||
fun onMasterTokenChanged(token: String)
|
||||
fun getMasterTokenPosition(token: String): Int
|
||||
fun doMasterScroll(scroller: LinearSmoothScroller)
|
||||
}
|
||||
|
||||
private val updateChannel = Channel<Unit>(Channel.CONFLATED)
|
||||
@@ -23,7 +25,7 @@ class ScrollBinding(
|
||||
updateChannel.offer(Unit)
|
||||
}
|
||||
|
||||
suspend fun scrollMaster(token: String) {
|
||||
fun scrollMaster(token: String) {
|
||||
val position = callback.getMasterTokenPosition(token)
|
||||
|
||||
if (position < 0)
|
||||
@@ -46,6 +48,10 @@ class ScrollBinding(
|
||||
preventSlaveScroll = true
|
||||
}
|
||||
|
||||
override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics?): Float {
|
||||
return super.calculateSpeedPerPixel(displayMetrics) * 0.8f
|
||||
}
|
||||
|
||||
init {
|
||||
targetPosition = position
|
||||
}
|
||||
@@ -61,7 +67,7 @@ class ScrollBinding(
|
||||
updateChannel.receive()
|
||||
|
||||
val currentToken = callback.getCurrentMasterToken()
|
||||
if (lastToken == currentToken)
|
||||
if (preventSlaveScroll || lastToken == currentToken)
|
||||
continue
|
||||
|
||||
lastToken = currentToken
|
||||
|
||||
Reference in new issue
Block a user