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
|
@ -133,9 +133,7 @@ class DownloadChildFragment : Fragment() {
|
||||||
{ click ->
|
{ click ->
|
||||||
if (click.action == DOWNLOAD_ACTION_DELETE_FILE) {
|
if (click.action == DOWNLOAD_ACTION_DELETE_FILE) {
|
||||||
context?.let { ctx ->
|
context?.let { ctx ->
|
||||||
downloadsViewModel.handleSingleDelete(ctx, click.data.id) {
|
downloadsViewModel.handleSingleDelete(ctx, click.data.id)
|
||||||
downloadsViewModel.updateChildList(ctx, folder)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else handleDownloadClick(click)
|
} else handleDownloadClick(click)
|
||||||
},
|
},
|
||||||
|
@ -170,10 +168,7 @@ class DownloadChildFragment : Fragment() {
|
||||||
|
|
||||||
binding?.btnDelete?.setOnClickListener {
|
binding?.btnDelete?.setOnClickListener {
|
||||||
context?.let { ctx ->
|
context?.let { ctx ->
|
||||||
downloadsViewModel.handleMultiDelete(ctx) {
|
downloadsViewModel.handleMultiDelete(ctx)
|
||||||
arguments?.getString("folder")
|
|
||||||
?.let { folder -> downloadsViewModel.updateChildList(ctx, folder) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -180,9 +180,7 @@ class DownloadFragment : Fragment() {
|
||||||
{ click ->
|
{ click ->
|
||||||
if (click.action == DOWNLOAD_ACTION_DELETE_FILE) {
|
if (click.action == DOWNLOAD_ACTION_DELETE_FILE) {
|
||||||
context?.let { ctx ->
|
context?.let { ctx ->
|
||||||
downloadsViewModel.handleSingleDelete(ctx, click.data.id) {
|
downloadsViewModel.handleSingleDelete(ctx, click.data.id)
|
||||||
downloadsViewModel.updateList(ctx)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else handleDownloadClick(click)
|
} else handleDownloadClick(click)
|
||||||
},
|
},
|
||||||
|
@ -253,9 +251,7 @@ class DownloadFragment : Fragment() {
|
||||||
|
|
||||||
binding?.btnDelete?.setOnClickListener {
|
binding?.btnDelete?.setOnClickListener {
|
||||||
context?.let { ctx ->
|
context?.let { ctx ->
|
||||||
downloadsViewModel.handleMultiDelete(ctx) {
|
downloadsViewModel.handleMultiDelete(ctx)
|
||||||
downloadsViewModel.updateList(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>) {
|
private fun updateStorageStats(visual: List<VisualDownloadCached.Header>) {
|
||||||
try {
|
try {
|
||||||
val stat = StatFs(Environment.getExternalStorageDirectory().path)
|
val stat = StatFs(Environment.getExternalStorageDirectory().path)
|
||||||
|
@ -267,25 +278,21 @@ class DownloadViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleMultiDelete(
|
fun handleMultiDelete(context: Context) = viewModelScope.launchSafe {
|
||||||
context: Context,
|
|
||||||
onDeleteConfirm: () -> Unit
|
|
||||||
) = viewModelScope.launchSafe {
|
|
||||||
val selectedItemsList = getSelectedItemsData() ?: emptyList()
|
val selectedItemsList = getSelectedItemsData() ?: emptyList()
|
||||||
val deleteData = processSelectedItems(context, selectedItemsList)
|
val deleteData = processSelectedItems(context, selectedItemsList)
|
||||||
val message = buildDeleteMessage(context, deleteData)
|
val message = buildDeleteMessage(context, deleteData)
|
||||||
showDeleteConfirmationDialog(context, message, deleteData.ids, onDeleteConfirm)
|
showDeleteConfirmationDialog(context, message, deleteData.ids, deleteData.parentIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleSingleDelete(
|
fun handleSingleDelete(
|
||||||
context: Context,
|
context: Context,
|
||||||
itemId: Int,
|
itemId: Int
|
||||||
onDeleteConfirm: () -> Unit
|
|
||||||
) = viewModelScope.launchSafe {
|
) = viewModelScope.launchSafe {
|
||||||
val itemData = getItemDataFromId(itemId)
|
val itemData = getItemDataFromId(itemId)
|
||||||
val deleteData = processSelectedItems(context, itemData)
|
val deleteData = processSelectedItems(context, itemData)
|
||||||
val message = buildDeleteMessage(context, deleteData)
|
val message = buildDeleteMessage(context, deleteData)
|
||||||
showDeleteConfirmationDialog(context, message, deleteData.ids, onDeleteConfirm)
|
showDeleteConfirmationDialog(context, message, deleteData.ids, deleteData.parentIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSelectedItemsData(): List<VisualDownloadCached>? {
|
private fun getSelectedItemsData(): List<VisualDownloadCached>? {
|
||||||
|
@ -312,6 +319,7 @@ class DownloadViewModel : ViewModel() {
|
||||||
selectedItemsList: List<VisualDownloadCached>
|
selectedItemsList: List<VisualDownloadCached>
|
||||||
): DeleteData {
|
): DeleteData {
|
||||||
val ids = mutableListOf<Int>()
|
val ids = mutableListOf<Int>()
|
||||||
|
val parentIds = mutableListOf<Int>()
|
||||||
val seriesNames = mutableListOf<String>()
|
val seriesNames = mutableListOf<String>()
|
||||||
val names = mutableListOf<String>()
|
val names = mutableListOf<String>()
|
||||||
var parentName: String? = null
|
var parentName: String? = null
|
||||||
|
@ -329,6 +337,7 @@ class DownloadViewModel : ViewModel() {
|
||||||
.filter { it.parentId == item.data.id }
|
.filter { it.parentId == item.data.id }
|
||||||
.map { it.id }
|
.map { it.id }
|
||||||
ids.addAll(episodes)
|
ids.addAll(episodes)
|
||||||
|
parentIds.add(item.data.id)
|
||||||
|
|
||||||
val episodeInfo = "${item.data.name} (${item.totalDownloads} ${
|
val episodeInfo = "${item.data.name} (${item.totalDownloads} ${
|
||||||
context.resources.getQuantityString(
|
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(
|
private fun buildDeleteMessage(
|
||||||
|
@ -402,7 +411,7 @@ class DownloadViewModel : ViewModel() {
|
||||||
context: Context,
|
context: Context,
|
||||||
message: String,
|
message: String,
|
||||||
ids: List<Int>,
|
ids: List<Int>,
|
||||||
onDeleteConfirm: () -> Unit
|
parentIds: List<Int>
|
||||||
) {
|
) {
|
||||||
val builder = AlertDialog.Builder(context)
|
val builder = AlertDialog.Builder(context)
|
||||||
val dialogClickListener =
|
val dialogClickListener =
|
||||||
|
@ -410,9 +419,13 @@ class DownloadViewModel : ViewModel() {
|
||||||
when (which) {
|
when (which) {
|
||||||
DialogInterface.BUTTON_POSITIVE -> {
|
DialogInterface.BUTTON_POSITIVE -> {
|
||||||
viewModelScope.launchSafe {
|
viewModelScope.launchSafe {
|
||||||
deleteFilesAndUpdateSettings(context, ids, this)
|
|
||||||
setIsMultiDeleteState(false)
|
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(
|
private data class DeleteData(
|
||||||
val ids: List<Int>,
|
val ids: List<Int>,
|
||||||
|
val parentIds: List<Int>,
|
||||||
val seriesNames: List<String>,
|
val seriesNames: List<String>,
|
||||||
val names: List<String>,
|
val names: List<String>,
|
||||||
val parentName: 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) {
|
scope.launchSafe(Dispatchers.IO) {
|
||||||
val deleteJobs = ids.map { id ->
|
val deleteJobs = ids.map { id ->
|
||||||
async {
|
async {
|
||||||
|
@ -1719,7 +1724,9 @@ object VideoDownloadManager {
|
||||||
}
|
}
|
||||||
val results = deleteJobs.awaitAll()
|
val results = deleteJobs.awaitAll()
|
||||||
|
|
||||||
|
val successfulDeletes = results.filter { it.second }.map { it.first }
|
||||||
val failedDeletes = results.filterNot { it.second }
|
val failedDeletes = results.filterNot { it.second }
|
||||||
|
|
||||||
if (failedDeletes.isNotEmpty()) {
|
if (failedDeletes.isNotEmpty()) {
|
||||||
failedDeletes.forEach { (id, _) ->
|
failedDeletes.forEach { (id, _) ->
|
||||||
// TODO show a toast if some failed?
|
// TODO show a toast if some failed?
|
||||||
|
@ -1728,6 +1735,8 @@ object VideoDownloadManager {
|
||||||
} else {
|
} else {
|
||||||
Log.i("FileDeletion", "All files deleted successfully")
|
Log.i("FileDeletion", "All files deleted successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onComplete.invoke(successfulDeletes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue