diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BaseAdapterListener.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BaseAdapterListener.kt new file mode 100644 index 00000000..daf83b28 --- /dev/null +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BaseAdapterListener.kt @@ -0,0 +1,31 @@ +package com.v2ray.ang.ui + +/** + * A common Adapter -> host callback interface that includes common actions: edit, remove and refresh. + * Extend this interface or define more specific interfaces for different adapters as needed. + */ +interface BaseAdapterListener { + /** + * Request the host to edit the specified item. + * @param guid Unique identifier (GUID) of the item + */ + fun onEdit(guid: String) + + /** + * Request the host to remove the specified item. Position is provided for optional animation or validation. + * @param guid Unique identifier (GUID) of the item + * @param position Current position in the adapter (optional; host should validate it) + */ + fun onRemove(guid: String, position: Int) + + /** + * Request the host to share the specified URL. + * @param url The URL to be shared + */ + fun onShare(url: String) + + /** + * Request the host to refresh data (for example, reload from the ViewModel or call notifyDataSetChanged). + */ + fun onRefreshData() +} 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 cdf96386..828e5d5e 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 @@ -3,18 +3,27 @@ package com.v2ray.ang.ui import android.annotation.SuppressLint import android.content.Intent import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater import android.view.Menu import android.view.MenuItem import androidx.activity.viewModels +import androidx.appcompat.app.AlertDialog import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager +import com.v2ray.ang.AppConfig import com.v2ray.ang.R import com.v2ray.ang.databinding.ActivitySubSettingBinding +import com.v2ray.ang.databinding.ItemQrcodeBinding +import com.v2ray.ang.extension.toast 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.util.QRCodeDecoder +import com.v2ray.ang.util.Utils import com.v2ray.ang.viewmodel.SubscriptionsViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay @@ -22,17 +31,21 @@ import kotlinx.coroutines.launch class SubSettingActivity : BaseActivity() { private val binding by lazy { ActivitySubSettingBinding.inflate(layoutInflater) } - + private val ownerActivity: SubSettingActivity + get() = this private val viewModel: SubscriptionsViewModel by viewModels() private lateinit var adapter: SubSettingRecyclerAdapter private var mItemTouchHelper: ItemTouchHelper? = null + private val share_method: Array by lazy { + resources.getStringArray(R.array.share_sub_method) + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) //setContentView(binding.root) setContentViewWithToolbar(binding.root, showHomeAsUp = true, title = getString(R.string.title_sub_setting)) - adapter = SubSettingRecyclerAdapter(this, viewModel) + adapter = SubSettingRecyclerAdapter(viewModel, ActivityAdapterListener()) binding.recyclerView.setHasFixedSize(true) binding.recyclerView.layoutManager = LinearLayoutManager(this) @@ -88,4 +101,62 @@ class SubSettingActivity : BaseActivity() { viewModel.reload() adapter.notifyDataSetChanged() } + + private inner class ActivityAdapterListener : BaseAdapterListener { + override fun onEdit(guid: String) { + startActivity( + Intent(ownerActivity, SubEditActivity::class.java) + .putExtra("subId", guid) + ) + } + + override fun onRemove(guid: String, position: Int) { + if (MmkvManager.decodeSettingsBool(AppConfig.PREF_CONFIRM_REMOVE)) { + AlertDialog.Builder(ownerActivity) + .setMessage(R.string.del_config_comfirm) + .setPositiveButton(android.R.string.ok) { _, _ -> + viewModel.remove(guid) + refreshData() + } + .setNegativeButton(android.R.string.cancel, null) + .show() + } else { + viewModel.remove(guid) + refreshData() + } + } + + override fun onShare(url: String) { + AlertDialog.Builder(ownerActivity) + .setItems(share_method.asList().toTypedArray()) { _, i -> + try { + when (i) { + 0 -> { + val ivBinding = + ItemQrcodeBinding.inflate(LayoutInflater.from(ownerActivity)) + ivBinding.ivQcode.setImageBitmap( + QRCodeDecoder.createQRCode( + url + + ) + ) + AlertDialog.Builder(ownerActivity).setView(ivBinding.root).show() + } + + 1 -> { + Utils.setClipboard(ownerActivity, url) + } + + else -> ownerActivity.toast("else") + } + } catch (e: Exception) { + Log.e(AppConfig.TAG, "Share subscription failed", e) + } + }.show() + } + + override fun onRefreshData() { + refreshData() + } + } } 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 562fd8a7..f97bb70a 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 @@ -1,37 +1,22 @@ package com.v2ray.ang.ui -import android.content.Intent import android.graphics.Color import android.text.TextUtils -import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.appcompat.app.AlertDialog import androidx.recyclerview.widget.RecyclerView -import com.v2ray.ang.AppConfig -import com.v2ray.ang.R -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.helper.ItemTouchHelperAdapter import com.v2ray.ang.helper.ItemTouchHelperViewHolder -import com.v2ray.ang.util.QRCodeDecoder import com.v2ray.ang.util.Utils import com.v2ray.ang.viewmodel.SubscriptionsViewModel class SubSettingRecyclerAdapter( - val activity: SubSettingActivity, - private val viewModel: SubscriptionsViewModel + private val viewModel: SubscriptionsViewModel, + private val adapterListener: BaseAdapterListener? ) : RecyclerView.Adapter(), ItemTouchHelperAdapter { - private var mActivity: SubSettingActivity = activity - - private val share_method: Array by lazy { - mActivity.resources.getStringArray(R.array.share_sub_method) - } - override fun getItemCount() = viewModel.getAll().size override fun onBindViewHolder(holder: MainViewHolder, position: Int) { @@ -45,14 +30,11 @@ class SubSettingRecyclerAdapter( holder.itemView.setBackgroundColor(Color.TRANSPARENT) holder.itemSubSettingBinding.layoutEdit.setOnClickListener { - mActivity.startActivity( - Intent(mActivity, SubEditActivity::class.java) - .putExtra("subId", subId) - ) + adapterListener?.onEdit(subId) } holder.itemSubSettingBinding.layoutRemove.setOnClickListener { - removeSubscription(subId, position) + adapterListener?.onRemove(subId, position) } holder.itemSubSettingBinding.chkEnable.setOnCheckedChangeListener { it, isChecked -> @@ -72,58 +54,11 @@ class SubSettingRecyclerAdapter( holder.itemSubSettingBinding.chkEnable.visibility = View.VISIBLE holder.itemSubSettingBinding.layoutLastUpdated.visibility = View.VISIBLE holder.itemSubSettingBinding.layoutShare.setOnClickListener { - AlertDialog.Builder(mActivity) - .setItems(share_method.asList().toTypedArray()) { _, i -> - try { - when (i) { - 0 -> { - val ivBinding = - ItemQrcodeBinding.inflate(LayoutInflater.from(mActivity)) - ivBinding.ivQcode.setImageBitmap( - QRCodeDecoder.createQRCode( - subItem.url - - ) - ) - AlertDialog.Builder(mActivity).setView(ivBinding.root).show() - } - - 1 -> { - Utils.setClipboard(mActivity, subItem.url) - } - - else -> mActivity.toast("else") - } - } catch (e: Exception) { - Log.e(AppConfig.TAG, "Share subscription failed", e) - } - }.show() + adapterListener?.onShare(subItem.url) } } } - private fun removeSubscription(subId: String, position: Int) { - if (MmkvManager.decodeSettingsBool(AppConfig.PREF_CONFIRM_REMOVE)) { - AlertDialog.Builder(mActivity).setMessage(R.string.del_config_comfirm) - .setPositiveButton(android.R.string.ok) { _, _ -> - removeSubscriptionSub(subId, position) - } - .setNegativeButton(android.R.string.cancel) { _, _ -> - //do noting - } - .show() - } else { - removeSubscriptionSub(subId, position) - } - } - - private fun removeSubscriptionSub(subId: String, position: Int) { - viewModel.remove(subId) - notifyItemRemoved(position) - notifyItemRangeChanged(position, viewModel.getAll().size) - mActivity.refreshData() - } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainViewHolder { return MainViewHolder( ItemRecyclerSubSettingBinding.inflate( @@ -154,7 +89,7 @@ class SubSettingRecyclerAdapter( } override fun onItemMoveCompleted() { - mActivity.refreshData() + adapterListener?.onRefreshData() } override fun onItemDismiss(position: Int) {