proxy activity

This commit is contained in:
Kr328 committed 2019-11-28 23:49:11 +08:00
1 parent 8968469310
commit 7765d14588
16 files changed
+420 -136

No files matched your search

+1 -1
View File
@@ -44,7 +44,7 @@
android:exported="false"
android:screenOrientation="portrait"/>
<activity android:name=".ProxyActivity"
android:label="@string/clash_profiles"
android:label="@string/clash_proxy_manage"
android:exported="false"
android:screenOrientation="portrait"/>
</application>
@@ -1,28 +1,70 @@
package com.github.kr328.clash
import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.kr328.clash.adapter.ProxyGroupAdapter
import com.github.kr328.clash.core.model.Proxy
import com.github.kr328.clash.core.model.ProxyPacket
import com.github.kr328.clash.model.ListProxyGroup
import kotlinx.android.synthetic.main.activity_proxies.*
class ProxyActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_proxies)
val content = RecyclerView(this)
setSupportActionBar(activity_proxies_toolbar)
setContentView(content)
content.layoutManager = LinearLayoutManager(this)
content.adapter = ProxyGroupAdapter(this)
activity_proxies_list.also {
it.layoutManager = LinearLayoutManager(this)
it.adapter = ProxyGroupAdapter(this)
it.visibility = View.GONE
}
runClash { clash ->
val proxies = clash.queryAllProxies().proxies
val adapterProxies = proxies
.mapValues {
ListProxyGroup.ListProxy(it.value.name,
it.value.type.toString(),
it.value.delay)
}
val listData = proxies
.asSequence()
.filter {
when (it.value.type) {
ProxyPacket.Type.URL_TEST -> true
ProxyPacket.Type.FALLBACK -> true
ProxyPacket.Type.LOAD_BALANCE -> true
ProxyPacket.Type.SELECT -> true
else -> false
}
}
.sortedWith(compareBy(
{
it.value.type != ProxyPacket.Type.SELECT
}, {
it.value.name
}))
.map {
ListProxyGroup(
it.value.name,
it.value.type.toString(),
it.value.all.mapNotNull { hash ->
adapterProxies[hash]
},
adapterProxies[it.value.now]
)
}
.toList()
runOnUiThread {
(content.adapter!! as ProxyGroupAdapter).data = proxies.toList()
.sortedWith(compareBy({ it.second.type == Proxy.TYPE_SELECT }, { it.first }))
(activity_proxies_list.adapter!! as ProxyGroupAdapter).apply {
data = listData
notifyDataSetChanged()
}
activity_proxies_list.visibility = View.VISIBLE
}
}
}
@@ -0,0 +1,53 @@
package com.github.kr328.clash.adapter
import android.content.Context
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.github.kr328.clash.R
import com.github.kr328.clash.model.ListProxyGroup
import com.google.android.material.card.MaterialCardView
class ProxyAdapter(private val context: Context): RecyclerView.Adapter<ProxyAdapter.Holder>() {
var proxies: List<ListProxyGroup.ListProxy> = emptyList()
var now: ListProxyGroup.ListProxy? = null
class Holder(view: View) : RecyclerView.ViewHolder(view) {
val name: TextView = view.findViewById(R.id.adapter_proxy_name)
val type: TextView = view.findViewById(R.id.adapter_proxy_type)
val delay: TextView = view.findViewById(R.id.adapter_proxy_delay)
val card: MaterialCardView = view.findViewById(R.id.adapter_proxy_card)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
return Holder(LayoutInflater.from(context).inflate(R.layout.adapter_proxy, parent, false))
}
override fun getItemCount(): Int {
return proxies.size
}
override fun onBindViewHolder(holder: Holder, position: Int) {
val current = proxies[position]
if ( current === now ) {
holder.card.setCardBackgroundColor(context.getColor(R.color.colorAccent))
holder.name.setTextColor(Color.WHITE)
holder.type.setTextColor(Color.WHITE - 0x22222222)
holder.delay.setTextColor(Color.WHITE - 0x11111111)
}
else{
holder.card.setCardBackgroundColor(Color.WHITE)
holder.name.setTextColor(Color.BLACK)
holder.type.setTextColor(Color.LTGRAY)
holder.delay.setTextColor(Color.DKGRAY)
}
holder.name.text = current.name
holder.type.text = current.type
holder.delay.text = if ( current.delay > 0 ) current.delay.toString() else ""
}
}
@@ -5,21 +5,28 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.kr328.clash.R
import com.github.kr328.clash.core.model.Proxy
import com.github.kr328.clash.model.ListProxyGroup
class ProxyGroupAdapter(private val context: Context) : RecyclerView.Adapter<ProxyGroupAdapter.Holder>() {
var data: List<Pair<String, Proxy>> = emptyList()
var data: List<ListProxyGroup> = emptyList()
class Holder(view: View) : RecyclerView.ViewHolder(view) {
val name = view.findViewById<TextView>(R.id.adapter_proxy_group_name)
val list = view.findViewById<RecyclerView>(R.id.adapter_proxy_group_list)
val name: TextView = view.findViewById(R.id.adapter_proxy_group_name)
val list: RecyclerView = view.findViewById(R.id.adapter_proxy_group_list)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
return Holder(LayoutInflater.from(context)
.inflate(R.layout.adapter_proxy_group, parent, false))
.inflate(R.layout.adapter_proxy_group, parent, false)).apply {
list.layoutManager = object: GridLayoutManager(context, 2) {
override fun canScrollHorizontally(): Boolean = false
override fun canScrollVertically(): Boolean = false
}
list.adapter = ProxyAdapter(context)
}
}
override fun getItemCount(): Int {
@@ -29,6 +36,11 @@ class ProxyGroupAdapter(private val context: Context) : RecyclerView.Adapter<Pro
override fun onBindViewHolder(holder: Holder, position: Int) {
val current = data[position]
holder.name.text = current.first
holder.name.text = current.name
(holder.list.adapter as ProxyAdapter).apply {
proxies = current.proxies
now = current.now
}
}
}
@@ -0,0 +1,5 @@
package com.github.kr328.clash.model
data class ListProxyGroup(val name: String, val type: String, val proxies: List<ListProxy>, var now: ListProxy?) {
data class ListProxy(val name: String, val type: String, val delay: Long)
}
+9
View File
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M16.59,8.59L12,13.17 7.41,8.59 6,10l6,6 6,-6z"/>
</vector>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/activity_proxies_toolbar"
android:layout_width="match_parent"
android:layout_height="60dp" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/activity_proxies_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
+29 -8
View File
@@ -1,29 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.cardview.widget.CardView
<com.google.android.material.card.MaterialCardView
android:id="@+id/adapter_proxy_card"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
app:cardUseCompatPadding="true"
app:cardElevation="2dp"
app:cardCornerRadius="5dp">
<RelativeLayout
android:padding="18dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:padding="15dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/adapter_proxy_name"
android:textColor="@android:color/black"
android:text="@string/app_name"
android:maxLines="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/adapter_proxy_type"
android:layout_below="@id/adapter_proxy_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"/>
android:textSize="12sp"
android:text="@string/app_name"
android:maxLines="1"/>
<TextView
android:layout_alignParentEnd="true"
android:gravity="end"
android:textSize="12sp"
android:id="@+id/adapter_proxy_delay"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/adapter_proxy_name"
android:layout_marginStart="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="30dp"/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
</com.google.android.material.card.MaterialCardView>
</FrameLayout>
@@ -1,18 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:paddingTop="12dp">
<TextView
android:padding="5dp"
android:layout_marginStart="2dp"
android:textColor="@color/colorAccent"
android:text="@string/app_name"
android:id="@+id/adapter_proxy_group_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<View
android:layout_alignParentEnd="true"
android:layout_width="16dp"
android:layout_height="16dp"
android:background="@drawable/ic_expand"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/adapter_proxy_group_list"
android:layout_below="@id/adapter_proxy_group_name"
+2
View File
@@ -41,4 +41,6 @@
<string name="clash_import_file_empty_name">Empty Name</string>
<string name="clash_import_file_empty_path">Empty Path</string>
<string name="clash_import_file_invalid">Invalid Config: %s</string>
<string name="clash_proxy_group_title">%s - %s</string>
</resources>
@@ -8,8 +8,7 @@ import com.github.kr328.clash.core.event.LogEvent
import com.github.kr328.clash.core.event.ProcessEvent
import com.github.kr328.clash.core.event.ProxyChangedEvent
import com.github.kr328.clash.core.event.TrafficEvent
import com.github.kr328.clash.core.model.Proxy
import com.github.kr328.clash.core.model.ProxyPacket
import com.github.kr328.clash.core.model.RawProxyPacket
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import org.json.JSONObject
@@ -57,14 +56,14 @@ class Clash(
}
}
fun queryProxies(): ProxyPacket {
fun queryProxies(): RawProxyPacket {
return runControl(COMMAND_QUERY_PROXIES) { _, input, _ ->
val data = input.readString()
Log.d(TAG, data)
Json(JsonConfiguration.Stable.copy(strictMode = false))
.parse(ProxyPacket.serializer(), data)
.parse(RawProxyPacket.serializer(), data)
}
}
@@ -1,30 +0,0 @@
package com.github.kr328.clash.core.model
import android.os.Parcel
import android.os.Parcelable
import com.github.kr328.clash.core.serialization.Parcels
import kotlinx.serialization.Serializable
@Serializable
data class Proxy(val type: String,
val all: List<String> = emptyList(),
val now: String = "",
val history: List<History> = emptyList()) {
@Serializable
data class History(val delay: Long)
companion object {
const val TYPE_SELECT = "Selector"
const val TYPE_URL_TEST = "URLTest"
const val TYPE_DIRECT = "Direct"
const val TYPE_FALLBACK = "Fallback"
const val TYPE_REJECT = "Reject"
const val TYPE_SHADOWSOCKS = "Shadowsocks"
const val TYPE_SNELL = "Snell"
const val TYPE_SOCKS5 = "Socks5"
const val TYPE_HTTP = "Http"
const val TYPE_VMESS = "Vmess"
const val TYPE_LOAD_BALANCE = "LoadBalance"
const val TYPE_UNKNOWN = "Unknown"
}
}
@@ -6,7 +6,99 @@ import com.github.kr328.clash.core.serialization.Parcels
import kotlinx.serialization.Serializable
@Serializable
data class ProxyPacket(val proxies: Map<String, Proxy>) : Parcelable {
data class ProxyPacket(val proxies: Map<Int, Proxy>): Parcelable {
@Serializable
data class Proxy(val name: String, val type: Type, val now: Int, val all: Set<Int>, val delay: Long)
enum class Type {
SELECT,
URL_TEST,
FALLBACK,
DIRECT,
REJECT,
SHADOWSOCKS,
SNELL,
SOCKS5,
HTTP,
VMESS,
LOAD_BALANCE,
UNKNOWN;
override fun toString(): String {
return when ( this ) {
SELECT -> "Select"
URL_TEST -> "UrlTest"
FALLBACK -> "Fallback"
DIRECT -> "Direct"
REJECT -> "Reject"
SHADOWSOCKS -> "Shadowsocks"
SNELL -> "Snell"
SOCKS5 -> "Socks5"
HTTP -> "HTTP"
VMESS -> "Vmess"
LOAD_BALANCE -> "LoadBalance"
UNKNOWN -> "Unknown"
}
}
}
companion object {
private const val TYPE_SELECT = "Selector"
private const val TYPE_URL_TEST = "URLTest"
private const val TYPE_FALLBACK = "Fallback"
private const val TYPE_DIRECT = "Direct"
private const val TYPE_REJECT = "Reject"
private const val TYPE_SHADOWSOCKS = "Shadowsocks"
private const val TYPE_SNELL = "Snell"
private const val TYPE_SOCKS5 = "Socks5"
private const val TYPE_HTTP = "Http"
private const val TYPE_VMESS = "Vmess"
private const val TYPE_LOAD_BALANCE = "LoadBalance"
private const val TYPE_UNKNOWN = "Unknown"
fun fromRawProxy(rawProxy: RawProxyPacket): ProxyPacket {
val hashed = rawProxy.proxies
.map { it.key to (it.key.hashCode() to it.value) }.toMap()
val proxies = hashed.map { entry ->
val type = when ( entry.value.second.type ) {
TYPE_SELECT -> Type.SELECT
TYPE_URL_TEST -> Type.URL_TEST
TYPE_FALLBACK -> Type.FALLBACK
TYPE_DIRECT -> Type.DIRECT
TYPE_REJECT -> Type.REJECT
TYPE_SHADOWSOCKS -> Type.SHADOWSOCKS
TYPE_SNELL -> Type.SNELL
TYPE_SOCKS5 -> Type.SOCKS5
TYPE_HTTP -> Type.HTTP
TYPE_VMESS -> Type.VMESS
TYPE_LOAD_BALANCE -> Type.LOAD_BALANCE
TYPE_UNKNOWN -> Type.UNKNOWN
else -> Type.UNKNOWN
}
val now = hashed[entry.value.second.now]?.first ?: 0
val all = entry.value.second.all.mapNotNull { hashed[it]?.first }.toSet()
val delay = entry.value.second.history.firstOrNull()?.delay ?: 0
entry.value.first to Proxy(entry.key, type, now, all, delay)
}
return ProxyPacket(proxies.toMap())
}
@JvmField
val CREATOR = object: Parcelable.Creator<ProxyPacket> {
override fun createFromParcel(parcel: Parcel): ProxyPacket {
return Parcels.load(serializer(), parcel)
}
override fun newArray(size: Int): Array<ProxyPacket?> {
return arrayOfNulls(size)
}
}
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
Parcels.dump(serializer(), this, parcel)
}
@@ -14,15 +106,4 @@ data class ProxyPacket(val proxies: Map<String, Proxy>) : Parcelable {
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<ProxyPacket> {
override fun createFromParcel(parcel: Parcel): ProxyPacket {
return Parcels.load(serializer(), parcel)
}
override fun newArray(size: Int): Array<ProxyPacket?> {
return arrayOfNulls(size)
}
}
}
@@ -0,0 +1,15 @@
package com.github.kr328.clash.core.model
import kotlinx.serialization.Serializable
@Serializable
data class RawProxyPacket(val proxies: Map<String, RawProxy>) {
@Serializable
data class RawProxy(val type: String,
val all: List<String> = emptyList(),
val now: String = "",
val history: List<History> = emptyList()) {
@Serializable
data class History(val delay: Long)
}
}
@@ -18,14 +18,85 @@ object Parcels : AbstractSerialFormat(EmptyModule) {
}
private class ParcelsEncoder(private val parcel: Parcel) :
ElementValueEncoder() {
override fun encodeValue(value: Any) {
parcel.writeValue(value)
Encoder, CompositeEncoder {
override val context: SerialModule
get() = EmptyModule
override fun beginCollection(
desc: SerialDescriptor,
collectionSize: Int,
vararg typeParams: KSerializer<*>
): CompositeEncoder {
encodeInt(collectionSize)
return super.beginCollection(desc, collectionSize, *typeParams)
}
override fun encodeNull() {
parcel.writeValue(null)
}
override fun encodeBooleanElement(desc: SerialDescriptor, index: Int, value: Boolean) =
encodeBoolean(value)
override fun encodeByteElement(desc: SerialDescriptor, index: Int, value: Byte) =
encodeByte(value)
override fun encodeCharElement(desc: SerialDescriptor, index: Int, value: Char) =
encodeChar(value)
override fun encodeDoubleElement(desc: SerialDescriptor, index: Int, value: Double) =
encodeDouble(value)
override fun encodeFloatElement(desc: SerialDescriptor, index: Int, value: Float) =
encodeFloat(value)
override fun encodeIntElement(desc: SerialDescriptor, index: Int, value: Int) =
encodeInt(value)
override fun encodeLongElement(desc: SerialDescriptor, index: Int, value: Long) =
encodeLong(value)
override fun encodeShortElement(desc: SerialDescriptor, index: Int, value: Short) =
encodeShort(value)
override fun encodeStringElement(desc: SerialDescriptor, index: Int, value: String) =
encodeString(value)
override fun encodeUnitElement(desc: SerialDescriptor, index: Int) =
encodeUnit()
override fun encodeNonSerializableElement(desc: SerialDescriptor, index: Int, value: Any) =
throw IllegalArgumentException("Unsupported")
override fun <T : Any> encodeNullableSerializableElement(
desc: SerialDescriptor,
index: Int,
serializer: SerializationStrategy<T>,
value: T?
) = encodeNullableSerializableValue(serializer, value)
override fun <T> encodeSerializableElement(
desc: SerialDescriptor,
index: Int,
serializer: SerializationStrategy<T>,
value: T
) = encodeSerializableValue(serializer, value)
override fun beginStructure(
desc: SerialDescriptor,
vararg typeParams: KSerializer<*>
): CompositeEncoder = this
override fun encodeBoolean(value: Boolean) =
parcel.writeByte(if ( value ) 1 else 0)
override fun encodeByte(value: Byte) =
parcel.writeByte(value)
override fun encodeChar(value: Char) =
parcel.writeInt(value.toInt())
override fun encodeDouble(value: Double) =
parcel.writeDouble(value)
override fun encodeEnum(enumDescription: SerialDescriptor, ordinal: Int) =
parcel.writeInt(ordinal)
override fun encodeFloat(value: Float) =
parcel.writeFloat(value)
override fun encodeInt(value: Int) =
parcel.writeInt(value)
override fun encodeLong(value: Long) =
parcel.writeLong(value)
override fun encodeNotNullMark() =
encodeBoolean(true)
override fun encodeNull() =
encodeBoolean(false)
override fun encodeShort(value: Short) =
parcel.writeInt(value.toInt())
override fun encodeString(value: String) =
parcel.writeString(value)
override fun encodeUnit() {}
}
class ParcelsDecoder(private val parcel: Parcel) : Decoder, CompositeDecoder {
@@ -36,6 +107,8 @@ object Parcels : AbstractSerialFormat(EmptyModule) {
override fun decodeElementIndex(desc: SerialDescriptor) =
CompositeDecoder.READ_ALL
override fun decodeCollectionSize(desc: SerialDescriptor) =
decodeInt()
override fun decodeBooleanElement(desc: SerialDescriptor, index: Int) =
decodeBoolean()
@@ -88,57 +161,31 @@ object Parcels : AbstractSerialFormat(EmptyModule) {
vararg typeParams: KSerializer<*>
): CompositeDecoder = this
override fun decodeBoolean(): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun decodeByte(): Byte {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun decodeChar(): Char {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun decodeDouble(): Double {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun decodeEnum(enumDescription: SerialDescriptor): Int {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun decodeFloat(): Float {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun decodeInt(): Int {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun decodeLong(): Long {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun decodeNotNullMark(): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun decodeNull(): Nothing? {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun decodeShort(): Short {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun decodeString(): String {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun decodeUnit() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun decodeBoolean() =
parcel.readByte() != 0.toByte()
override fun decodeByte() =
parcel.readByte()
override fun decodeChar() =
parcel.readInt().toChar()
override fun decodeDouble() =
parcel.readDouble()
override fun decodeEnum(enumDescription: SerialDescriptor) =
parcel.readInt()
override fun decodeFloat() =
parcel.readFloat()
override fun decodeInt() =
parcel.readInt()
override fun decodeLong() =
parcel.readLong()
override fun decodeNotNullMark() =
decodeBoolean()
override fun decodeNull() =
null
override fun decodeShort() =
parcel.readInt().toShort()
override fun decodeString() =
parcel.readString() ?: throw NullPointerException("String null")
override fun decodeUnit() {}
}
}
@@ -12,9 +12,9 @@ import android.os.ParcelFileDescriptor
import com.github.kr328.clash.core.Clash
import com.github.kr328.clash.core.event.*
import com.github.kr328.clash.core.model.ProxyPacket
import com.github.kr328.clash.core.model.RawProxyPacket
import com.github.kr328.clash.core.utils.Log
import com.github.kr328.clash.service.data.ClashDatabase
import java.io.EOFException
import java.io.File
import java.io.IOException
import java.util.concurrent.Executors
@@ -40,14 +40,11 @@ class ClashService : Service(), IClashEventObserver, ClashEventService.Master,
override fun queryAllProxies(): ProxyPacket {
return try {
ProxyPacket(clash.queryProxies().proxies.mapValues {
it.value.copy(history = it.value.history.take(1))
})
ProxyPacket.fromRawProxy(clash.queryProxies())
} catch (e: Exception) {
this@ClashService.eventService.preformErrorEvent(
ErrorEvent(ErrorEvent.Type.QUERY_PROXY_FAILURE, e.toString())
)
ProxyPacket(emptyMap())
}
}