@@ -43,15 +43,15 @@ class StorageCategoryDetailFragment : BottomSheetDialogFragment() {
4343 private var extensions: Set <String > = emptySet()
4444 private var allKnownExtensions: Set <String > = emptySet()
4545
46- private data class ResourceItem (
46+ data class ResourceItem (
4747 val resourceId : String ,
4848 val title : String ,
4949 val files : List <File >,
5050 val totalSizeBytes : Long ,
51- var isChecked : Boolean = false
51+ val isChecked : Boolean = false
5252 )
5353
54- private val items = mutableListOf <ResourceItem >()
54+ private var items: List <ResourceItem > = emptyList ()
5555 private lateinit var adapter: ResourceAdapter
5656
5757 companion object {
@@ -106,14 +106,20 @@ class StorageCategoryDetailFragment : BottomSheetDialogFragment() {
106106 binding.categoryTitle.text = categoryLabel
107107 binding.closeButton.setOnClickListener { dismiss() }
108108
109- adapter = ResourceAdapter ()
109+ adapter = ResourceAdapter { clickedItem ->
110+ items = items.map {
111+ if (it.resourceId == clickedItem.resourceId) it.copy(isChecked = ! it.isChecked) else it
112+ }
113+ adapter.submitList(items)
114+ updateSelectionState()
115+ }
110116 binding.resourceList.layoutManager = LinearLayoutManager (requireContext())
111117 binding.resourceList.adapter = adapter
112118
113119 binding.selectAllRow.setOnClickListener {
114120 val allChecked = items.all { it.isChecked }
115- items.forEach { it.isChecked = ! allChecked }
116- adapter.notifyDataSetChanged( )
121+ items = items.map { it.copy( isChecked = ! allChecked) }
122+ adapter.submitList(items )
117123 updateSelectionState()
118124 }
119125
@@ -150,9 +156,8 @@ class StorageCategoryDetailFragment : BottomSheetDialogFragment() {
150156 return @launch
151157 }
152158
153- items.clear()
154- items.addAll(loaded)
155- adapter.notifyDataSetChanged()
159+ items = loaded
160+ adapter.submitList(items)
156161
157162 binding.resourceList.visibility = View .VISIBLE
158163 binding.actionButtons.visibility = View .VISIBLE
@@ -193,6 +198,7 @@ class StorageCategoryDetailFragment : BottomSheetDialogFragment() {
193198 }
194199
195200 private fun updateSelectionState () {
201+ if (_binding == null ) return
196202 val checkedCount = items.count { it.isChecked }
197203 val allChecked = checkedCount == items.size && items.isNotEmpty()
198204
@@ -217,6 +223,7 @@ class StorageCategoryDetailFragment : BottomSheetDialogFragment() {
217223 }
218224
219225 private fun deleteItems (toDelete : List <ResourceItem >) {
226+ if (_binding == null ) return
220227 binding.deleteSelectedButton.isEnabled = false
221228 binding.deleteAllButton.isEnabled = false
222229
@@ -248,7 +255,9 @@ class StorageCategoryDetailFragment : BottomSheetDialogFragment() {
248255 }
249256 }
250257
251- inner class ResourceAdapter : RecyclerView .Adapter <ResourceAdapter .ViewHolder >() {
258+ inner class ResourceAdapter (
259+ private val onItemClicked : (ResourceItem ) -> Unit
260+ ) : androidx.recyclerview.widget.ListAdapter<ResourceItem, ResourceAdapter.ViewHolder>(ResourceDiffCallback ()) {
252261
253262 inner class ViewHolder (val binding : ItemDownloadedResourceBinding ) :
254263 RecyclerView .ViewHolder (binding.root)
@@ -261,18 +270,45 @@ class StorageCategoryDetailFragment : BottomSheetDialogFragment() {
261270 }
262271
263272 override fun onBindViewHolder (holder : ViewHolder , position : Int ) {
264- val item = items[ position]
273+ val item = getItem( position)
265274 holder.binding.resourceTitle.text = item.title
266275 holder.binding.resourceSize.text = FileUtils .formatSize(requireContext(), item.totalSizeBytes)
267276 holder.binding.checkBox.isChecked = item.isChecked
268277 holder.binding.root.setOnClickListener {
269- item.isChecked = ! item.isChecked
278+ onItemClicked(item)
279+ }
280+ holder.binding.checkBox.setOnClickListener {
281+ onItemClicked(item)
282+ }
283+ }
284+
285+ override fun onBindViewHolder (holder : ViewHolder , position : Int , payloads : MutableList <Any >) {
286+ if (payloads.isNotEmpty()) {
287+ val item = getItem(position)
270288 holder.binding.checkBox.isChecked = item.isChecked
271- updateSelectionState()
289+ holder.binding.root.setOnClickListener { onItemClicked(item) }
290+ holder.binding.checkBox.setOnClickListener { onItemClicked(item) }
291+ } else {
292+ super .onBindViewHolder(holder, position, payloads)
272293 }
273294 }
295+ }
296+
297+ private class ResourceDiffCallback : androidx.recyclerview.widget.DiffUtil .ItemCallback <ResourceItem >() {
298+ override fun areItemsTheSame (oldItem : ResourceItem , newItem : ResourceItem ): Boolean {
299+ return oldItem.resourceId == newItem.resourceId
300+ }
274301
275- override fun getItemCount () = items.size
302+ override fun areContentsTheSame (oldItem : ResourceItem , newItem : ResourceItem ): Boolean {
303+ return oldItem == newItem
304+ }
305+
306+ override fun getChangePayload (oldItem : ResourceItem , newItem : ResourceItem ): Any? {
307+ if (oldItem.copy(isChecked = newItem.isChecked) == newItem) {
308+ return true
309+ }
310+ return null
311+ }
276312 }
277313
278314 override fun onDestroyView () {
0 commit comments