From 3ad2ad402f6c0a3d818a599f3939d8823808f0ed Mon Sep 17 00:00:00 2001 From: davidoskky Date: Fri, 28 Feb 2025 20:01:15 +0100 Subject: [PATCH 1/4] Add a confirmation when deleting a source A popup appears after tapping the delete source button with the name of the source. --- .../android/adapters/SourcesListAdapter.kt | 70 +++++++++++-------- androidApp/src/main/res/values/strings.xml | 2 + 2 files changed, 41 insertions(+), 31 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..63b226a 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 @@ -8,6 +8,7 @@ import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.Toast +import androidx.appcompat.app.AlertDialog import androidx.constraintlayout.widget.ConstraintLayout import androidx.recyclerview.widget.RecyclerView import bou.amine.apps.readerforselfossv2.android.R @@ -39,10 +40,7 @@ class SourcesListAdapter( private val repository: Repository by instance() private val appSettingsService: AppSettingsService by instance() - override fun onCreateViewHolder( - parent: ViewGroup, - viewType: Int, - ): ViewHolder { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { binding = SourceListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) return ViewHolder(binding.root) } @@ -51,50 +49,31 @@ class SourcesListAdapter( holder: ViewHolder, position: Int, ) { - val itm = items[position] + val source = 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() - } - } - } + deleteBtn.setOnClickListener { this.showDeleteConfirmationDialog(source, position) } 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()) + if (source.getIcon(repository.baseUrl).isEmpty()) { + binding.itemImage.setBackgroundAndText(source.title.getHtmlDecoded()) } else { - c.circularDrawable(itm.getIcon(repository.baseUrl), binding.itemImage, appSettingsService) + c.circularDrawable(source.getIcon(repository.baseUrl), binding.itemImage, appSettingsService) } - if (!itm.error.isNullOrBlank()) { + if (!source.error.isNullOrBlank()) { binding.errorText.visibility = View.VISIBLE - binding.errorText.text = itm.error + binding.errorText.text = source.error } else { binding.errorText.visibility = View.GONE } - binding.sourceTitle.text = itm.title.getHtmlDecoded() + binding.sourceTitle.text = source.title.getHtmlDecoded() } override fun getItemId(position: Int) = position.toLong() @@ -103,6 +82,35 @@ class SourcesListAdapter( override fun getItemCount(): Int = items.size + + 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() + } + } + } + } + inner class ViewHolder( val mView: ConstraintLayout, ) : RecyclerView.ViewHolder(mView) 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 -- 2.34.1 From ba4b27651b8754f26253c65f6edcb3770af4dd3f Mon Sep 17 00:00:00 2001 From: davidoskky Date: Fri, 28 Feb 2025 20:13:00 +0100 Subject: [PATCH 2/4] Move binding source binding logic to the viewholder. --- .../android/adapters/SourcesListAdapter.kt | 120 ++++++++---------- 1 file changed, 56 insertions(+), 64 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 63b226a..aca1943 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,10 +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.appcompat.app.AlertDialog -import androidx.constraintlayout.widget.ConstraintLayout import androidx.recyclerview.widget.RecyclerView import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.UpsertSourceActivity @@ -33,47 +31,15 @@ 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 source = items[position] - - val deleteBtn: Button = holder.mView.findViewById(R.id.deleteBtn) - - deleteBtn.setOnClickListener { this.showDeleteConfirmationDialog(source, position) } - - holder.mView.setOnClickListener { - repository.setSelectedSource(source) - app.startActivity(Intent(app, UpsertSourceActivity::class.java)) - } - - if (source.getIcon(repository.baseUrl).isEmpty()) { - binding.itemImage.setBackgroundAndText(source.title.getHtmlDecoded()) - } else { - c.circularDrawable(source.getIcon(repository.baseUrl), binding.itemImage, appSettingsService) - } - - if (!source.error.isNullOrBlank()) { - binding.errorText.visibility = View.VISIBLE - binding.errorText.text = source.error - } else { - binding.errorText.visibility = View.GONE - } - - binding.sourceTitle.text = source.title.getHtmlDecoded() + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(items[position], position) } override fun getItemId(position: Int) = position.toLong() @@ -83,35 +49,61 @@ class SourcesListAdapter( override fun getItemCount(): Int = items.size - 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() - } + inner class ViewHolder(val binding: SourceListItemBinding) : RecyclerView.ViewHolder(binding.root) { - 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) + 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 { - Toast.makeText( - app, - R.string.can_delete_source, - Toast.LENGTH_SHORT, - ).show() + 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() + } } } } } - - inner class ViewHolder( - val mView: ConstraintLayout, - ) : RecyclerView.ViewHolder(mView) } -- 2.34.1 From 43146b5afff461add8992fe2c1ecf431f9e595fd Mon Sep 17 00:00:00 2001 From: davidoskky Date: Sun, 9 Mar 2025 12:42:44 +0100 Subject: [PATCH 3/4] Fix Ktlint warnings --- .../android/adapters/SourcesListAdapter.kt | 47 +++++++++++++------ 1 file changed, 32 insertions(+), 15 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 aca1943..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 @@ -32,13 +32,19 @@ class SourcesListAdapter( ) : RecyclerView.Adapter(), DIAware { override val di: DI by closestDI(app) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int, + ): ViewHolder { val binding = SourceListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) return ViewHolder(binding) } - override fun onBindViewHolder(holder: ViewHolder, position: Int) { + override fun onBindViewHolder( + holder: ViewHolder, + position: Int, + ) { holder.bind(items[position], position) } @@ -48,14 +54,17 @@ class SourcesListAdapter( override fun getItemCount(): Int = items.size - - inner class ViewHolder(val binding: SourceListItemBinding) : RecyclerView.ViewHolder(binding.root) { - + 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) { + fun bind( + source: SelfossModel.SourceDetail, + position: Int, + ) { binding.apply { sourceTitle.text = source.title.getHtmlDecoded() if (source.getIcon(repository.baseUrl).isEmpty()) { @@ -78,8 +87,12 @@ class SourcesListAdapter( } } - private fun showDeleteConfirmationDialog(source: SelfossModel.SourceDetail, position: Int) { - AlertDialog.Builder(app) + 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) } @@ -87,7 +100,10 @@ class SourcesListAdapter( .show() } - private fun deleteSource(source: SelfossModel.SourceDetail, position: Int) { + private fun deleteSource( + source: SelfossModel.SourceDetail, + position: Int, + ) { CoroutineScope(Dispatchers.IO).launch { val successfullyDeletedSource = repository.deleteSource(source.id, source.title) launch(Dispatchers.Main) { @@ -96,11 +112,12 @@ class SourcesListAdapter( notifyItemRemoved(position) notifyItemRangeChanged(position, itemCount) } else { - Toast.makeText( - app, - R.string.can_delete_source, - Toast.LENGTH_SHORT, - ).show() + Toast + .makeText( + app, + R.string.can_delete_source, + Toast.LENGTH_SHORT, + ).show() } } } -- 2.34.1 From cdf4ece99c7d434a54bf294bea48a046a1fdba8a Mon Sep 17 00:00:00 2001 From: Amine Date: Sun, 9 Mar 2025 13:55:23 +0100 Subject: [PATCH 4/4] chore: translations. --- androidApp/src/main/res/values-ca-rES/strings.xml | 2 ++ androidApp/src/main/res/values-de-rDE/strings.xml | 2 ++ androidApp/src/main/res/values-es-rES/strings.xml | 2 ++ androidApp/src/main/res/values-fr-rFR/strings.xml | 2 ++ androidApp/src/main/res/values-gl-rES/strings.xml | 2 ++ androidApp/src/main/res/values-in-rID/strings.xml | 2 ++ androidApp/src/main/res/values-it-rIT/strings.xml | 2 ++ androidApp/src/main/res/values-ko-rKR/strings.xml | 2 ++ androidApp/src/main/res/values-nl-rNL/strings.xml | 2 ++ androidApp/src/main/res/values-pt-rBR/strings.xml | 2 ++ androidApp/src/main/res/values-pt-rPT/strings.xml | 2 ++ androidApp/src/main/res/values-si-rLK/strings.xml | 2 ++ androidApp/src/main/res/values-tr-rTR/strings.xml | 2 ++ androidApp/src/main/res/values-zh-rCN/strings.xml | 2 ++ androidApp/src/main/res/values-zh-rTW/strings.xml | 2 ++ 15 files changed, 30 insertions(+) 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 -- 2.34.1