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 0aa6d1ae..03c4b7ef 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 b49b5cab..c3bd1f70 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 9e672304..7dfe940a 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 035c84d2..fb12df99 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 2fc0366c..07d553a8 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 e3a3e389..e3576b03 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 8175827f..30eeaef7 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 8bb17490..d11d45d3 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 66920664..63c81b1e 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 43da71bb..3035383c 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 c847693f..d3019324 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 41543a0e..fb4a81dc 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 9ad0b919..56179362 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 49252428..96b2912e 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 f8a132c8..a1ab3457 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 108e15fc..dbf21a08 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 8698e41c..d04a31ac 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