From b2e10fc60ba3243af279720a8d2fea6ff1242b5d Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Mon, 25 May 2026 09:55:30 +0800 Subject: [PATCH] Skip complex config types when deduplicating servers https://github.com/2dust/v2rayNG/issues/5675 --- .../main/java/com/v2ray/ang/extension/_Ext.kt | 21 ++++++++++++++++++- .../com/v2ray/ang/viewmodel/MainViewModel.kt | 13 ++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/extension/_Ext.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/extension/_Ext.kt index 909d3a3ba..ba0ede48e 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/extension/_Ext.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/extension/_Ext.kt @@ -8,6 +8,7 @@ import android.os.Build import android.os.Bundle import android.widget.Toast import com.v2ray.ang.AngApplication +import com.v2ray.ang.enums.EConfigType import es.dmoral.toasty.Toasty import java.io.Serializable import java.net.URI @@ -200,4 +201,22 @@ fun String.matchesPattern(regex: Regex?, keyword: String?, ignoreCase: Boolean = } return regex?.containsMatchIn(this) ?: this.contains(keyword, ignoreCase = ignoreCase) -} \ No newline at end of file +} + +/** + * Checks if the config type is a group type (PolicyGroup or ProxyChain). + * + * @return True if the config type is PolicyGroup or ProxyChain, false otherwise. + */ +fun EConfigType.isGroupType(): Boolean { + return this == EConfigType.POLICYGROUP || this == EConfigType.PROXYCHAIN +} + +/** + * Checks if the config type is a complex type (Custom, PolicyGroup, or ProxyChain). + * + * @return True if the config type is Custom, PolicyGroup, or ProxyChain, false otherwise. + */ +fun EConfigType.isComplexType(): Boolean { + return this == EConfigType.CUSTOM || this == EConfigType.POLICYGROUP || this == EConfigType.PROXYCHAIN +} diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/MainViewModel.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/MainViewModel.kt index 449fbdda5..87046e150 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/MainViewModel.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/MainViewModel.kt @@ -18,6 +18,7 @@ import com.v2ray.ang.dto.SubscriptionUpdateResult import com.v2ray.ang.dto.TestServiceMessage import com.v2ray.ang.dto.entities.ServersCache import com.v2ray.ang.dto.entities.SubscriptionCache +import com.v2ray.ang.extension.isComplexType import com.v2ray.ang.extension.matchesPattern import com.v2ray.ang.extension.toastError import com.v2ray.ang.extension.toastSuccess @@ -296,16 +297,28 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { /** * Removes duplicate servers. + * Excludes servers with complex types (Custom, PolicyGroup, or ProxyChain) from duplicate comparison. * @return The number of removed servers. */ fun removeDuplicateServer(): Int { val serversCacheCopy = serversCache.toList().toMutableList() val deleteServer = mutableListOf() + serversCacheCopy.forEachIndexed { index, sc -> val profile = sc.profile + // Skip if this profile has a complex config type + if (profile.configType.isComplexType()) { + return@forEachIndexed + } + serversCacheCopy.forEachIndexed { index2, sc2 -> if (index2 > index) { val profile2 = sc2.profile + // Skip if the second profile has a complex config type + if (profile2.configType.isComplexType()) { + return@forEachIndexed + } + if (profile == profile2 && !deleteServer.contains(sc2.guid)) { deleteServer.add(sc2.guid) }