commit 7938871086d68501335c86aec1baf4d7e3663e32
parent bbcaab4e75b4aac792907802532aacdb4a188cf4
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Sun, 29 Oct 2023 03:06:11 +0100

fix(app/tasks): download progress
- fix crashes

Diffstat:
Mapp/src/main/kotlin/me/rhunk/snapenhance/download/DownloadProcessor.kt | 7++++++-
Mapp/src/main/kotlin/me/rhunk/snapenhance/task/PendingTask.kt | 1+
Mapp/src/main/kotlin/me/rhunk/snapenhance/task/TaskManager.kt | 2+-
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/TasksSection.kt | 39++++++++++++++++++++-------------------
4 files changed, 28 insertions(+), 21 deletions(-)

diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/download/DownloadProcessor.kt b/app/src/main/kotlin/me/rhunk/snapenhance/download/DownloadProcessor.kt @@ -180,12 +180,14 @@ class DownloadProcessor ( private fun downloadInputMedias(pendingTask: PendingTask, downloadRequest: DownloadRequest) = runBlocking { val jobs = mutableListOf<Job>() val downloadedMedias = mutableMapOf<InputMedia, File>() + var totalSize = 1L + val inputMediaDownloadedBytes = mutableMapOf<InputMedia, Long>() val inputMediaProgress = ConcurrentHashMap<InputMedia, String>() fun updateDownloadProgress() { pendingTask.updateProgress( inputMediaProgress.values.joinToString("\n"), - progress = (jobs.filter { it.isActive }.size.toDouble() / jobs.size.toDouble() * 100.0).toInt() + progress = (inputMediaDownloadedBytes.values.sum() * 100 / totalSize).toInt().coerceIn(0, 100) ) } @@ -207,6 +209,7 @@ class DownloadProcessor ( while (decryptedInputStream.read(buffer).also { read = it } != -1) { outputStream.write(buffer, 0, read) totalRead += read + inputMediaDownloadedBytes[inputMedia] = totalRead if (totalRead - lastTotalRead > 1024 * 1024) { setProgress("${totalRead / 1024}KB/${estimatedSize / 1024}KB") lastTotalRead = totalRead @@ -219,6 +222,7 @@ class DownloadProcessor ( when (inputMedia.type) { DownloadMediaType.PROTO_MEDIA -> { RemoteMediaResolver.downloadBoltMedia(Base64.UrlSafe.decode(inputMedia.content), decryptionCallback = { it }, resultCallback = { inputStream, length -> + totalSize += length handleInputStream(inputStream, estimatedSize = length) }) } @@ -227,6 +231,7 @@ class DownloadProcessor ( requestMethod = "GET" setRequestProperty("User-Agent", Constants.USER_AGENT) connect() + totalSize += contentLength.toLong() handleInputStream(inputStream, estimatedSize = contentLength.toLong()) } } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/task/PendingTask.kt b/app/src/main/kotlin/me/rhunk/snapenhance/task/PendingTask.kt @@ -61,6 +61,7 @@ data class Task( } class PendingTask( + val taskId: Long, val task: Task ) { private val listeners = mutableListOf<PendingTaskListener>() diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/task/TaskManager.kt b/app/src/main/kotlin/me/rhunk/snapenhance/task/TaskManager.kt @@ -89,7 +89,7 @@ class TaskManager( updateTask(taskId, task) } - val pendingTask = PendingTask(task) + val pendingTask = PendingTask(taskId, task) activeTasks[taskId] = pendingTask return pendingTask } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/TasksSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/TasksSection.kt @@ -25,7 +25,7 @@ import me.rhunk.snapenhance.ui.manager.Section import me.rhunk.snapenhance.ui.util.OnLifecycleEvent class TasksSection : Section() { - private lateinit var activeTasks: MutableMap<Long, PendingTask> + private var activeTasks by mutableStateOf(listOf<PendingTask>()) private lateinit var recentTasks: MutableList<Task> @Composable @@ -48,14 +48,14 @@ class TasksSection : Section() { onClick = { context.taskManager.clearAllTasks() recentTasks.clear() - activeTasks.toList().forEach { + activeTasks.forEach { runCatching { - it.second.cancel() + it.cancel() }.onFailure { throwable -> - context.log.error("Failed to cancel task ${it.first}", throwable) + context.log.error("Failed to cancel task $it", throwable) } - activeTasks.remove(it.first) } + activeTasks = listOf() context.taskManager.getActiveTasks().clear() showConfirmDialog = false } @@ -90,7 +90,11 @@ class TasksSection : Section() { taskProgressLabel = label taskProgress = progress } - ).also { pendingTask?.addListener(it) }} + ) } + + LaunchedEffect(Unit) { + pendingTask?.addListener(listener) + } DisposableEffect(Unit) { onDispose { @@ -163,7 +167,6 @@ class TasksSection : Section() { override fun Content() { val scrollState = rememberLazyListState() val scope = rememberCoroutineScope() - activeTasks = remember { mutableStateMapOf() } recentTasks = remember { mutableStateListOf() } var lastFetchedTaskId: Long? by remember { mutableStateOf(null) } @@ -172,28 +175,27 @@ class TasksSection : Section() { val tasks = context.taskManager.fetchStoredTasks(lastFetchedTaskId ?: Long.MAX_VALUE) if (tasks.isNotEmpty()) { lastFetchedTaskId = tasks.keys.last() - recentTasks.addAll(tasks.filter { !activeTasks.containsKey(it.key) }.values) + scope.launch { + val activeTaskIds = activeTasks.map { it.taskId } + recentTasks.addAll(tasks.filter { it.key !in activeTaskIds }.values) + } } } } fun fetchActiveTasks() { - scope.launch { - activeTasks.clear() - activeTasks.putAll(context.taskManager.getActiveTasks()) - } + activeTasks = context.taskManager.getActiveTasks().values.sortedByDescending { it.taskId }.toMutableList() } - SideEffect { + LaunchedEffect(Unit) { fetchActiveTasks() } OnLifecycleEvent { _, event -> - when (event) { - Lifecycle.Event.ON_RESUME -> { + if (event == Lifecycle.Event.ON_RESUME) { + scope.launch { fetchActiveTasks() } - else -> {} } } @@ -213,11 +215,10 @@ class TasksSection : Section() { } } } - items(activeTasks.size) { index -> - val pendingTask = activeTasks.values.elementAt(index) + items(activeTasks, key = { it.task.hash }) {pendingTask -> TaskCard(modifier = Modifier.padding(8.dp), pendingTask.task, pendingTask = pendingTask) } - items(recentTasks) { task -> + items(recentTasks, key = { it.hash }) { task -> TaskCard(modifier = Modifier.padding(8.dp), task) } item {