From a1c0241a58c9b28ce24901633cd8d230f2cca357 Mon Sep 17 00:00:00 2001 From: davidoskky Date: Sun, 9 Mar 2025 13:49:32 +0000 Subject: [PATCH] Show a confirmation dialog before deleting sources (#185) ## 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 Reviewed-on: https://gitea.amine-bouabdallaoui.fr/Louvorg/ReaderForSelfoss-multiplatform/pulls/185 Co-authored-by: davidoskky Co-committed-by: davidoskky --- .../android/adapters/SourcesListAdapter.kt | 127 ++++++++++-------- .../src/main/res/values-ca-rES/strings.xml | 2 + .../src/main/res/values-de-rDE/strings.xml | 2 + .../src/main/res/values-es-rES/strings.xml | 2 + .../src/main/res/values-fr-rFR/strings.xml | 2 + .../src/main/res/values-gl-rES/strings.xml | 2 + .../src/main/res/values-in-rID/strings.xml | 2 + .../src/main/res/values-it-rIT/strings.xml | 2 + .../src/main/res/values-ko-rKR/strings.xml | 2 + .../src/main/res/values-nl-rNL/strings.xml | 2 + .../src/main/res/values-pt-rBR/strings.xml | 2 + .../src/main/res/values-pt-rPT/strings.xml | 2 + .../src/main/res/values-si-rLK/strings.xml | 2 + .../src/main/res/values-tr-rTR/strings.xml | 2 + .../src/main/res/values-zh-rCN/strings.xml | 2 + .../src/main/res/values-zh-rTW/strings.xml | 2 + androidApp/src/main/res/values/strings.xml | 2 + 17 files changed, 104 insertions(+), 55 deletions(-) diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt index 0aa6d1a..03c4b7e 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt @@ -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,69 +31,21 @@ class SourcesListAdapter( private val items: ArrayList, ) : RecyclerView.Adapter(), 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] - - 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() + holder.bind(items[position], position) } override fun getItemId(position: Int) = position.toLong() @@ -104,6 +55,72 @@ class SourcesListAdapter( override fun getItemCount(): Int = items.size inner class ViewHolder( - val mView: ConstraintLayout, - ) : RecyclerView.ViewHolder(mView) + 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(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() + } + } + } + } + } } diff --git a/androidApp/src/main/res/values-ca-rES/strings.xml b/androidApp/src/main/res/values-ca-rES/strings.xml index b49b5ca..c3bd1f7 100644 --- a/androidApp/src/main/res/values-ca-rES/strings.xml +++ b/androidApp/src/main/res/values-ca-rES/strings.xml @@ -129,4 +129,6 @@ "Quant a" "Element llegit" "Item unread" + Confirm Deletion + Are you sure you want to delete the following source?\n%s diff --git a/androidApp/src/main/res/values-de-rDE/strings.xml b/androidApp/src/main/res/values-de-rDE/strings.xml index 9e67230..7dfe940 100644 --- a/androidApp/src/main/res/values-de-rDE/strings.xml +++ b/androidApp/src/main/res/values-de-rDE/strings.xml @@ -129,4 +129,6 @@ "Über" "Artikel gelesen" "Item unread" + Confirm Deletion + Are you sure you want to delete the following source?\n%s diff --git a/androidApp/src/main/res/values-es-rES/strings.xml b/androidApp/src/main/res/values-es-rES/strings.xml index 035c84d..fb12df9 100644 --- a/androidApp/src/main/res/values-es-rES/strings.xml +++ b/androidApp/src/main/res/values-es-rES/strings.xml @@ -129,4 +129,6 @@ "Acerca de" "Artículo leído" "Artículo no leído" + Confirm Deletion + Are you sure you want to delete the following source?\n%s diff --git a/androidApp/src/main/res/values-fr-rFR/strings.xml b/androidApp/src/main/res/values-fr-rFR/strings.xml index 2fc0366..07d553a 100644 --- a/androidApp/src/main/res/values-fr-rFR/strings.xml +++ b/androidApp/src/main/res/values-fr-rFR/strings.xml @@ -129,4 +129,6 @@ "À propos" "Marqué comme lu" "Marqué comme non lu" + Confirm Deletion + Are you sure you want to delete the following source?\n%s diff --git a/androidApp/src/main/res/values-gl-rES/strings.xml b/androidApp/src/main/res/values-gl-rES/strings.xml index e3a3e38..e3576b0 100644 --- a/androidApp/src/main/res/values-gl-rES/strings.xml +++ b/androidApp/src/main/res/values-gl-rES/strings.xml @@ -129,4 +129,6 @@ "Acerca de" "Elemento lido" "Elemento non lido" + Confirm Deletion + Are you sure you want to delete the following source?\n%s diff --git a/androidApp/src/main/res/values-in-rID/strings.xml b/androidApp/src/main/res/values-in-rID/strings.xml index 8175827..30eeaef 100644 --- a/androidApp/src/main/res/values-in-rID/strings.xml +++ b/androidApp/src/main/res/values-in-rID/strings.xml @@ -129,4 +129,6 @@ "Tentang" "Membaca item" "Item unread" + Confirm Deletion + Are you sure you want to delete the following source?\n%s diff --git a/androidApp/src/main/res/values-it-rIT/strings.xml b/androidApp/src/main/res/values-it-rIT/strings.xml index 8bb1749..d11d45d 100644 --- a/androidApp/src/main/res/values-it-rIT/strings.xml +++ b/androidApp/src/main/res/values-it-rIT/strings.xml @@ -129,4 +129,6 @@ "Informazioni" "Articolo letto" "Item unread" + Confirm Deletion + Are you sure you want to delete the following source?\n%s diff --git a/androidApp/src/main/res/values-ko-rKR/strings.xml b/androidApp/src/main/res/values-ko-rKR/strings.xml index 6692066..63c81b1 100644 --- a/androidApp/src/main/res/values-ko-rKR/strings.xml +++ b/androidApp/src/main/res/values-ko-rKR/strings.xml @@ -129,4 +129,6 @@ "정보" "항목 읽기" "Item unread" + Confirm Deletion + Are you sure you want to delete the following source?\n%s diff --git a/androidApp/src/main/res/values-nl-rNL/strings.xml b/androidApp/src/main/res/values-nl-rNL/strings.xml index 43da71b..3035383 100644 --- a/androidApp/src/main/res/values-nl-rNL/strings.xml +++ b/androidApp/src/main/res/values-nl-rNL/strings.xml @@ -129,4 +129,6 @@ "Over" "Artikel gelezen" "Item unread" + Confirm Deletion + Are you sure you want to delete the following source?\n%s diff --git a/androidApp/src/main/res/values-pt-rBR/strings.xml b/androidApp/src/main/res/values-pt-rBR/strings.xml index c847693..d301932 100644 --- a/androidApp/src/main/res/values-pt-rBR/strings.xml +++ b/androidApp/src/main/res/values-pt-rBR/strings.xml @@ -129,4 +129,6 @@ "Sobre" "Item lido" "Item unread" + Confirm Deletion + Are you sure you want to delete the following source?\n%s diff --git a/androidApp/src/main/res/values-pt-rPT/strings.xml b/androidApp/src/main/res/values-pt-rPT/strings.xml index 41543a0..fb4a81d 100644 --- a/androidApp/src/main/res/values-pt-rPT/strings.xml +++ b/androidApp/src/main/res/values-pt-rPT/strings.xml @@ -129,4 +129,6 @@ "Sobre" "Item lido" "Item unread" + Confirm Deletion + Are you sure you want to delete the following source?\n%s diff --git a/androidApp/src/main/res/values-si-rLK/strings.xml b/androidApp/src/main/res/values-si-rLK/strings.xml index 9ad0b91..5617936 100644 --- a/androidApp/src/main/res/values-si-rLK/strings.xml +++ b/androidApp/src/main/res/values-si-rLK/strings.xml @@ -129,4 +129,6 @@ "මේ ගැන" "Item read" "Item unread" + Confirm Deletion + Are you sure you want to delete the following source?\n%s diff --git a/androidApp/src/main/res/values-tr-rTR/strings.xml b/androidApp/src/main/res/values-tr-rTR/strings.xml index 4925242..96b2912 100644 --- a/androidApp/src/main/res/values-tr-rTR/strings.xml +++ b/androidApp/src/main/res/values-tr-rTR/strings.xml @@ -129,4 +129,6 @@ "Hakkında" "Öğeleri oku" "Item unread" + Confirm Deletion + Are you sure you want to delete the following source?\n%s diff --git a/androidApp/src/main/res/values-zh-rCN/strings.xml b/androidApp/src/main/res/values-zh-rCN/strings.xml index f8a132c..a1ab345 100644 --- a/androidApp/src/main/res/values-zh-rCN/strings.xml +++ b/androidApp/src/main/res/values-zh-rCN/strings.xml @@ -129,4 +129,6 @@ "关于我们" "已读" "未读条目" + Confirm Deletion + Are you sure you want to delete the following source?\n%s diff --git a/androidApp/src/main/res/values-zh-rTW/strings.xml b/androidApp/src/main/res/values-zh-rTW/strings.xml index 108e15f..dbf21a0 100644 --- a/androidApp/src/main/res/values-zh-rTW/strings.xml +++ b/androidApp/src/main/res/values-zh-rTW/strings.xml @@ -129,4 +129,6 @@ "关于我们" "已读" "未讀項目" + Confirm Deletion + Are you sure you want to delete the following source?\n%s diff --git a/androidApp/src/main/res/values/strings.xml b/androidApp/src/main/res/values/strings.xml index 8698e41..d04a31a 100644 --- a/androidApp/src/main/res/values/strings.xml +++ b/androidApp/src/main/res/values/strings.xml @@ -131,4 +131,6 @@ "About" "Item read" "Item unread" + Confirm Deletion + Are you sure you want to delete the following source?\n%s