mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Faster remove downloads from adapter after deletion
This commit is contained in:
parent
145c42f1c8
commit
3e62382d3e
4 changed files with 92 additions and 49 deletions
app/src/main/java/com/lagradost/cloudstream3/ui/download
|
@ -251,6 +251,15 @@ class DownloadAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
fun removeItem(itemId: Int) {
|
||||
val currentList = currentList.toMutableList()
|
||||
val position = currentList.indexOfFirst { it.data.id == itemId }
|
||||
if (position != -1) {
|
||||
currentList.removeAt(position)
|
||||
notifyItemRemoved(position)
|
||||
}
|
||||
}
|
||||
|
||||
class DiffCallback : DiffUtil.ItemCallback<VisualDownloadCached>() {
|
||||
override fun areItemsTheSame(oldItem: VisualDownloadCached, newItem: VisualDownloadCached): Boolean {
|
||||
return oldItem.data.id == newItem.data.id
|
||||
|
|
|
@ -127,11 +127,11 @@ class DownloadChildFragment : Fragment() {
|
|||
|
||||
private fun setUpDownloadDeleteListener(folder: String) {
|
||||
downloadDeleteEventListener = { id: Int ->
|
||||
val list = (binding?.downloadChildList?.adapter as? DownloadAdapter)?.currentList
|
||||
if (list != null) {
|
||||
if (list.any { it.data.id == id }) {
|
||||
updateList(folder)
|
||||
}
|
||||
val adapter = binding?.downloadChildList?.adapter as? DownloadAdapter
|
||||
val list = adapter?.currentList
|
||||
if (list?.any { it.data.id == id }) {
|
||||
adapter.removeItem(id)
|
||||
updateList(folder)
|
||||
}
|
||||
}
|
||||
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent += it }
|
||||
|
|
|
@ -170,9 +170,11 @@ class DownloadFragment : Fragment() {
|
|||
|
||||
private fun setUpDownloadDeleteListener() {
|
||||
downloadDeleteEventListener = { id ->
|
||||
val list = (binding?.downloadList?.adapter as? DownloadAdapter)?.currentList
|
||||
val adapter = binding?.downloadList?.adapter as? DownloadAdapter
|
||||
val list = adapter?.currentList
|
||||
if (list?.any { it.data.id == id } == true) {
|
||||
context?.let { downloadsViewModel.updateList(it) }
|
||||
adapter.removeItem(id)
|
||||
downloadsViewModel.removeItem(id)
|
||||
}
|
||||
}
|
||||
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent += it }
|
||||
|
|
|
@ -35,74 +35,96 @@ class DownloadViewModel : ViewModel() {
|
|||
|
||||
private var previousVisual: List<VisualDownloadHeaderCached>? = null
|
||||
|
||||
fun updateList(context: Context) = viewModelScope.launchSafe {
|
||||
val children = withContext(Dispatchers.IO) {
|
||||
context.getKeys(DOWNLOAD_EPISODE_CACHE)
|
||||
.mapNotNull { context.getKey<VideoDownloadHelper.DownloadEpisodeCached>(it) }
|
||||
.distinctBy { it.id } // Remove duplicates
|
||||
}
|
||||
fun updateList(context: Context) {
|
||||
viewModelScope.launchSafe {
|
||||
try {
|
||||
val children = withContext(Dispatchers.IO) {
|
||||
fetchDownloadedEpisodes(context)
|
||||
}
|
||||
val visual = withContext(Dispatchers.IO) {
|
||||
generateVisualList(context, children)
|
||||
}
|
||||
|
||||
// parentId : bytes
|
||||
if (visual != previousVisual) {
|
||||
previousVisual = visual
|
||||
updateBytes(context, visual)
|
||||
_headerCards.postValue(visual)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchDownloadedEpisodes(context: Context): List<VideoDownloadHelper.DownloadEpisodeCached> {
|
||||
return context.getKeys(DOWNLOAD_EPISODE_CACHE)
|
||||
.mapNotNull { context.getKey<VideoDownloadHelper.DownloadEpisodeCached>(it) }
|
||||
.distinctBy { it.id }
|
||||
}
|
||||
|
||||
private suspend fun generateVisualList(
|
||||
context: Context,
|
||||
children: List<VideoDownloadHelper.DownloadEpisodeCached>
|
||||
): List<VisualDownloadHeaderCached> {
|
||||
val totalBytesUsedByChild = HashMap<Int, Long>()
|
||||
// parentId : bytes
|
||||
val currentBytesUsedByChild = HashMap<Int, Long>()
|
||||
// parentId : downloadsCount
|
||||
val totalDownloads = HashMap<Int, Int>()
|
||||
|
||||
// Gets all children downloads
|
||||
withContext(Dispatchers.IO) {
|
||||
children.forEach { c ->
|
||||
val childFile = getDownloadFileInfoAndUpdateSettings(context, c.id) ?: return@forEach
|
||||
val childFile =
|
||||
getDownloadFileInfoAndUpdateSettings(context, c.id) ?: return@forEach
|
||||
|
||||
if (childFile.fileLength <= 1) return@forEach
|
||||
|
||||
val len = childFile.totalBytes
|
||||
val flen = childFile.fileLength
|
||||
|
||||
totalBytesUsedByChild[c.parentId] = totalBytesUsedByChild[c.parentId]?.plus(len) ?: len
|
||||
currentBytesUsedByChild[c.parentId] = currentBytesUsedByChild[c.parentId]?.plus(flen) ?: flen
|
||||
totalBytesUsedByChild[c.parentId] =
|
||||
totalBytesUsedByChild[c.parentId]?.plus(len) ?: len
|
||||
currentBytesUsedByChild[c.parentId] =
|
||||
currentBytesUsedByChild[c.parentId]?.plus(flen) ?: flen
|
||||
totalDownloads[c.parentId] = totalDownloads[c.parentId]?.plus(1) ?: 1
|
||||
}
|
||||
}
|
||||
|
||||
val cached = withContext(Dispatchers.IO) { // Won't fetch useless keys
|
||||
totalDownloads.entries.filter { it.value > 0 }.mapNotNull {
|
||||
return totalDownloads.entries
|
||||
.filter { it.value > 0 }
|
||||
.mapNotNull {
|
||||
context.getKey<VideoDownloadHelper.DownloadHeaderCached>(
|
||||
DOWNLOAD_HEADER_CACHE,
|
||||
it.key.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val visual = withContext(Dispatchers.IO) {
|
||||
cached.mapNotNull {
|
||||
.mapNotNull {
|
||||
val downloads = totalDownloads[it.id] ?: 0
|
||||
val bytes = totalBytesUsedByChild[it.id] ?: 0
|
||||
val currentBytes = currentBytesUsedByChild[it.id] ?: 0
|
||||
if (bytes <= 0 || downloads <= 0) return@mapNotNull null
|
||||
val movieEpisode =
|
||||
if (!it.type.isMovieType()) null
|
||||
|
||||
if (bytes <= 0 || downloads <= 0) null
|
||||
else {
|
||||
val movieEpisode = if (!it.type.isMovieType()) null
|
||||
else context.getKey<VideoDownloadHelper.DownloadEpisodeCached>(
|
||||
DOWNLOAD_EPISODE_CACHE,
|
||||
getFolderName(it.id.toString(), it.id.toString())
|
||||
)
|
||||
VisualDownloadHeaderCached(
|
||||
currentBytes = currentBytes,
|
||||
totalBytes = bytes,
|
||||
data = it,
|
||||
child = movieEpisode,
|
||||
currentOngoingDownloads = 0,
|
||||
totalDownloads = downloads,
|
||||
)
|
||||
}.sortedBy {
|
||||
(it.child?.episode ?: 0) + (it.child?.season?.times(10000) ?: 0)
|
||||
} // Episode sorting by episode, lowest to highest
|
||||
}
|
||||
|
||||
// Only update list if different from the previous one to prevent duplicate initialization
|
||||
if (visual != previousVisual) {
|
||||
previousVisual = visual
|
||||
VisualDownloadHeaderCached(
|
||||
currentBytes = currentBytes,
|
||||
totalBytes = bytes,
|
||||
data = it,
|
||||
child = movieEpisode,
|
||||
currentOngoingDownloads = 0,
|
||||
totalDownloads = downloads,
|
||||
)
|
||||
}
|
||||
}
|
||||
.sortedBy { (it.child?.episode ?: 0) + (it.child?.season?.times(10000) ?: 0) }
|
||||
}
|
||||
|
||||
try {
|
||||
private suspend fun updateBytes(context: Context, visual: List<VisualDownloadHeaderCached>) {
|
||||
try {
|
||||
withContext(Dispatchers.IO) {
|
||||
val stat = StatFs(Environment.getExternalStorageDirectory().path)
|
||||
val localBytesAvailable = stat.availableBytes
|
||||
val localTotalBytes = stat.blockSizeLong * stat.blockCountLong
|
||||
|
@ -111,12 +133,22 @@ class DownloadViewModel : ViewModel() {
|
|||
_usedBytes.postValue(localTotalBytes - localBytesAvailable - localDownloadedBytes)
|
||||
_availableBytes.postValue(localBytesAvailable)
|
||||
_downloadBytes.postValue(localDownloadedBytes)
|
||||
} catch (t: Throwable) {
|
||||
_downloadBytes.postValue(0)
|
||||
logError(t)
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
_downloadBytes.postValue(0)
|
||||
logError(t)
|
||||
}
|
||||
}
|
||||
|
||||
_headerCards.postValue(visual)
|
||||
fun removeItem(itemId: Int) {
|
||||
val visual = _headerCards.value?.toMutableList() ?: mutableListOf()
|
||||
val position = visual.indexOfFirst { it.data.id == itemId }
|
||||
if (position != -1) {
|
||||
visual.removeAt(position)
|
||||
if (visual != previousVisual) {
|
||||
previousVisual = visual
|
||||
_headerCards.postValue(visual)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue