feat: show upload progress for attachments and tweaks

Signed-off-by: Infi <wingit@geist.ga>
This commit is contained in:
Infi 2023-06-12 19:35:05 +02:00
parent 75c7ec95a4
commit 21c2556eb1
3 changed files with 73 additions and 36 deletions

View File

@ -1,15 +1,27 @@
package chat.revolt.components.screens.chat package chat.revolt.components.screens.chat
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.* import androidx.compose.material3.Icon
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ProgressIndicatorDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@ -23,44 +35,57 @@ import java.io.File
fun AttachmentManager( fun AttachmentManager(
attachments: List<FileArgs>, attachments: List<FileArgs>,
uploading: Boolean, uploading: Boolean,
uploadProgress: Float = 0f,
onRemove: (FileArgs) -> Unit, onRemove: (FileArgs) -> Unit,
) { ) {
Row( val animatedProgress by animateFloatAsState(
targetValue = uploadProgress,
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
label = "Upload progress"
)
Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp)) .background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp))
.horizontalScroll(rememberScrollState())
.padding(horizontal = 8.dp, vertical = 4.dp)
) { ) {
AnimatedVisibility(uploading) { Row(
CircularProgressIndicator( modifier = Modifier
modifier = Modifier.padding(4.dp), .horizontalScroll(rememberScrollState())
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.7f) .padding(horizontal = 8.dp, vertical = 4.dp)
) ) {
attachments.forEach { attachment ->
Row(
modifier = Modifier
.padding(4.dp)
.clip(MaterialTheme.shapes.small)
.clickable {
onRemove(attachment)
}
.background(
color = MaterialTheme.colorScheme.background,
shape = MaterialTheme.shapes.small
)
.padding(8.dp)
) {
Text(attachment.filename, maxLines = 1)
Spacer(modifier = Modifier.width(4.dp))
Icon(
Icons.Default.Close,
contentDescription = stringResource(R.string.remove_attachment_alt)
)
}
Spacer(modifier = Modifier.width(8.dp))
}
} }
attachments.forEach { attachment -> AnimatedVisibility(visible = uploading) {
Row( LinearProgressIndicator(
progress = animatedProgress,
modifier = Modifier modifier = Modifier
.padding(4.dp) .fillMaxWidth()
.clip(MaterialTheme.shapes.small) )
.clickable {
onRemove(attachment)
}
.background(
color = MaterialTheme.colorScheme.background,
shape = MaterialTheme.shapes.small
)
.padding(8.dp)
) {
Text(attachment.filename, maxLines = 1)
Spacer(modifier = Modifier.width(4.dp))
Icon(
Icons.Default.Close,
contentDescription = stringResource(R.string.remove_attachment_alt)
)
}
Spacer(modifier = Modifier.width(8.dp))
} }
} }
} }

View File

@ -385,7 +385,8 @@ fun ChannelScreen(
AttachmentManager( AttachmentManager(
attachments = viewModel.pendingAttachments, attachments = viewModel.pendingAttachments,
uploading = viewModel.isSendingMessage, uploading = viewModel.isSendingMessage,
onRemove = { viewModel.pendingAttachments.remove(it) } uploadProgress = viewModel.pendingUploadProgress,
onRemove = { viewModel.pendingAttachments.remove(it) },
) )
} }

View File

@ -2,10 +2,11 @@ package chat.revolt.screens.chat.views.channel
import android.util.Log import android.util.Log
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshots.SnapshotStateList import androidx.compose.runtime.toMutableStateList
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import chat.revolt.api.RevoltAPI import chat.revolt.api.RevoltAPI
@ -55,9 +56,11 @@ class ChannelScreenViewModel : ViewModel() {
var pendingReplies = mutableStateListOf<SendMessageReply>() var pendingReplies = mutableStateListOf<SendMessageReply>()
var pendingAttachments = mutableStateListOf<FileArgs>() var pendingAttachments = mutableStateListOf<FileArgs>()
var pendingUploadProgress by mutableFloatStateOf(0f)
private fun popAttachmentBatch() { private fun popAttachmentBatch() {
pendingAttachments = pendingAttachments =
pendingAttachments.drop(MAX_ATTACHMENTS_PER_MESSAGE) as SnapshotStateList<FileArgs> pendingAttachments.drop(MAX_ATTACHMENTS_PER_MESSAGE).toMutableStateList()
} }
private fun setRenderableMessages(messages: List<Message>) { private fun setRenderableMessages(messages: List<Message>) {
@ -142,14 +145,20 @@ class ChannelScreenViewModel : ViewModel() {
viewModelScope.launch { viewModelScope.launch {
val attachmentIds = arrayListOf<String>() val attachmentIds = arrayListOf<String>()
val takenAttachments = pendingAttachments.take(MAX_ATTACHMENTS_PER_MESSAGE)
val totalTaken = takenAttachments.size
pendingAttachments.take(MAX_ATTACHMENTS_PER_MESSAGE).forEach { takenAttachments.forEachIndexed { index, it ->
try { try {
val id = uploadToAutumn( val id = uploadToAutumn(
it.file, it.file,
it.filename, it.filename,
"attachments", "attachments",
ContentType.parse(it.contentType) ContentType.parse(it.contentType),
onProgress = { current, total ->
pendingUploadProgress =
((current.toFloat() / total.toFloat()) / totalTaken.toFloat()) + (index.toFloat() / totalTaken.toFloat())
}
) )
Log.d("ChannelScreen", "Uploaded attachment with id $id") Log.d("ChannelScreen", "Uploaded attachment with id $id")
attachmentIds.add(id) attachmentIds.add(id)
@ -168,6 +177,8 @@ class ChannelScreenViewModel : ViewModel() {
pendingMessageContent = "" pendingMessageContent = ""
hasNoMoreMessages = false hasNoMoreMessages = false
isSendingMessage = false
pendingUploadProgress = 0f
popAttachmentBatch() popAttachmentBatch()
clearInReplyTo() clearInReplyTo()
} }