Ensure default subscription on removals

Add removeSubscriptionWithDefault in SettingsManager to remove a subscription and recreate a default subscription if none remain. Modify MmkvManager.decodeAllServerList to include servers from DEFAULT_SUBSCRIPTION_ID when it's not listed, and remove the defensive check in MmkvManager.removeSubscription so removals are delegated to SettingsManager. Update callers (SubEditActivity, SubscriptionsViewModel) to use SettingsManager.removeSubscriptionWithDefault, remove UI restrictions hiding the delete action for the default subscription, and simplify group-display logic in MainViewModel. These changes ensure a default subscription always exists and server lists include default servers when appropriate.
This commit is contained in:
2dust
2026-03-09 19:38:29 +08:00
parent 850096789b
commit 405cd7f55e
6 changed files with 42 additions and 19 deletions
@@ -114,9 +114,15 @@ object MmkvManager {
*/
fun decodeAllServerList(): MutableList<String> {
val allServers = mutableListOf<String>()
val subsList = decodeSubsList()
// Add servers from all subscriptions (including default subscription)
decodeSubsList().forEach { guid ->
// If DEFAULT_SUBSCRIPTION_ID is not in the subscriptions list, add its servers
if (!subsList.contains(DEFAULT_SUBSCRIPTION_ID)) {
allServers.addAll(decodeServerList(DEFAULT_SUBSCRIPTION_ID))
}
// Add servers from all subscriptions
subsList.forEach { guid ->
allServers.addAll(decodeServerList(guid))
}
@@ -381,11 +387,6 @@ object MmkvManager {
* @param subid The subscription ID.
*/
fun removeSubscription(subid: String) {
// Protect default subscription from being deleted
if (subid == DEFAULT_SUBSCRIPTION_ID) {
return
}
subStorage.remove(subid)
val subsList = decodeSubsList()
subsList.remove(subid)
@@ -25,6 +25,7 @@ import com.v2ray.ang.handler.MmkvManager.decodeServerConfig
import com.v2ray.ang.handler.MmkvManager.decodeSubsList
import com.v2ray.ang.handler.MmkvManager.decodeSubscription
import com.v2ray.ang.handler.MmkvManager.encodeSubscription
import com.v2ray.ang.handler.MmkvManager.removeSubscription
import com.v2ray.ang.util.JsonUtil
import com.v2ray.ang.util.Utils
import java.io.File
@@ -36,7 +37,7 @@ object SettingsManager {
fun initApp(context: Context) {
ensureDefaultSettings()
ensureDefaultSubscription()
//ensureDefaultSubscription()
initRoutingRulesets(context)
migrateServerListToSubscriptions()
migrateHysteria2PinSHA256()
@@ -240,6 +241,33 @@ object SettingsManager {
.firstOrNull { it.remarks == remarks }
}
/**
* Removes the subscription.
* If there are no remaining subscriptions,
* it creates a new default subscription to ensure that ungroup
**/
fun removeSubscriptionWithDefault(subid: String) {
// val subsList = decodeSubsList()
// if (subsList.size == 1 && subsList.first() == DEFAULT_SUBSCRIPTION_ID) {
// Log.i(ANG_PACKAGE,"Attempted to remove the only existing default subscription, operation ignored.")
// return
// }
// Remove the subscription
removeSubscription(subid)
// After removal, check if there are any subscriptions left. If not, create a default subscription.
val subsList2 = decodeSubsList()
if (subsList2.isNotEmpty()) {
return
}
val defaultSub = SubscriptionItem(
remarks = "Default",
)
encodeSubscription(DEFAULT_SUBSCRIPTION_ID, defaultSub)
}
/**
* Get the SOCKS port.
* @return The SOCKS port.
@@ -14,6 +14,7 @@ import com.v2ray.ang.extension.toast
import com.v2ray.ang.extension.toastSuccess
import com.v2ray.ang.handler.MmkvManager
import com.v2ray.ang.handler.SettingsChangeManager
import com.v2ray.ang.handler.SettingsManager
import com.v2ray.ang.util.Utils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -118,7 +119,7 @@ class SubEditActivity : BaseActivity() {
AlertDialog.Builder(this).setMessage(R.string.del_config_comfirm)
.setPositiveButton(android.R.string.ok) { _, _ ->
lifecycleScope.launch(Dispatchers.IO) {
MmkvManager.removeSubscription(editSubId)
SettingsManager.removeSubscriptionWithDefault(editSubId)
launch(Dispatchers.Main) {
finish()
}
@@ -130,7 +131,7 @@ class SubEditActivity : BaseActivity() {
.show()
} else {
lifecycleScope.launch(Dispatchers.IO) {
MmkvManager.removeSubscription(editSubId)
SettingsManager.removeSubscriptionWithDefault(editSubId)
launch(Dispatchers.Main) {
finish()
}
@@ -145,10 +146,6 @@ class SubEditActivity : BaseActivity() {
del_config = menu.findItem(R.id.del_config)
save_config = menu.findItem(R.id.save_config)
if (editSubId.isEmpty() || editSubId == AppConfig.DEFAULT_SUBSCRIPTION_ID) {
del_config?.isVisible = false
}
return super.onCreateOptionsMenu(menu)
}
@@ -39,7 +39,6 @@ class SubSettingRecyclerAdapter(
holder.itemSubSettingBinding.layoutRemove.setOnClickListener {
adapterListener?.onRemove(subId, position)
}
holder.itemSubSettingBinding.layoutRemove.isVisible = subId != AppConfig.DEFAULT_SUBSCRIPTION_ID
holder.itemSubSettingBinding.chkEnable.setOnCheckedChangeListener { it, isChecked ->
if (!it.isPressed) return@setOnCheckedChangeListener
@@ -252,9 +252,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
}
val groups = mutableListOf<GroupMapItem>()
if (subscriptions.size > 1
&& MmkvManager.decodeSettingsBool(AppConfig.PREF_GROUP_ALL_DISPLAY)
) {
if (MmkvManager.decodeSettingsBool(AppConfig.PREF_GROUP_ALL_DISPLAY)) {
groups.add(
GroupMapItem(
id = "",
@@ -21,7 +21,7 @@ class SubscriptionsViewModel : ViewModel() {
fun remove(subId: String): Boolean {
val changed = subscriptions.removeAll { it.guid == subId }
if (changed) {
MmkvManager.removeSubscription(subId)
SettingsManager.removeSubscriptionWithDefault(subId)
SettingsChangeManager.makeSetupGroupTab()
}
return changed