From 0bf9ca9a4916487ede857cef537b3afa66003c65 Mon Sep 17 00:00:00 2001 From: davidoskky Date: Tue, 19 Nov 2024 01:50:58 +0100 Subject: [PATCH 1/2] Fix recycleview article positions The articles were being opened by setting a click listener on the binding. In card view this was being done through a function and as such it used the overall viewbind of the view rather than the binding of the item viewholder. Now the functions are more explicit to avoid future errors. Pulled up a few members from ItemCardAdapter and ItemListAdapter to ItemAdapter. --- .../android/HomeActivity.kt | 16 ++------ .../android/adapters/ItemCardAdapter.kt | 34 ++++------------ .../android/adapters/ItemListAdapter.kt | 22 ++--------- .../android/adapters/ItemsAdapter.kt | 39 +++++++++++++++---- 4 files changed, 47 insertions(+), 64 deletions(-) diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt index 09108db8..88f5a40c 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt @@ -58,7 +58,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private lateinit var recyclerViewScrollListener: RecyclerView.OnScrollListener private lateinit var binding: ActivityHomeBinding - private var recyclerAdapter: RecyclerView.Adapter<*>? = null + private var recyclerAdapter: ItemsAdapter? = null private var fromTabShortcut: Boolean = false @@ -477,17 +477,13 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar ItemCardAdapter( this, items, - ) { - updateItems(it) - } + ) } else { recyclerAdapter = ItemListAdapter( this, items, - ) { - updateItems(it) - } + ) binding.recyclerView.addItemDecoration( DividerItemDecoration( @@ -498,7 +494,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } binding.recyclerView.adapter = recyclerAdapter } else { - (recyclerAdapter as ItemsAdapter<*>).updateAllItems(items) + recyclerAdapter!!.updateAllItems(items) } reloadBadges() @@ -660,10 +656,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar else -> repository.badgeUnread.value // if !elementsShown then unread are fetched. } - private fun updateItems(adapterItems: ArrayList) { - items = adapterItems - } - private fun handleRecurringTask() { if (appSettingsService.isPeriodicRefreshEnabled()) { val myConstraints = diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemCardAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemCardAdapter.kt index e61a20dd..a8565a57 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemCardAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemCardAdapter.kt @@ -1,7 +1,6 @@ package bou.amine.apps.readerforselfossv2.android.adapters import android.app.Activity -import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -14,7 +13,6 @@ import bou.amine.apps.readerforselfossv2.android.utils.LinkOnTouchListener import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop import bou.amine.apps.readerforselfossv2.android.utils.glide.circularDrawable import bou.amine.apps.readerforselfossv2.android.utils.openInBrowserAsNewTask -import bou.amine.apps.readerforselfossv2.android.utils.openItemUrl import bou.amine.apps.readerforselfossv2.android.utils.shareLink import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.repository.Repository @@ -32,11 +30,9 @@ import org.kodein.di.instance class ItemCardAdapter( override val app: Activity, - override var items: ArrayList, - override val updateItems: (ArrayList) -> Unit, + override val items: ArrayList, ) : ItemsAdapter() { - private lateinit var binding: CardItemBinding - private val c: Context = app.baseContext + override lateinit var binding: CardItemBinding private val imageMaxHeight: Int = c.resources.getDimension(R.dimen.card_image_max_height).toInt() @@ -52,8 +48,8 @@ class ItemCardAdapter( return ViewHolder(binding) } - private fun handleClickListeners(position: Int) { - binding.favButton.setOnClickListener { + private fun handleClickListeners(holderBinding: CardItemBinding, position: Int) { + holderBinding.favButton.setOnClickListener { val item = items[position] if (item.starred) { CoroutineScope(Dispatchers.IO).launch { @@ -78,27 +74,15 @@ class ItemCardAdapter( } } - private fun handleLinkOpening(position: Int) { - binding.root.setOnClickListener { - repository.setReaderItems(items) - c.openItemUrl( - position, - items[position].getLinkDecoded(), - appSettingsService.isArticleViewerEnabled(), - app, - ) - } - } - override fun onBindViewHolder( holder: ViewHolder, position: Int, ) { with(holder) { - val itm = items[holder.bindingAdapterPosition] + val itm = items[position] - handleClickListeners(holder.bindingAdapterPosition) - handleLinkOpening(holder.bindingAdapterPosition) + handleClickListeners(binding, position) + openLink(binding, position) binding.favButton.isSelected = itm.starred if (appSettingsService.getPublicAccess()) { @@ -140,9 +124,5 @@ class ItemCardAdapter( } } - override fun getItemCount(): Int { - return items.size - } - inner class ViewHolder(val binding: CardItemBinding) : RecyclerView.ViewHolder(binding.root) } diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt index 2d27e847..098433b5 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt @@ -1,7 +1,6 @@ package bou.amine.apps.readerforselfossv2.android.adapters import android.app.Activity -import android.content.Context import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView @@ -10,7 +9,6 @@ import bou.amine.apps.readerforselfossv2.android.databinding.ListItemBinding import bou.amine.apps.readerforselfossv2.android.sendSilentlyWithAcraWithName import bou.amine.apps.readerforselfossv2.android.utils.LinkOnTouchListener import bou.amine.apps.readerforselfossv2.android.utils.glide.circularDrawable -import bou.amine.apps.readerforselfossv2.android.utils.openItemUrl import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.service.AppSettingsService @@ -23,11 +21,9 @@ import org.kodein.di.instance class ItemListAdapter( override val app: Activity, - override var items: ArrayList, - override val updateItems: (ArrayList) -> Unit, + override val items: ArrayList, ) : ItemsAdapter() { - private lateinit var binding: ListItemBinding - private val c: Context = app.baseContext + override lateinit var binding: ListItemBinding override val di: DI by closestDI(app) override val repository: Repository by instance() @@ -46,17 +42,9 @@ class ItemListAdapter( position: Int, ) { with(holder) { - val itm = items[holder.bindingAdapterPosition] + val itm = items[position] - binding.root.setOnClickListener { - repository.setReaderItems(items) - c.openItemUrl( - holder.bindingAdapterPosition, - items[holder.bindingAdapterPosition].getLinkDecoded(), - appSettingsService.isArticleViewerEnabled(), - app, - ) - } + openLink(binding, position) binding.title.text = itm.title.getHtmlDecoded() @@ -83,7 +71,5 @@ class ItemListAdapter( } } - override fun getItemCount(): Int = items.size - inner class ViewHolder(val binding: ListItemBinding) : RecyclerView.ViewHolder(binding.root) } diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt index aa6b545a..1ff89ed2 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt @@ -1,10 +1,14 @@ package bou.amine.apps.readerforselfossv2.android.adapters import android.app.Activity +import android.content.Context import android.graphics.Color +import android.util.Log import android.widget.TextView import androidx.recyclerview.widget.RecyclerView +import androidx.viewbinding.ViewBinding import bou.amine.apps.readerforselfossv2.android.R +import bou.amine.apps.readerforselfossv2.android.utils.openItemUrl import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.service.AppSettingsService @@ -16,16 +20,18 @@ import kotlinx.coroutines.launch import org.kodein.di.DIAware abstract class ItemsAdapter : RecyclerView.Adapter(), DIAware { - abstract var items: ArrayList + abstract val items: ArrayList abstract val repository: Repository + abstract val binding: ViewBinding abstract val appSettingsService: AppSettingsService abstract val app: Activity - abstract val updateItems: (ArrayList) -> Unit + + protected val c: Context get() = app.baseContext fun updateAllItems(items: ArrayList) { - this.items = items + this.items.clear() + this.items.addAll(items) notifyDataSetChanged() - updateItems(this.items) } private fun unmarkSnackbar( @@ -70,6 +76,22 @@ abstract class ItemsAdapter : RecyclerView.Adapte s.show() } + protected fun openLink(holderBinding: ViewBinding, position: Int) { + holderBinding.root.setOnClickListener { + Log.d( + "RecyclerViewDebug", + "Clicked position: $position, Item ID: ${items[position].id}" + ) + repository.setReaderItems(items) + c.openItemUrl( + position, + items[position].getLinkDecoded(), + appSettingsService.isArticleViewerEnabled(), + app, + ) + } + } + fun handleItemAtIndex(position: Int) { if (items[position].unread) { readItemAtIndex(items[position], position) @@ -90,7 +112,6 @@ abstract class ItemsAdapter : RecyclerView.Adapte items.remove(item) notifyItemRemoved(position) notifyItemRangeChanged(position, itemCount) - updateItems(items) } else { notifyItemChanged(position) } @@ -119,13 +140,17 @@ abstract class ItemsAdapter : RecyclerView.Adapte ) { items.add(position, item) notifyItemInserted(position) - updateItems(items) } fun addItemsAtEnd(newItems: List) { val oldSize = items.size items.addAll(newItems) notifyItemRangeInserted(oldSize, newItems.size) - updateItems(items) + } + + override fun getItemCount(): Int = items.size + + override fun getItemId(position: Int): Long { + return items[position].id.toLong() } } From 3a33cb4510ad333b5a1b21929a6259f0ad6dc59f Mon Sep 17 00:00:00 2001 From: davidoskky Date: Wed, 20 Nov 2024 01:28:47 +0100 Subject: [PATCH 2/2] Provide method to update items in the home Removed in the previous commit, the item adapter accepts a method to update the articles list in the home page. Renamed the method to make its objective more clear. Removed a debugging log. Reverted change to function name. --- .../readerforselfossv2/android/HomeActivity.kt | 18 +++++++++++++++--- .../android/adapters/ItemCardAdapter.kt | 3 ++- .../android/adapters/ItemListAdapter.kt | 3 ++- .../android/adapters/ItemsAdapter.kt | 16 ++++++---------- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt index 88f5a40c..a60904ee 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt @@ -13,7 +13,11 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.SearchView import androidx.core.view.doOnNextLayout import androidx.lifecycle.lifecycleScope -import androidx.recyclerview.widget.* +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.ItemTouchHelper +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.StaggeredGridLayoutManager import androidx.work.Constraints import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.PeriodicWorkRequestBuilder @@ -477,13 +481,17 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar ItemCardAdapter( this, items, - ) + ) { + updateItems(it) + } } else { recyclerAdapter = ItemListAdapter( this, items, - ) + ) { + updateItems(it) + } binding.recyclerView.addItemDecoration( DividerItemDecoration( @@ -656,6 +664,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar else -> repository.badgeUnread.value // if !elementsShown then unread are fetched. } + private fun updateItems(adapterItems: ArrayList) { + items = adapterItems + } + private fun handleRecurringTask() { if (appSettingsService.isPeriodicRefreshEnabled()) { val myConstraints = diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemCardAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemCardAdapter.kt index a8565a57..2175fd7b 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemCardAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemCardAdapter.kt @@ -31,6 +31,7 @@ import org.kodein.di.instance class ItemCardAdapter( override val app: Activity, override val items: ArrayList, + override val updateHomeItems: (ArrayList) -> Unit, ) : ItemsAdapter() { override lateinit var binding: CardItemBinding private val imageMaxHeight: Int = @@ -82,7 +83,7 @@ class ItemCardAdapter( val itm = items[position] handleClickListeners(binding, position) - openLink(binding, position) + handleLinkOpening(binding, position) binding.favButton.isSelected = itm.starred if (appSettingsService.getPublicAccess()) { diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt index 098433b5..ac43bd62 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt @@ -22,6 +22,7 @@ import org.kodein.di.instance class ItemListAdapter( override val app: Activity, override val items: ArrayList, + override val updateHomeItems: (ArrayList) -> Unit, ) : ItemsAdapter() { override lateinit var binding: ListItemBinding @@ -44,7 +45,7 @@ class ItemListAdapter( with(holder) { val itm = items[position] - openLink(binding, position) + handleLinkOpening(binding, position) binding.title.text = itm.title.getHtmlDecoded() diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt index 1ff89ed2..e3ea18c5 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt @@ -3,7 +3,6 @@ package bou.amine.apps.readerforselfossv2.android.adapters import android.app.Activity import android.content.Context import android.graphics.Color -import android.util.Log import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding @@ -25,12 +24,14 @@ abstract class ItemsAdapter : RecyclerView.Adapte abstract val binding: ViewBinding abstract val appSettingsService: AppSettingsService abstract val app: Activity + abstract val updateHomeItems: (ArrayList) -> Unit protected val c: Context get() = app.baseContext fun updateAllItems(items: ArrayList) { this.items.clear() this.items.addAll(items) + updateHomeItems(items) notifyDataSetChanged() } @@ -76,12 +77,8 @@ abstract class ItemsAdapter : RecyclerView.Adapte s.show() } - protected fun openLink(holderBinding: ViewBinding, position: Int) { + protected fun handleLinkOpening(holderBinding: ViewBinding, position: Int) { holderBinding.root.setOnClickListener { - Log.d( - "RecyclerViewDebug", - "Clicked position: $position, Item ID: ${items[position].id}" - ) repository.setReaderItems(items) c.openItemUrl( position, @@ -112,6 +109,7 @@ abstract class ItemsAdapter : RecyclerView.Adapte items.remove(item) notifyItemRemoved(position) notifyItemRangeChanged(position, itemCount) + updateHomeItems(items) } else { notifyItemChanged(position) } @@ -140,17 +138,15 @@ abstract class ItemsAdapter : RecyclerView.Adapte ) { items.add(position, item) notifyItemInserted(position) + updateHomeItems(items) } fun addItemsAtEnd(newItems: List) { val oldSize = items.size items.addAll(newItems) notifyItemRangeInserted(oldSize, newItems.size) + updateHomeItems(items) } override fun getItemCount(): Int = items.size - - override fun getItemId(position: Int): Long { - return items[position].id.toLong() - } }