Fix persistence bug

This commit is contained in:
Luna712 2024-07-06 17:44:13 -06:00 committed by GitHub
parent 1164177384
commit c5d2b30bc8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 92 additions and 13 deletions

View file

@ -91,6 +91,7 @@ class DownloadAdapter(
) : ListAdapter<VisualDownloadCached, DownloadAdapter.DownloadViewHolder>(DiffCallback()) { ) : ListAdapter<VisualDownloadCached, DownloadAdapter.DownloadViewHolder>(DiffCallback()) {
private var showDeleteCheckbox: Boolean = false private var showDeleteCheckbox: Boolean = false
private val selectedIds: HashMap<Int, Boolean> = HashMap()
companion object { companion object {
private const val VIEW_TYPE_HEADER = 0 private const val VIEW_TYPE_HEADER = 0
@ -125,6 +126,14 @@ class DownloadAdapter(
if (card.child != null) { if (card.child != null) {
handleChildDownload(card, formattedSize) handleChildDownload(card, formattedSize)
} else handleParentDownload(card, formattedSize) } else handleParentDownload(card, formattedSize)
deleteCheckbox.apply {
isVisible = showDeleteCheckbox
isChecked = selectedIds[card.data.id] == true
setOnCheckedChangeListener { _, isChecked ->
selectedChangedCallback.invoke(card.data.id, card.data.name, isChecked)
}
}
} }
} }
@ -170,7 +179,7 @@ class DownloadAdapter(
deleteCheckbox.apply { deleteCheckbox.apply {
isVisible = showDeleteCheckbox isVisible = showDeleteCheckbox
isChecked = card.selected isChecked = selectedIds[card.data.id] == true
setOnCheckedChangeListener { _, isChecked -> setOnCheckedChangeListener { _, isChecked ->
selectedChangedCallback.invoke(card.data.id, card.data.name, isChecked) selectedChangedCallback.invoke(card.data.id, card.data.name, isChecked)
} }
@ -183,7 +192,7 @@ class DownloadAdapter(
formattedSize: String formattedSize: String
) { ) {
downloadButton.isVisible = false downloadButton.isVisible = false
downloadHeaderGotoChild.isVisible = true downloadHeaderGotoChild.isVisible = !showDeleteCheckbox
try { try {
downloadHeaderInfo.text = downloadHeaderInfo.context.getString(R.string.extra_info_format).format( downloadHeaderInfo.text = downloadHeaderInfo.context.getString(R.string.extra_info_format).format(
@ -199,6 +208,14 @@ class DownloadAdapter(
episodeHolder.setOnClickListener { episodeHolder.setOnClickListener {
headerClickCallback.invoke(DownloadHeaderClickEvent(DOWNLOAD_ACTION_GO_TO_CHILD, card.data)) headerClickCallback.invoke(DownloadHeaderClickEvent(DOWNLOAD_ACTION_GO_TO_CHILD, card.data))
} }
deleteCheckbox.apply {
isVisible = showDeleteCheckbox
isChecked = selectedIds[card.data.id] == true
setOnCheckedChangeListener { _, isChecked ->
selectedChangedCallback.invoke(card.data.id, card.data.name, isChecked)
}
}
} }
private fun bindChild(card: VisualDownloadChildCached?) { private fun bindChild(card: VisualDownloadChildCached?) {
@ -279,6 +296,29 @@ class DownloadAdapter(
notifyItemRangeChanged(0, itemCount) notifyItemRangeChanged(0, itemCount)
} }
fun updateSelectedItem(id: Int, isSelected: Boolean) {
if (isSelected) {
selectedIds[id] = true
} else selectedIds.remove(id)
val position = currentList.indexOfFirst { it.data.id == id }
if (position != -1) {
notifyItemChanged(position)
}
}
fun updateSelectedItems(updatedList: List<VisualDownloadCached>) {
updatedList.forEach { item ->
val position = currentList.indexOfFirst { it.data.id == item.data.id }
if (position != -1) {
notifyItemChanged(position)
}
}
}
fun clearSelectedIds() {
selectedIds.clear()
}
class DiffCallback : DiffUtil.ItemCallback<VisualDownloadCached>() { class DiffCallback : DiffUtil.ItemCallback<VisualDownloadCached>() {
override fun areItemsTheSame(oldItem: VisualDownloadCached, newItem: VisualDownloadCached): Boolean { override fun areItemsTheSame(oldItem: VisualDownloadCached, newItem: VisualDownloadCached): Boolean {
return oldItem.data.id == newItem.data.id return oldItem.data.id == newItem.data.id

View file

@ -93,7 +93,7 @@ class DownloadFragment : Fragment() {
// We always want fresh selections // We always want fresh selections
// when navigating to downloads // when navigating to downloads
downloadsViewModel.resetSelected() downloadsViewModel.clearSelectedIds()
observe(downloadsViewModel.headerCards) { observe(downloadsViewModel.headerCards) {
(binding?.downloadList?.adapter as? DownloadAdapter)?.submitList(it) (binding?.downloadList?.adapter as? DownloadAdapter)?.submitList(it)
@ -128,6 +128,10 @@ class DownloadFragment : Fragment() {
downloadClickEvent.data.id, downloadClickEvent.data.id,
it it
) )
(binding?.downloadList?.adapter as? DownloadAdapter)?.updateSelectedItem(
downloadClickEvent.data.id,
true
)
} }
} }
}, },
@ -196,7 +200,7 @@ class DownloadFragment : Fragment() {
context?.let { ctx -> downloadsViewModel.handleMultiDelete(ctx) } context?.let { ctx -> downloadsViewModel.handleMultiDelete(ctx) }
} }
binding?.downloadDeleteToolbar?.btnCancel?.setOnClickListener { binding?.downloadDeleteToolbar?.btnCancel?.setOnClickListener {
downloadsViewModel.resetSelected() downloadsViewModel.clearSelectedIds()
} }
adapter?.setDeleteCheckboxVisibility(true) adapter?.setDeleteCheckboxVisibility(true)
@ -206,16 +210,41 @@ class DownloadFragment : Fragment() {
// Make sure we don't display it early // Make sure we don't display it early
!downloadsViewModel.headerCards.value.isNullOrEmpty() && !downloadsViewModel.headerCards.value.isNullOrEmpty() &&
downloadsViewModel.usedBytes.value?.let { it > 0 } == true downloadsViewModel.usedBytes.value?.let { it > 0 } == true
adapter?.setDeleteCheckboxVisibility(false) adapter?.setDeleteCheckboxVisibility(false)
adapter?.clearSelectedIds()
downloadsViewModel.clearSelectedIds()
} }
} }
private fun updateSelectedState(selected: HashMap<Int, String>) { private fun updateSelectedState(selected: HashMap<Int, String>) {
val currentList = downloadsViewModel.headerCards.value ?: return if (selected == downloadsViewModel.selectedIds.value) return
val updatedList = currentList.map { header -> val currentSelectedIds = downloadsViewModel.selectedIds.value ?: HashMap()
header.copy(selected = selected.keys.contains(header.data.id))
// Remove deselected items
currentSelectedIds.keys.retainAll(selected.keys)
// Add newly selected items
selected.forEach { (id, name) ->
currentSelectedIds[id] = name
} }
(binding?.downloadList?.adapter as? DownloadAdapter)?.submitList(updatedList)
downloadsViewModel.setSelected(currentSelectedIds)
val currentList = downloadsViewModel.headerCards.value ?: return
val updatedList = currentList.map { item ->
item.copy(selected = currentSelectedIds.containsKey(item.data.id))
}
val adapter = binding?.downloadList?.adapter as? DownloadAdapter
// Pass the IDs of the updated list to the ViewModel for filtering
val updatedIds = updatedList.filter { it.selected }.map { it.data.id }.toSet()
downloadsViewModel.filterSelectedIds(updatedIds)
val selectedItems = updatedList.filter { it.selected }
adapter?.updateSelectedItems(selectedItems)
} }
private fun setUpDownloadDeleteListener() { private fun setUpDownloadDeleteListener() {

View file

@ -45,29 +45,39 @@ class DownloadViewModel : ViewModel() {
private var previousVisual: List<VisualDownloadHeaderCached>? = null private var previousVisual: List<VisualDownloadHeaderCached>? = null
fun addSelected(id: Int, name: String) { fun addSelected(id: Int, name: String) {
_selectedIds.value?.let { selectedIds -> selectedIds.value?.let { selectedIds ->
selectedIds[id] = name selectedIds[id] = name
_selectedIds.postValue(selectedIds) _selectedIds.postValue(selectedIds)
} }
} }
fun setSelected(selected: HashMap<Int, String>) {
_selectedIds.postValue(selected)
}
fun removeSelected(id: Int) { fun removeSelected(id: Int) {
_selectedIds.value?.let { selectedIds -> selectedIds.value?.let { selectedIds ->
selectedIds.remove(id) selectedIds.remove(id)
_selectedIds.postValue(selectedIds) _selectedIds.postValue(selectedIds)
} }
} }
fun resetSelected() { fun filterSelectedIds(updatedIds: Set<Int>) {
val currentSelectedIds = _selectedIds.value ?: return
val filteredIds = currentSelectedIds.filterKeys { updatedIds.contains(it) }
_selectedIds.value = HashMap(filteredIds)
}
fun clearSelectedIds() {
_selectedIds.postValue(HashMap()) _selectedIds.postValue(HashMap())
} }
private fun getSelectedIds(): List<Int> { private fun getSelectedIds(): List<Int> {
return _selectedIds.value?.keys?.toList() ?: emptyList() return selectedIds.value?.keys?.toList() ?: emptyList()
} }
private fun getSelectedNames(): List<String> { private fun getSelectedNames(): List<String> {
return _selectedIds.value?.values?.toList() ?: emptyList() return selectedIds.value?.values?.toList() ?: emptyList()
} }
fun updateList(context: Context) = viewModelScope.launchSafe { fun updateList(context: Context) = viewModelScope.launchSafe {