mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Add a deselect all button and move child handling to view model
This commit is contained in:
parent
0a564b6f33
commit
1f37db3c63
7 changed files with 105 additions and 32 deletions
|
@ -315,13 +315,11 @@ class DownloadAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
|
||||||
fun setIsMultiDeleteState(value: Boolean) {
|
fun setIsMultiDeleteState(value: Boolean) {
|
||||||
if (isMultiDeleteState == value) return
|
if (isMultiDeleteState == value) return
|
||||||
isMultiDeleteState = value
|
isMultiDeleteState = value
|
||||||
if (!value) {
|
if (!value) {
|
||||||
selectedIds.clear()
|
clearSelectedItems()
|
||||||
notifyDataSetChanged()
|
|
||||||
} else notifyItemRangeChanged(0, itemCount)
|
} else notifyItemRangeChanged(0, itemCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,6 +333,12 @@ class DownloadAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
fun clearSelectedItems() {
|
||||||
|
selectedIds.clear()
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
private fun toggleIsChecked(checkbox: CheckBox, item: VisualDownloadCached) {
|
private fun toggleIsChecked(checkbox: CheckBox, item: VisualDownloadCached) {
|
||||||
val isChecked = !checkbox.isChecked
|
val isChecked = !checkbox.isChecked
|
||||||
checkbox.isChecked = isChecked
|
checkbox.isChecked = isChecked
|
||||||
|
|
|
@ -60,31 +60,6 @@ class DownloadChildFragment : Fragment() {
|
||||||
return localBinding.root
|
return localBinding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateList(folder: String) = main {
|
|
||||||
context?.let { ctx ->
|
|
||||||
val data = withContext(Dispatchers.IO) { ctx.getKeys(folder) }
|
|
||||||
val eps = withContext(Dispatchers.IO) {
|
|
||||||
data.mapNotNull { key ->
|
|
||||||
context?.getKey<VideoDownloadHelper.DownloadEpisodeCached>(key)
|
|
||||||
}.mapNotNull {
|
|
||||||
val info = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(ctx, it.id)
|
|
||||||
?: return@mapNotNull null
|
|
||||||
VisualDownloadCached.Child(
|
|
||||||
currentBytes = info.fileLength,
|
|
||||||
totalBytes = info.totalBytes,
|
|
||||||
data = it,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}.sortedBy { it.data.episode + (it.data.season ?: 0) * 100000 }
|
|
||||||
if (eps.isEmpty()) {
|
|
||||||
activity?.onBackPressedDispatcher?.onBackPressed()
|
|
||||||
return@main
|
|
||||||
}
|
|
||||||
|
|
||||||
(binding?.downloadChildList?.adapter as? DownloadAdapter)?.submitList(eps)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var downloadDeleteEventListener: ((Int) -> Unit)? = null
|
private var downloadDeleteEventListener: ((Int) -> Unit)? = null
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
@ -113,6 +88,14 @@ class DownloadChildFragment : Fragment() {
|
||||||
setAppBarNoScrollFlagsOnTV()
|
setAppBarNoScrollFlagsOnTV()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
observe(downloadsViewModel.childCards) {
|
||||||
|
if (it.isEmpty()) {
|
||||||
|
activity?.onBackPressedDispatcher?.onBackPressed()
|
||||||
|
return@observe
|
||||||
|
}
|
||||||
|
|
||||||
|
(binding?.downloadChildList?.adapter as? DownloadAdapter)?.submitList(it)
|
||||||
|
}
|
||||||
observe(downloadsViewModel.isMultiDeleteState) { isMultiDeleteState ->
|
observe(downloadsViewModel.isMultiDeleteState) { isMultiDeleteState ->
|
||||||
val adapter = binding?.downloadChildList?.adapter as? DownloadAdapter
|
val adapter = binding?.downloadChildList?.adapter as? DownloadAdapter
|
||||||
adapter?.setIsMultiDeleteState(isMultiDeleteState)
|
adapter?.setIsMultiDeleteState(isMultiDeleteState)
|
||||||
|
@ -158,7 +141,7 @@ class DownloadChildFragment : Fragment() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateList(folder)
|
downloadsViewModel.updateChildList(requireContext(), folder)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSelectedChange(selected: MutableList<VisualDownloadCached>) {
|
private fun handleSelectedChange(selected: MutableList<VisualDownloadCached>) {
|
||||||
|
@ -174,11 +157,22 @@ class DownloadChildFragment : Fragment() {
|
||||||
downloadsViewModel.setIsMultiDeleteState(false)
|
downloadsViewModel.setIsMultiDeleteState(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding?.btnSelectAll?.isVisible = !downloadsViewModel.isAllSelected()
|
||||||
|
binding?.btnDeselectAll?.isVisible = downloadsViewModel.isAllSelected()
|
||||||
|
|
||||||
binding?.btnSelectAll?.setOnClickListener {
|
binding?.btnSelectAll?.setOnClickListener {
|
||||||
(binding?.downloadChildList?.adapter as? DownloadAdapter)?.selectAllItems()
|
(binding?.downloadChildList?.adapter as? DownloadAdapter)?.selectAllItems()
|
||||||
downloadsViewModel.selectAllItems()
|
downloadsViewModel.selectAllItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding?.btnDeselectAll?.setOnClickListener {
|
||||||
|
(binding?.downloadChildList?.adapter as? DownloadAdapter)?.clearSelectedItems()
|
||||||
|
downloadsViewModel.clearSelectedItems()
|
||||||
|
|
||||||
|
binding?.btnSelectAll?.isVisible = true
|
||||||
|
binding?.btnDeselectAll?.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
downloadsViewModel.setIsMultiDeleteState(true)
|
downloadsViewModel.setIsMultiDeleteState(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,7 +181,7 @@ class DownloadChildFragment : Fragment() {
|
||||||
downloadDeleteEventListener = { id: Int ->
|
downloadDeleteEventListener = { id: Int ->
|
||||||
val list = (binding?.downloadChildList?.adapter as? DownloadAdapter)?.currentList
|
val list = (binding?.downloadChildList?.adapter as? DownloadAdapter)?.currentList
|
||||||
if (list?.any { it.data.id == id } == true) {
|
if (list?.any { it.data.id == id } == true) {
|
||||||
updateList(folder)
|
context?.let { downloadsViewModel.updateChildList(it, folder) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent += it }
|
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent += it }
|
||||||
|
|
|
@ -213,11 +213,22 @@ class DownloadFragment : Fragment() {
|
||||||
downloadsViewModel.setIsMultiDeleteState(false)
|
downloadsViewModel.setIsMultiDeleteState(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding?.btnSelectAll?.isVisible = !downloadsViewModel.isAllSelected()
|
||||||
|
binding?.btnDeselectAll?.isVisible = downloadsViewModel.isAllSelected()
|
||||||
|
|
||||||
binding?.btnSelectAll?.setOnClickListener {
|
binding?.btnSelectAll?.setOnClickListener {
|
||||||
(binding?.downloadList?.adapter as? DownloadAdapter)?.selectAllItems()
|
(binding?.downloadList?.adapter as? DownloadAdapter)?.selectAllItems()
|
||||||
downloadsViewModel.selectAllItems()
|
downloadsViewModel.selectAllItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding?.btnDeselectAll?.setOnClickListener {
|
||||||
|
(binding?.downloadList?.adapter as? DownloadAdapter)?.clearSelectedItems()
|
||||||
|
downloadsViewModel.clearSelectedItems()
|
||||||
|
|
||||||
|
binding?.btnSelectAll?.isVisible = true
|
||||||
|
binding?.btnDeselectAll?.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
downloadsViewModel.setIsMultiDeleteState(true)
|
downloadsViewModel.setIsMultiDeleteState(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,10 @@ class DownloadViewModel : ViewModel() {
|
||||||
MutableLiveData<List<VisualDownloadCached.Header>>().apply { listOf<VisualDownloadCached.Header>() }
|
MutableLiveData<List<VisualDownloadCached.Header>>().apply { listOf<VisualDownloadCached.Header>() }
|
||||||
val headerCards: LiveData<List<VisualDownloadCached.Header>> = _headerCards
|
val headerCards: LiveData<List<VisualDownloadCached.Header>> = _headerCards
|
||||||
|
|
||||||
|
private val _childCards =
|
||||||
|
MutableLiveData<List<VisualDownloadCached.Child>>().apply { listOf<VisualDownloadCached.Child>() }
|
||||||
|
val childCards: LiveData<List<VisualDownloadCached.Child>> = _childCards
|
||||||
|
|
||||||
private val _usedBytes = MutableLiveData<Long>()
|
private val _usedBytes = MutableLiveData<Long>()
|
||||||
val usedBytes: LiveData<Long> = _usedBytes
|
val usedBytes: LiveData<Long> = _usedBytes
|
||||||
|
|
||||||
|
@ -46,7 +50,7 @@ class DownloadViewModel : ViewModel() {
|
||||||
private val _selectedItems = MutableLiveData<MutableList<VisualDownloadCached>>(mutableListOf())
|
private val _selectedItems = MutableLiveData<MutableList<VisualDownloadCached>>(mutableListOf())
|
||||||
val selectedItems: LiveData<MutableList<VisualDownloadCached>> = _selectedItems
|
val selectedItems: LiveData<MutableList<VisualDownloadCached>> = _selectedItems
|
||||||
|
|
||||||
private var previousVisual: List<VisualDownloadCached.Header>? = null
|
private var previousVisual: List<VisualDownloadCached>? = null
|
||||||
|
|
||||||
fun setIsMultiDeleteState(value: Boolean) {
|
fun setIsMultiDeleteState(value: Boolean) {
|
||||||
_isMultiDeleteState.postValue(value)
|
_isMultiDeleteState.postValue(value)
|
||||||
|
@ -69,7 +73,8 @@ class DownloadViewModel : ViewModel() {
|
||||||
|
|
||||||
fun selectAllItems() {
|
fun selectAllItems() {
|
||||||
val currentSelected = selectedItems.value ?: mutableListOf()
|
val currentSelected = selectedItems.value ?: mutableListOf()
|
||||||
val items = headerCards.value ?: return
|
val items = (headerCards.value ?: emptyList()) + (childCards.value ?: emptyList())
|
||||||
|
if(items.isEmpty()) return
|
||||||
items.forEach { item ->
|
items.forEach { item ->
|
||||||
if (!currentSelected.contains(item)) {
|
if (!currentSelected.contains(item)) {
|
||||||
currentSelected.add(item)
|
currentSelected.add(item)
|
||||||
|
@ -82,6 +87,22 @@ class DownloadViewModel : ViewModel() {
|
||||||
_selectedItems.postValue(mutableListOf())
|
_selectedItems.postValue(mutableListOf())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isAllSelected(): Boolean {
|
||||||
|
val currentSelected = selectedItems.value ?: return false
|
||||||
|
val headerItems = headerCards.value
|
||||||
|
val childItems = childCards.value
|
||||||
|
|
||||||
|
val isAllHeadersSelected = headerItems != null &&
|
||||||
|
headerItems.count() == currentSelected.count() &&
|
||||||
|
headerItems.containsAll(currentSelected)
|
||||||
|
|
||||||
|
val isAllChildrenSelected = childItems != null &&
|
||||||
|
childItems.count() == currentSelected.count() &&
|
||||||
|
childItems.containsAll(currentSelected)
|
||||||
|
|
||||||
|
return isAllHeadersSelected || isAllChildrenSelected
|
||||||
|
}
|
||||||
|
|
||||||
fun updateList(context: Context) = viewModelScope.launchSafe {
|
fun updateList(context: Context) = viewModelScope.launchSafe {
|
||||||
val children = withContext(Dispatchers.IO) {
|
val children = withContext(Dispatchers.IO) {
|
||||||
context.getKeys(DOWNLOAD_EPISODE_CACHE)
|
context.getKeys(DOWNLOAD_EPISODE_CACHE)
|
||||||
|
@ -153,6 +174,28 @@ class DownloadViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateChildList(context: Context, folder: String) = viewModelScope.launchSafe {
|
||||||
|
val data = withContext(Dispatchers.IO) { context.getKeys(folder) }
|
||||||
|
val visual = withContext(Dispatchers.IO) {
|
||||||
|
data.mapNotNull { key ->
|
||||||
|
context.getKey<VideoDownloadHelper.DownloadEpisodeCached>(key)
|
||||||
|
}.mapNotNull {
|
||||||
|
val info = getDownloadFileInfoAndUpdateSettings(context, it.id)
|
||||||
|
?: return@mapNotNull null
|
||||||
|
VisualDownloadCached.Child(
|
||||||
|
currentBytes = info.fileLength,
|
||||||
|
totalBytes = info.totalBytes,
|
||||||
|
data = it,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.sortedBy { it.data.episode + (it.data.season ?: 0) * 100000 }
|
||||||
|
|
||||||
|
if (previousVisual != visual) {
|
||||||
|
previousVisual = visual
|
||||||
|
_childCards.postValue(visual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateStorageStats(visual: List<VisualDownloadCached.Header>) {
|
private fun updateStorageStats(visual: List<VisualDownloadCached.Header>) {
|
||||||
try {
|
try {
|
||||||
val stat = StatFs(Environment.getExternalStorageDirectory().path)
|
val stat = StatFs(Environment.getExternalStorageDirectory().path)
|
||||||
|
|
|
@ -70,6 +70,16 @@
|
||||||
android:text="@string/select_all"
|
android:text="@string/select_all"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:layout_marginEnd="8dp" />
|
android:layout_marginEnd="8dp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnDeselectAll"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:text="@string/deselect_all"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:visibility="gone" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
|
|
@ -73,6 +73,16 @@
|
||||||
android:text="@string/select_all"
|
android:text="@string/select_all"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:layout_marginEnd="8dp" />
|
android:layout_marginEnd="8dp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnDeselectAll"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:text="@string/deselect_all"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:visibility="gone" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
|
|
@ -153,6 +153,7 @@
|
||||||
<string name="downloads_empty">There are currently no downloads.</string>
|
<string name="downloads_empty">There are currently no downloads.</string>
|
||||||
<string name="offline_file">Available for watching offline</string>
|
<string name="offline_file">Available for watching offline</string>
|
||||||
<string name="select_all">Select All</string>
|
<string name="select_all">Select All</string>
|
||||||
|
<string name="deselect_all">Deselect All</string>
|
||||||
<string name="update_started">Update Started</string>
|
<string name="update_started">Update Started</string>
|
||||||
<string name="stream">Network stream</string>
|
<string name="stream">Network stream</string>
|
||||||
<string name="open_local_video">Open local video</string>
|
<string name="open_local_video">Open local video</string>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue