mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Fix potential race condition and update lists faster
This commit is contained in:
parent
b42337c605
commit
ca469093f8
4 changed files with 40 additions and 26 deletions
app/src/main/java/com/lagradost/cloudstream3
|
@ -133,9 +133,7 @@ class DownloadChildFragment : Fragment() {
|
|||
{ click ->
|
||||
if (click.action == DOWNLOAD_ACTION_DELETE_FILE) {
|
||||
context?.let { ctx ->
|
||||
downloadsViewModel.handleSingleDelete(ctx, click.data.id) {
|
||||
downloadsViewModel.updateChildList(ctx, folder)
|
||||
}
|
||||
downloadsViewModel.handleSingleDelete(ctx, click.data.id)
|
||||
}
|
||||
} else handleDownloadClick(click)
|
||||
},
|
||||
|
@ -170,10 +168,7 @@ class DownloadChildFragment : Fragment() {
|
|||
|
||||
binding?.btnDelete?.setOnClickListener {
|
||||
context?.let { ctx ->
|
||||
downloadsViewModel.handleMultiDelete(ctx) {
|
||||
arguments?.getString("folder")
|
||||
?.let { folder -> downloadsViewModel.updateChildList(ctx, folder) }
|
||||
}
|
||||
downloadsViewModel.handleMultiDelete(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -180,9 +180,7 @@ class DownloadFragment : Fragment() {
|
|||
{ click ->
|
||||
if (click.action == DOWNLOAD_ACTION_DELETE_FILE) {
|
||||
context?.let { ctx ->
|
||||
downloadsViewModel.handleSingleDelete(ctx, click.data.id) {
|
||||
downloadsViewModel.updateList(ctx)
|
||||
}
|
||||
downloadsViewModel.handleSingleDelete(ctx, click.data.id)
|
||||
}
|
||||
} else handleDownloadClick(click)
|
||||
},
|
||||
|
@ -253,9 +251,7 @@ class DownloadFragment : Fragment() {
|
|||
|
||||
binding?.btnDelete?.setOnClickListener {
|
||||
context?.let { ctx ->
|
||||
downloadsViewModel.handleMultiDelete(ctx) {
|
||||
downloadsViewModel.updateList(ctx)
|
||||
}
|
||||
downloadsViewModel.handleMultiDelete(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -251,6 +251,17 @@ class DownloadViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun removeItems(idsToRemove: List<Int>) = viewModelScope.launchSafe {
|
||||
val currentHeaders = headerCards.value ?: emptyList()
|
||||
val currentChildren = childCards.value ?: emptyList()
|
||||
|
||||
val updatedHeaders = currentHeaders.filter { !idsToRemove.contains(it.data.id) }
|
||||
val updatedChildren = currentChildren.filter { !idsToRemove.contains(it.data.id) }
|
||||
|
||||
_headerCards.postValue(updatedHeaders)
|
||||
_childCards.postValue(updatedChildren)
|
||||
}
|
||||
|
||||
private fun updateStorageStats(visual: List<VisualDownloadCached.Header>) {
|
||||
try {
|
||||
val stat = StatFs(Environment.getExternalStorageDirectory().path)
|
||||
|
@ -267,25 +278,21 @@ class DownloadViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
fun handleMultiDelete(
|
||||
context: Context,
|
||||
onDeleteConfirm: () -> Unit
|
||||
) = viewModelScope.launchSafe {
|
||||
fun handleMultiDelete(context: Context) = viewModelScope.launchSafe {
|
||||
val selectedItemsList = getSelectedItemsData() ?: emptyList()
|
||||
val deleteData = processSelectedItems(context, selectedItemsList)
|
||||
val message = buildDeleteMessage(context, deleteData)
|
||||
showDeleteConfirmationDialog(context, message, deleteData.ids, onDeleteConfirm)
|
||||
showDeleteConfirmationDialog(context, message, deleteData.ids, deleteData.parentIds)
|
||||
}
|
||||
|
||||
fun handleSingleDelete(
|
||||
context: Context,
|
||||
itemId: Int,
|
||||
onDeleteConfirm: () -> Unit
|
||||
itemId: Int
|
||||
) = viewModelScope.launchSafe {
|
||||
val itemData = getItemDataFromId(itemId)
|
||||
val deleteData = processSelectedItems(context, itemData)
|
||||
val message = buildDeleteMessage(context, deleteData)
|
||||
showDeleteConfirmationDialog(context, message, deleteData.ids, onDeleteConfirm)
|
||||
showDeleteConfirmationDialog(context, message, deleteData.ids, deleteData.parentIds)
|
||||
}
|
||||
|
||||
private fun getSelectedItemsData(): List<VisualDownloadCached>? {
|
||||
|
@ -312,6 +319,7 @@ class DownloadViewModel : ViewModel() {
|
|||
selectedItemsList: List<VisualDownloadCached>
|
||||
): DeleteData {
|
||||
val ids = mutableListOf<Int>()
|
||||
val parentIds = mutableListOf<Int>()
|
||||
val seriesNames = mutableListOf<String>()
|
||||
val names = mutableListOf<String>()
|
||||
var parentName: String? = null
|
||||
|
@ -329,6 +337,7 @@ class DownloadViewModel : ViewModel() {
|
|||
.filter { it.parentId == item.data.id }
|
||||
.map { it.id }
|
||||
ids.addAll(episodes)
|
||||
parentIds.add(item.data.id)
|
||||
|
||||
val episodeInfo = "${item.data.name} (${item.totalDownloads} ${
|
||||
context.resources.getQuantityString(
|
||||
|
@ -361,7 +370,7 @@ class DownloadViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
return DeleteData(ids, seriesNames, names, parentName)
|
||||
return DeleteData(ids, parentIds, seriesNames, names, parentName)
|
||||
}
|
||||
|
||||
private fun buildDeleteMessage(
|
||||
|
@ -402,7 +411,7 @@ class DownloadViewModel : ViewModel() {
|
|||
context: Context,
|
||||
message: String,
|
||||
ids: List<Int>,
|
||||
onDeleteConfirm: () -> Unit
|
||||
parentIds: List<Int>
|
||||
) {
|
||||
val builder = AlertDialog.Builder(context)
|
||||
val dialogClickListener =
|
||||
|
@ -410,9 +419,13 @@ class DownloadViewModel : ViewModel() {
|
|||
when (which) {
|
||||
DialogInterface.BUTTON_POSITIVE -> {
|
||||
viewModelScope.launchSafe {
|
||||
deleteFilesAndUpdateSettings(context, ids, this)
|
||||
setIsMultiDeleteState(false)
|
||||
onDeleteConfirm.invoke()
|
||||
deleteFilesAndUpdateSettings(context, ids, this) { successfulIds ->
|
||||
// We always remove parent because if we are deleting from here
|
||||
// and we have it as non-empty, it was triggered on
|
||||
// parent header card
|
||||
removeItems(successfulIds + parentIds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -438,6 +451,7 @@ class DownloadViewModel : ViewModel() {
|
|||
|
||||
private data class DeleteData(
|
||||
val ids: List<Int>,
|
||||
val parentIds: List<Int>,
|
||||
val seriesNames: List<String>,
|
||||
val names: List<String>,
|
||||
val parentName: String?
|
||||
|
|
|
@ -1710,7 +1710,12 @@ object VideoDownloadManager {
|
|||
}
|
||||
}
|
||||
|
||||
fun deleteFilesAndUpdateSettings(context: Context, ids: List<Int>, scope: CoroutineScope) {
|
||||
fun deleteFilesAndUpdateSettings(
|
||||
context: Context,
|
||||
ids: List<Int>,
|
||||
scope: CoroutineScope,
|
||||
onComplete: (List<Int>) -> Unit = {}
|
||||
) {
|
||||
scope.launchSafe(Dispatchers.IO) {
|
||||
val deleteJobs = ids.map { id ->
|
||||
async {
|
||||
|
@ -1719,7 +1724,9 @@ object VideoDownloadManager {
|
|||
}
|
||||
val results = deleteJobs.awaitAll()
|
||||
|
||||
val successfulDeletes = results.filter { it.second }.map { it.first }
|
||||
val failedDeletes = results.filterNot { it.second }
|
||||
|
||||
if (failedDeletes.isNotEmpty()) {
|
||||
failedDeletes.forEach { (id, _) ->
|
||||
// TODO show a toast if some failed?
|
||||
|
@ -1728,6 +1735,8 @@ object VideoDownloadManager {
|
|||
} else {
|
||||
Log.i("FileDeletion", "All files deleted successfully")
|
||||
}
|
||||
|
||||
onComplete.invoke(successfulDeletes)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue