feat(subscription): add update state management and UI feedback

This commit is contained in:
zarazaex69
2026-04-11 12:21:13 +03:00
parent 346be42e37
commit 9af6472f8b
3 changed files with 79 additions and 37 deletions
@@ -41,7 +41,6 @@ class SubSettingActivity : BaseActivity() {
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(viewModel, ActivityAdapterListener())
@@ -53,6 +52,10 @@ class SubSettingActivity : BaseActivity() {
mItemTouchHelper = ItemTouchHelper(SimpleItemTouchHelperCallback(adapter))
mItemTouchHelper?.attachToRecyclerView(binding.recyclerView)
viewModel.isUpdating.observe(this) { isUpdating ->
adapter.setUpdating(isUpdating)
}
}
override fun onResume() {
@@ -62,44 +65,55 @@ class SubSettingActivity : BaseActivity() {
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.action_sub_setting, menu)
viewModel.isUpdating.observe(this) { isUpdating ->
menu.findItem(R.id.sub_update)?.isEnabled = !isUpdating
menu.findItem(R.id.add_config)?.isEnabled = !isUpdating
}
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.add_config -> {
startActivity(Intent(this, SubEditActivity::class.java))
true
}
R.id.sub_update -> {
showLoading()
lifecycleScope.launch(Dispatchers.IO) {
val result = AngConfigManager.updateConfigViaSubAll()
delay(500L)
launch(Dispatchers.Main) {
if (result.successCount + result.failureCount + result.skipCount == 0) {
toast(R.string.title_update_subscription_no_subscription)
} else if (result.successCount > 0 && result.failureCount + result.skipCount == 0) {
toast(getString(R.string.title_update_config_count, result.configCount))
} else {
toast(
getString(
R.string.title_update_subscription_result,
result.configCount, result.successCount, result.failureCount, result.skipCount
)
)
}
hideLoading()
refreshData()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.add_config -> {
startActivity(Intent(this, SubEditActivity::class.java))
true
}
true
R.id.sub_update -> {
if (viewModel.isUpdating.value == true) {
return true
}
showLoading()
viewModel.isUpdating.value = true
lifecycleScope.launch(Dispatchers.IO) {
val result = AngConfigManager.updateConfigViaSubAll()
delay(500L)
launch(Dispatchers.Main) {
viewModel.isUpdating.value = false
if (result.successCount + result.failureCount + result.skipCount == 0) {
toast(R.string.title_update_subscription_no_subscription)
} else if (result.successCount > 0 && result.failureCount + result.skipCount == 0) {
toast(getString(R.string.title_update_config_count, result.configCount))
} else {
toast(
getString(
R.string.title_update_subscription_result,
result.configCount, result.successCount, result.failureCount, result.skipCount
)
)
}
hideLoading()
refreshData()
}
}
true
}
else -> super.onOptionsItemSelected(item)
}
else -> super.onOptionsItemSelected(item)
}
@SuppressLint("NotifyDataSetChanged")
@@ -20,6 +20,15 @@ class SubSettingRecyclerAdapter(
private val adapterListener: BaseAdapterListener?
) : RecyclerView.Adapter<SubSettingRecyclerAdapter.MainViewHolder>(), ItemTouchHelperAdapter {
private var isUpdating = false
fun setUpdating(updating: Boolean) {
if (isUpdating != updating) {
isUpdating = updating
notifyDataSetChanged()
}
}
override fun getItemCount() = viewModel.getAll().size
override fun onBindViewHolder(holder: MainViewHolder, position: Int) {
@@ -32,16 +41,28 @@ class SubSettingRecyclerAdapter(
holder.itemSubSettingBinding.tvLastUpdated.text = Utils.formatTimestamp(subItem.lastUpdated)
holder.itemView.setBackgroundColor(Color.TRANSPARENT)
val isEnabled = !isUpdating
holder.itemSubSettingBinding.layoutEdit.isClickable = isEnabled
holder.itemSubSettingBinding.layoutEdit.alpha = if (isEnabled) 1.0f else 0.5f
holder.itemSubSettingBinding.layoutEdit.setOnClickListener {
adapterListener?.onEdit(subId, position)
if (isEnabled) {
adapterListener?.onEdit(subId, position)
}
}
holder.itemSubSettingBinding.layoutRemove.isClickable = isEnabled
holder.itemSubSettingBinding.layoutRemove.alpha = if (isEnabled) 1.0f else 0.5f
holder.itemSubSettingBinding.layoutRemove.setOnClickListener {
adapterListener?.onRemove(subId, position)
if (isEnabled) {
adapterListener?.onRemove(subId, position)
}
}
holder.itemSubSettingBinding.chkEnable.isEnabled = isEnabled
holder.itemSubSettingBinding.chkEnable.alpha = if (isEnabled) 1.0f else 0.5f
holder.itemSubSettingBinding.chkEnable.setOnCheckedChangeListener { it, isChecked ->
if (!it.isPressed) return@setOnCheckedChangeListener
if (!it.isPressed || !isEnabled) return@setOnCheckedChangeListener
subItem.enabled = isChecked
viewModel.update(subId, subItem)
}
@@ -56,8 +77,12 @@ class SubSettingRecyclerAdapter(
holder.itemSubSettingBinding.layoutShare.visibility = View.VISIBLE
holder.itemSubSettingBinding.chkEnable.visibility = View.VISIBLE
holder.itemSubSettingBinding.layoutLastUpdated.visibility = View.VISIBLE
holder.itemSubSettingBinding.layoutShare.isClickable = isEnabled
holder.itemSubSettingBinding.layoutShare.alpha = if (isEnabled) 1.0f else 0.5f
holder.itemSubSettingBinding.layoutShare.setOnClickListener {
adapterListener?.onShare(subItem.url)
if (isEnabled) {
adapterListener?.onShare(subItem.url)
}
}
}
}
@@ -1,5 +1,6 @@
package xyz.zarazaex.olc.viewmodel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import xyz.zarazaex.olc.dto.SubscriptionCache
import xyz.zarazaex.olc.dto.SubscriptionItem
@@ -11,6 +12,8 @@ class SubscriptionsViewModel : ViewModel() {
private val subscriptions: MutableList<SubscriptionCache> =
MmkvManager.decodeSubscriptions().toMutableList()
val isUpdating = MutableLiveData<Boolean>(false)
fun getAll(): List<SubscriptionCache> = subscriptions.toList()
fun reload() {