Skip to content

Commit e7014d8

Browse files
authored
login: smoother settings storage detail list adapting (fixes #13583) (#13509)
1 parent 85dae05 commit e7014d8

2 files changed

Lines changed: 52 additions & 16 deletions

File tree

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ android {
1212
applicationId "org.ole.planet.myplanet"
1313
minSdk = 26
1414
targetSdk = 36
15-
versionCode = 5580
16-
versionName = "0.55.80"
15+
versionCode = 5581
16+
versionName = "0.55.81"
1717
ndkVersion = '26.3.11579264'
1818
vectorDrawables.useSupportLibrary = true
1919
}

app/src/main/java/org/ole/planet/myplanet/ui/settings/StorageCategoryDetailFragment.kt

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)