3
3
Fork 1
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:
Luna712 2024-07-17 16:01:51 -06:00 committed by GitHub
parent b42337c605
commit ca469093f8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 40 additions and 26 deletions
app/src/main/java/com/lagradost/cloudstream3

View file

@ -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)
}
}

View file

@ -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)
}
}

View file

@ -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?

View file

@ -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)
}
}