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.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Button
import android.widget.Toast import android.widget.Toast
import androidx.constraintlayout.widget.ConstraintLayout import androidx.appcompat.app.AlertDialog
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.R
import bou.amine.apps.readerforselfossv2.android.UpsertSourceActivity import bou.amine.apps.readerforselfossv2.android.UpsertSourceActivity
@ -32,69 +31,21 @@ class SourcesListAdapter(
private val items: ArrayList<SelfossModel.SourceDetail>, private val items: ArrayList<SelfossModel.SourceDetail>,
) : RecyclerView.Adapter<SourcesListAdapter.ViewHolder>(), ) : RecyclerView.Adapter<SourcesListAdapter.ViewHolder>(),
DIAware { DIAware {
private val c: Context = app.baseContext
private lateinit var binding: SourceListItemBinding
override val di: DI by closestDI(app) override val di: DI by closestDI(app)
private val repository: Repository by instance()
private val appSettingsService: AppSettingsService by instance()
override fun onCreateViewHolder( override fun onCreateViewHolder(
parent: ViewGroup, parent: ViewGroup,
viewType: Int, viewType: Int,
): ViewHolder { ): ViewHolder {
binding = SourceListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) val binding = SourceListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding.root) return ViewHolder(binding)
} }
override fun onBindViewHolder( override fun onBindViewHolder(
holder: ViewHolder, holder: ViewHolder,
position: Int, position: Int,
) { ) {
val itm = items[position] holder.bind(items[position], position)
val deleteBtn: Button = holder.mView.findViewById(R.id.deleteBtn)
deleteBtn.setOnClickListener {
val (id, title) = items[position]
CoroutineScope(Dispatchers.IO).launch {
val successfullyDeletedSource = repository.deleteSource(id, title)
if (successfullyDeletedSource) {
items.removeAt(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, itemCount)
} else {
Toast
.makeText(
app,
R.string.can_delete_source,
Toast.LENGTH_SHORT,
).show()
}
}
}
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 getItemId(position: Int) = position.toLong()
@ -104,6 +55,72 @@ class SourcesListAdapter(
override fun getItemCount(): Int = items.size override fun getItemCount(): Int = items.size
inner class ViewHolder( inner class ViewHolder(
val mView: ConstraintLayout, val binding: SourceListItemBinding,
) : RecyclerView.ViewHolder(mView) ) : 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(source.id, source.title)
launch(Dispatchers.Main) {
if (successfullyDeletedSource) {
items.removeAt(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, itemCount)
} else {
Toast
.makeText(
app,
R.string.can_delete_source,
Toast.LENGTH_SHORT,
).show()
}
}
}
}
}
} }

View File

@ -129,4 +129,6 @@
<string name="action_about">"Quant a"</string> <string name="action_about">"Quant a"</string>
<string name="marked_as_read">"Element llegit"</string> <string name="marked_as_read">"Element llegit"</string>
<string name="marked_as_unread">"Item unread"</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> </resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Über"</string> <string name="action_about">"Über"</string>
<string name="marked_as_read">"Artikel gelesen"</string> <string name="marked_as_read">"Artikel gelesen"</string>
<string name="marked_as_unread">"Item unread"</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> </resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Acerca de"</string> <string name="action_about">"Acerca de"</string>
<string name="marked_as_read">"Artículo leído"</string> <string name="marked_as_read">"Artículo leído"</string>
<string name="marked_as_unread">"Artículo no 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> </resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"À propos"</string> <string name="action_about">"À propos"</string>
<string name="marked_as_read">"Marqué comme lu"</string> <string name="marked_as_read">"Marqué comme lu"</string>
<string name="marked_as_unread">"Marqué comme non 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> </resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Acerca de"</string> <string name="action_about">"Acerca de"</string>
<string name="marked_as_read">"Elemento lido"</string> <string name="marked_as_read">"Elemento lido"</string>
<string name="marked_as_unread">"Elemento non 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> </resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Tentang"</string> <string name="action_about">"Tentang"</string>
<string name="marked_as_read">"Membaca item"</string> <string name="marked_as_read">"Membaca item"</string>
<string name="marked_as_unread">"Item unread"</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> </resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Informazioni"</string> <string name="action_about">"Informazioni"</string>
<string name="marked_as_read">"Articolo letto"</string> <string name="marked_as_read">"Articolo letto"</string>
<string name="marked_as_unread">"Item unread"</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> </resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"정보"</string> <string name="action_about">"정보"</string>
<string name="marked_as_read">"항목 읽기"</string> <string name="marked_as_read">"항목 읽기"</string>
<string name="marked_as_unread">"Item unread"</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> </resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Over"</string> <string name="action_about">"Over"</string>
<string name="marked_as_read">"Artikel gelezen"</string> <string name="marked_as_read">"Artikel gelezen"</string>
<string name="marked_as_unread">"Item unread"</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> </resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Sobre"</string> <string name="action_about">"Sobre"</string>
<string name="marked_as_read">"Item lido"</string> <string name="marked_as_read">"Item lido"</string>
<string name="marked_as_unread">"Item unread"</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> </resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Sobre"</string> <string name="action_about">"Sobre"</string>
<string name="marked_as_read">"Item lido"</string> <string name="marked_as_read">"Item lido"</string>
<string name="marked_as_unread">"Item unread"</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> </resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"මේ ගැන"</string> <string name="action_about">"මේ ගැන"</string>
<string name="marked_as_read">"Item read"</string> <string name="marked_as_read">"Item read"</string>
<string name="marked_as_unread">"Item unread"</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> </resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"Hakkında"</string> <string name="action_about">"Hakkında"</string>
<string name="marked_as_read">"Öğeleri oku"</string> <string name="marked_as_read">"Öğeleri oku"</string>
<string name="marked_as_unread">"Item unread"</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> </resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"关于我们"</string> <string name="action_about">"关于我们"</string>
<string name="marked_as_read">"已读"</string> <string name="marked_as_read">"已读"</string>
<string name="marked_as_unread">"未读条目"</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> </resources>

View File

@ -129,4 +129,6 @@
<string name="action_about">"关于我们"</string> <string name="action_about">"关于我们"</string>
<string name="marked_as_read">"已读"</string> <string name="marked_as_read">"已读"</string>
<string name="marked_as_unread">"未讀項目"</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> </resources>

View File

@ -131,4 +131,6 @@
<string name="action_about">"About"</string> <string name="action_about">"About"</string>
<string name="marked_as_read">"Item read"</string> <string name="marked_as_read">"Item read"</string>
<string name="marked_as_unread">"Item unread"</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> </resources>