diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SubSettingActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SubSettingActivity.kt index 1230a18c..ce7bcf5d 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SubSettingActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SubSettingActivity.kt @@ -5,26 +5,27 @@ import android.content.Intent import android.os.Bundle import android.view.Menu import android.view.MenuItem +import androidx.activity.viewModels import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import com.v2ray.ang.R import com.v2ray.ang.databinding.ActivitySubSettingBinding -import com.v2ray.ang.dto.SubscriptionItem import com.v2ray.ang.extension.toastError import com.v2ray.ang.extension.toastSuccess import com.v2ray.ang.handler.AngConfigManager -import com.v2ray.ang.handler.MmkvManager import com.v2ray.ang.helper.SimpleItemTouchHelperCallback +import com.v2ray.ang.viewmodel.SubscriptionsViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import kotlin.getValue class SubSettingActivity : BaseActivity() { private val binding by lazy { ActivitySubSettingBinding.inflate(layoutInflater) } - var subscriptions: List> = listOf() - private val adapter by lazy { SubSettingRecyclerAdapter(this) } + private val viewModel: SubscriptionsViewModel by viewModels() + private lateinit var adapter: SubSettingRecyclerAdapter private var mItemTouchHelper: ItemTouchHelper? = null override fun onCreate(savedInstanceState: Bundle?) { @@ -32,6 +33,8 @@ class SubSettingActivity : BaseActivity() { //setContentView(binding.root) setContentViewWithToolbar(binding.root, showHomeAsUp = true, title = getString(R.string.title_sub_setting)) + adapter = SubSettingRecyclerAdapter(this, viewModel) + binding.recyclerView.setHasFixedSize(true) binding.recyclerView.layoutManager = LinearLayoutManager(this) addCustomDividerToRecyclerView(binding.recyclerView, this, R.drawable.custom_divider) @@ -83,7 +86,7 @@ class SubSettingActivity : BaseActivity() { @SuppressLint("NotifyDataSetChanged") fun refreshData() { - subscriptions = MmkvManager.decodeSubscriptions() + viewModel.reload() adapter.notifyDataSetChanged() } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SubSettingRecyclerAdapter.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SubSettingRecyclerAdapter.kt index b4fcd62a..562fd8a7 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SubSettingRecyclerAdapter.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SubSettingRecyclerAdapter.kt @@ -8,7 +8,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.appcompat.app.AlertDialog -import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.RecyclerView import com.v2ray.ang.AppConfig import com.v2ray.ang.R @@ -16,16 +15,16 @@ import com.v2ray.ang.databinding.ItemQrcodeBinding import com.v2ray.ang.databinding.ItemRecyclerSubSettingBinding import com.v2ray.ang.extension.toast import com.v2ray.ang.handler.MmkvManager -import com.v2ray.ang.handler.SettingsChangeManager -import com.v2ray.ang.handler.SettingsManager import com.v2ray.ang.helper.ItemTouchHelperAdapter import com.v2ray.ang.helper.ItemTouchHelperViewHolder import com.v2ray.ang.util.QRCodeDecoder import com.v2ray.ang.util.Utils -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch +import com.v2ray.ang.viewmodel.SubscriptionsViewModel -class SubSettingRecyclerAdapter(val activity: SubSettingActivity) : RecyclerView.Adapter(), ItemTouchHelperAdapter { +class SubSettingRecyclerAdapter( + val activity: SubSettingActivity, + private val viewModel: SubscriptionsViewModel +) : RecyclerView.Adapter(), ItemTouchHelperAdapter { private var mActivity: SubSettingActivity = activity @@ -33,11 +32,12 @@ class SubSettingRecyclerAdapter(val activity: SubSettingActivity) : RecyclerView mActivity.resources.getStringArray(R.array.share_sub_method) } - override fun getItemCount() = mActivity.subscriptions.size + override fun getItemCount() = viewModel.getAll().size override fun onBindViewHolder(holder: MainViewHolder, position: Int) { - val subId = mActivity.subscriptions[position].first - val subItem = mActivity.subscriptions[position].second + val subscriptions = viewModel.getAll() + val subId = subscriptions[position].first + val subItem = subscriptions[position].second holder.itemSubSettingBinding.tvName.text = subItem.remarks holder.itemSubSettingBinding.tvUrl.text = subItem.url holder.itemSubSettingBinding.chkEnable.isChecked = subItem.enabled @@ -58,8 +58,7 @@ class SubSettingRecyclerAdapter(val activity: SubSettingActivity) : RecyclerView holder.itemSubSettingBinding.chkEnable.setOnCheckedChangeListener { it, isChecked -> if (!it.isPressed) return@setOnCheckedChangeListener subItem.enabled = isChecked - MmkvManager.encodeSubscription(subId, subItem) - + viewModel.update(subId, subItem) } if (TextUtils.isEmpty(subItem.url)) { @@ -119,15 +118,10 @@ class SubSettingRecyclerAdapter(val activity: SubSettingActivity) : RecyclerView } private fun removeSubscriptionSub(subId: String, position: Int) { - mActivity.lifecycleScope.launch(Dispatchers.IO) { - MmkvManager.removeSubscription(subId) - launch(Dispatchers.Main) { - notifyItemRemoved(position) - notifyItemRangeChanged(position, mActivity.subscriptions.size) - mActivity.refreshData() - SettingsChangeManager.makeSetupGroupTab() - } - } + viewModel.remove(subId) + notifyItemRemoved(position) + notifyItemRangeChanged(position, viewModel.getAll().size) + mActivity.refreshData() } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainViewHolder { @@ -154,14 +148,13 @@ class SubSettingRecyclerAdapter(val activity: SubSettingActivity) : RecyclerView } override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean { - SettingsManager.swapSubscriptions(fromPosition, toPosition) + viewModel.swap(fromPosition, toPosition) notifyItemMoved(fromPosition, toPosition) return true } override fun onItemMoveCompleted() { mActivity.refreshData() - SettingsChangeManager.makeSetupGroupTab() } override fun onItemDismiss(position: Int) { diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SubscriptionsViewModel.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SubscriptionsViewModel.kt new file mode 100644 index 00000000..41fe00da --- /dev/null +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SubscriptionsViewModel.kt @@ -0,0 +1,46 @@ +package com.v2ray.ang.viewmodel + +import androidx.lifecycle.ViewModel +import com.v2ray.ang.dto.SubscriptionItem +import com.v2ray.ang.handler.MmkvManager +import com.v2ray.ang.handler.SettingsChangeManager +import com.v2ray.ang.handler.SettingsManager + +class SubscriptionsViewModel : ViewModel() { + private val subscriptions: MutableList> = + MmkvManager.decodeSubscriptions().toMutableList() + + fun getAll(): List> = subscriptions.toList() + + fun reload() { + subscriptions.clear() + subscriptions.addAll(MmkvManager.decodeSubscriptions()) + } + + fun remove(subId: String): Boolean { + val changed = subscriptions.removeAll { it.first == subId } + if (changed) { + MmkvManager.removeSubscription(subId) + SettingsChangeManager.makeSetupGroupTab() + } + return changed + } + + fun update(subId: String, item: SubscriptionItem) { + val idx = subscriptions.indexOfFirst { it.first == subId } + if (idx >= 0) { + subscriptions[idx] = Pair(subId, item) + MmkvManager.encodeSubscription(subId, item) + } + } + + fun swap(fromPosition: Int, toPosition: Int) { + if (fromPosition in subscriptions.indices && toPosition in subscriptions.indices) { + val item = subscriptions.removeAt(fromPosition) + subscriptions.add(toPosition, item) + SettingsManager.swapSubscriptions(fromPosition, toPosition) + SettingsChangeManager.makeSetupGroupTab() + } + } +} +