From 4848a0f6d9743869f217b88212fc79dcce288448 Mon Sep 17 00:00:00 2001 From: Kr328 <39107975+Kr328@users.noreply.github.com> Date: Mon, 17 Feb 2020 00:43:31 +0800 Subject: [PATCH] fix auto proxy scroll --- .../com/github/kr328/clash/ProxiesActivity.kt | 14 ++++--- .../kr328/clash/adapter/ProxyAdapter.kt | 41 ++++++++++++------- .../github/kr328/clash/remote/ClashClient.kt | 2 +- .../github/kr328/clash/utils/ScrollBinding.kt | 18 +++++--- 4 files changed, 47 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/github/kr328/clash/ProxiesActivity.kt b/app/src/main/java/com/github/kr328/clash/ProxiesActivity.kt index 41cd780..527b639 100644 --- a/app/src/main/java/com/github/kr328/clash/ProxiesActivity.kt +++ b/app/src/main/java/com/github/kr328/clash/ProxiesActivity.kt @@ -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) } } \ No newline at end of file diff --git a/app/src/main/java/com/github/kr328/clash/adapter/ProxyAdapter.kt b/app/src/main/java/com/github/kr328/clash/adapter/ProxyAdapter.kt index a4ea2a9..935bd6d 100644 --- a/app/src/main/java/com/github/kr328/clash/adapter/ProxyAdapter.kt +++ b/app/src/main/java/com/github/kr328/clash/adapter/ProxyAdapter.kt @@ -22,7 +22,7 @@ class ProxyAdapter( private val context: Context, val onSelect: (String, String) -> Unit, val onUrlTest: (String) -> Unit -): RecyclerView.Adapter() { +) : RecyclerView.Adapter() { companion object { const val DEFAULT_SPAN_COUNT = 2 } @@ -66,7 +66,8 @@ class ProxyAdapter( private var rootMutex = Mutex() private var urlTesting: Set = emptySet() private var renderList = mutableListOf() - private val activeList: MutableMap = mutableMapOf() + private var activeList: MutableMap = mutableMapOf() + private var groupPosition: MutableMap = mutableMapOf() @ColorInt private val colorSurface: Int @ColorInt @@ -132,25 +133,34 @@ class ProxyAdapter( override fun getNewListSize(): Int = newRenderList.size }) + val groupCache: MutableMap = mutableMapOf() + val activeCache: MutableMap = 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 diff --git a/app/src/main/java/com/github/kr328/clash/remote/ClashClient.kt b/app/src/main/java/com/github/kr328/clash/remote/ClashClient.kt index 93ac660..cf3bc36 100644 --- a/app/src/main/java/com/github/kr328/clash/remote/ClashClient.kt +++ b/app/src/main/java/com/github/kr328/clash/remote/ClashClient.kt @@ -17,7 +17,7 @@ class ClashClient(private val service: IClashManager) { suspend fun startHealthCheck(group: String) = withContext(Dispatchers.IO) { CompletableDeferred().apply { - service.startHealthCheck(group, object: IStreamCallback.Stub() { + service.startHealthCheck(group, object : IStreamCallback.Stub() { override fun complete() { this@apply.complete(Unit) } diff --git a/app/src/main/java/com/github/kr328/clash/utils/ScrollBinding.kt b/app/src/main/java/com/github/kr328/clash/utils/ScrollBinding.kt index a239d6c..659581d 100644 --- a/app/src/main/java/com/github/kr328/clash/utils/ScrollBinding.kt +++ b/app/src/main/java/com/github/kr328/clash/utils/ScrollBinding.kt @@ -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(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