Show a confirmation dialog before deleting sources (#185)
All checks were successful
Check master code / build (push) Successful in 15m3s

## Types of changes

- [ x ] I have read the **CONTRIBUTING** document.
- [ x ] My code follows the code style of this project.
- [ ] I have updated the documentation accordingly.
- [ ] I have added tests to cover my changes.
- [ x ] All new and existing tests passed.
- [ x ] This is **NOT** translation related.

This is implements feature #156

I added a confirmation dialogue which pops up after tapping the delete source button. The popup displays the full name of the source to be deleted and allows the user to decide not to delete the source to prevent erroneous deletions.

I moved most of the logic into the viewholder. Can be easily reverted if you prefer.

All tests pass. I tested correct behavior in emulated versions of android API 25, 34 and 35.

Co-authored-by: Amine <amine.bouabdallaoui@pm.me>
Reviewed-on: #185
Co-authored-by: davidoskky <davidoskky@yahoo.it>
Co-committed-by: davidoskky <davidoskky@yahoo.it>
This commit is contained in:
davidoskky 2025-03-09 13:49:32 +00:00 committed by Amine Bouabdallaoui
parent f38936f9b4
commit a1c0241a58
17 changed files with 104 additions and 55 deletions

View File

@ -6,9 +6,8 @@ import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.Toast
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.appcompat.app.AlertDialog
import androidx.recyclerview.widget.RecyclerView
import bou.amine.apps.readerforselfossv2.android.R
import bou.amine.apps.readerforselfossv2.android.UpsertSourceActivity
@ -32,33 +31,82 @@ class SourcesListAdapter(
private val items: ArrayList<SelfossModel.SourceDetail>,
) : RecyclerView.Adapter<SourcesListAdapter.ViewHolder>(),
DIAware {
private val c: Context = app.baseContext
private lateinit var binding: SourceListItemBinding
override val di: DI by closestDI(app)
private val repository: Repository by instance()
private val appSettingsService: AppSettingsService by instance()
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int,
): ViewHolder {
binding = SourceListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding.root)
val binding = SourceListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(
holder: ViewHolder,
position: Int,
) {
val itm = items[position]
holder.bind(items[position], position)
}
val deleteBtn: Button = holder.mView.findViewById(R.id.deleteBtn)
override fun getItemId(position: Int) = position.toLong()
deleteBtn.setOnClickListener {
val (id, title) = items[position]
override fun getItemViewType(position: Int) = position
override fun getItemCount(): Int = items.size
inner class ViewHolder(
val binding: SourceListItemBinding,
) : RecyclerView.ViewHolder(binding.root) {
private val context: Context = app.applicationContext
private val repository: Repository by instance()
private val appSettingsService: AppSettingsService by instance()
fun bind(
source: SelfossModel.SourceDetail,
position: Int,
) {
binding.apply {
sourceTitle.text = source.title.getHtmlDecoded()
if (source.getIcon(repository.baseUrl).isEmpty()) {
itemImage.setBackgroundAndText(source.title.getHtmlDecoded())
} else {
context.circularDrawable(source.getIcon(repository.baseUrl), itemImage, appSettingsService)
}
errorText.apply {
visibility = if (!source.error.isNullOrBlank()) View.VISIBLE else View.GONE
text = source.error
}
deleteBtn.setOnClickListener { showDeleteConfirmationDialog(source, position) }
root.setOnClickListener {
repository.setSelectedSource(source)
app.startActivity(Intent(app, UpsertSourceActivity::class.java))
}
}
}
private fun showDeleteConfirmationDialog(
source: SelfossModel.SourceDetail,
position: Int,
) {
AlertDialog
.Builder(app)
.setTitle(app.getString(R.string.confirm_delete_title))
.setMessage(app.getString(R.string.confirm_delete_message, source.title))
.setPositiveButton(android.R.string.ok) { _, _ -> deleteSource(source, position) }
.setNegativeButton(android.R.string.cancel, null)
.show()
}
private fun deleteSource(
source: SelfossModel.SourceDetail,
position: Int,
) {
CoroutineScope(Dispatchers.IO).launch {
val successfullyDeletedSource = repository.deleteSource(id, title)
val successfullyDeletedSource = repository.deleteSource(source.id, source.title)
launch(Dispatchers.Main) {
if (successfullyDeletedSource) {
items.removeAt(position)
notifyItemRemoved(position)
@ -73,37 +121,6 @@ class SourcesListAdapter(
}
}
}
holder.mView.setOnClickListener {
val source = items[position]
repository.setSelectedSource(source)
app.startActivity(Intent(app, UpsertSourceActivity::class.java))
}
if (itm.getIcon(repository.baseUrl).isEmpty()) {
binding.itemImage.setBackgroundAndText(itm.title.getHtmlDecoded())
} else {
c.circularDrawable(itm.getIcon(repository.baseUrl), binding.itemImage, appSettingsService)
}
if (!itm.error.isNullOrBlank()) {
binding.errorText.visibility = View.VISIBLE
binding.errorText.text = itm.error
} else {
binding.errorText.visibility = View.GONE
}
binding.sourceTitle.text = itm.title.getHtmlDecoded()
}
override fun getItemId(position: Int) = position.toLong()
override fun getItemViewType(position: Int) = position
override fun getItemCount(): Int = items.size
inner class ViewHolder(
val mView: ConstraintLayout,
) : RecyclerView.ViewHolder(mView)
}

View File

@ -129,4 +129,6 @@
<string name="action_about">"Quant a"</string>
<string name="marked_as_read">"Element llegit"</string>
<string name="marked_as_unread">"Item unread"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Über"</string>
<string name="marked_as_read">"Artikel gelesen"</string>
<string name="marked_as_unread">"Item unread"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Acerca de"</string>
<string name="marked_as_read">"Artículo leído"</string>
<string name="marked_as_unread">"Artículo no leído"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"À propos"</string>
<string name="marked_as_read">"Marqué comme lu"</string>
<string name="marked_as_unread">"Marqué comme non lu"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Acerca de"</string>
<string name="marked_as_read">"Elemento lido"</string>
<string name="marked_as_unread">"Elemento non lido"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Tentang"</string>
<string name="marked_as_read">"Membaca item"</string>
<string name="marked_as_unread">"Item unread"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Informazioni"</string>
<string name="marked_as_read">"Articolo letto"</string>
<string name="marked_as_unread">"Item unread"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"정보"</string>
<string name="marked_as_read">"항목 읽기"</string>
<string name="marked_as_unread">"Item unread"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Over"</string>
<string name="marked_as_read">"Artikel gelezen"</string>
<string name="marked_as_unread">"Item unread"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Sobre"</string>
<string name="marked_as_read">"Item lido"</string>
<string name="marked_as_unread">"Item unread"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Sobre"</string>
<string name="marked_as_read">"Item lido"</string>
<string name="marked_as_unread">"Item unread"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"මේ ගැන"</string>
<string name="marked_as_read">"Item read"</string>
<string name="marked_as_unread">"Item unread"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Hakkında"</string>
<string name="marked_as_read">"Öğeleri oku"</string>
<string name="marked_as_unread">"Item unread"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"关于我们"</string>
<string name="marked_as_read">"已读"</string>
<string name="marked_as_unread">"未读条目"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"关于我们"</string>
<string name="marked_as_read">"已读"</string>
<string name="marked_as_unread">"未讀項目"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>

View File

@ -131,4 +131,6 @@
<string name="action_about">"About"</string>
<string name="marked_as_read">"Item read"</string>
<string name="marked_as_unread">"Item unread"</string>
<string name="confirm_delete_title">Confirm Deletion</string>
<string name="confirm_delete_message">Are you sure you want to delete the following source?\n%s</string>
</resources>