fix(app/tasks): download progress
- fix crashes
This commit is contained in:
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ data class Task(
|
||||
}
|
||||
|
||||
class PendingTask(
|
||||
val taskId: Long,
|
||||
val task: Task
|
||||
) {
|
||||
private val listeners = mutableListOf<PendingTaskListener>()
|
||||
|
||||
@@ -89,7 +89,7 @@ class TaskManager(
|
||||
updateTask(taskId, task)
|
||||
}
|
||||
|
||||
val pendingTask = PendingTask(task)
|
||||
val pendingTask = PendingTask(taskId, task)
|
||||
activeTasks[taskId] = pendingTask
|
||||
return pendingTask
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user