android: add media gallery and account checklist progress
This commit is contained in:
@@ -51,8 +51,10 @@ import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.safeDrawing
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import coil.compose.AsyncImage
|
||||
@@ -624,6 +626,8 @@ private fun MessageBubble(
|
||||
onClick: () -> Unit,
|
||||
onLongPress: () -> Unit,
|
||||
) {
|
||||
val clipboard = LocalClipboardManager.current
|
||||
var contextAttachmentUrl by remember { mutableStateOf<String?>(null) }
|
||||
val isOutgoing = message.isOutgoing
|
||||
val bubbleShape = if (isOutgoing) {
|
||||
RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp, bottomStart = 16.dp, bottomEnd = 6.dp)
|
||||
@@ -733,41 +737,120 @@ private fun MessageBubble(
|
||||
}
|
||||
if (message.attachments.isNotEmpty()) {
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
val showAsFileList = message.attachments.size > 1
|
||||
message.attachments.forEach { attachment ->
|
||||
val fileType = attachment.fileType.lowercase()
|
||||
when {
|
||||
fileType.startsWith("image/") -> {
|
||||
AsyncImage(
|
||||
model = attachment.fileUrl,
|
||||
contentDescription = "Image",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(160.dp)
|
||||
.clickable { onAttachmentImageClick(attachment.fileUrl) },
|
||||
contentScale = ContentScale.Crop,
|
||||
)
|
||||
}
|
||||
fileType.startsWith("video/") -> {
|
||||
VideoAttachmentCard(
|
||||
url = attachment.fileUrl,
|
||||
fileType = attachment.fileType,
|
||||
)
|
||||
}
|
||||
fileType.startsWith("audio/") -> {
|
||||
AudioAttachmentPlayer(url = attachment.fileUrl)
|
||||
}
|
||||
else -> {
|
||||
FileAttachmentRow(
|
||||
fileUrl = attachment.fileUrl,
|
||||
fileType = attachment.fileType,
|
||||
fileSize = attachment.fileSize,
|
||||
compact = showAsFileList,
|
||||
)
|
||||
val imageAttachments = message.attachments.filter { it.fileType.lowercase().startsWith("image/") }
|
||||
val nonImageAttachments = message.attachments.filterNot { it.fileType.lowercase().startsWith("image/") }
|
||||
|
||||
if (imageAttachments.isNotEmpty()) {
|
||||
if (imageAttachments.size == 1) {
|
||||
val single = imageAttachments.first()
|
||||
AsyncImage(
|
||||
model = single.fileUrl,
|
||||
contentDescription = "Image",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(180.dp)
|
||||
.combinedClickable(
|
||||
onClick = { onAttachmentImageClick(single.fileUrl) },
|
||||
onLongClick = { contextAttachmentUrl = single.fileUrl },
|
||||
),
|
||||
contentScale = ContentScale.Crop,
|
||||
)
|
||||
} else {
|
||||
imageAttachments.chunked(2).forEach { rowItems ->
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
rowItems.forEach { image ->
|
||||
AsyncImage(
|
||||
model = image.fileUrl,
|
||||
contentDescription = "Image",
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.height(110.dp)
|
||||
.combinedClickable(
|
||||
onClick = { onAttachmentImageClick(image.fileUrl) },
|
||||
onLongClick = { contextAttachmentUrl = image.fileUrl },
|
||||
),
|
||||
contentScale = ContentScale.Crop,
|
||||
)
|
||||
}
|
||||
if (rowItems.size == 1) {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
}
|
||||
|
||||
val showAsFileList = nonImageAttachments.size > 1
|
||||
nonImageAttachments.forEach { attachment ->
|
||||
val fileType = attachment.fileType.lowercase()
|
||||
when {
|
||||
fileType.startsWith("video/") -> {
|
||||
Box(
|
||||
modifier = Modifier.combinedClickable(
|
||||
onClick = {},
|
||||
onLongClick = { contextAttachmentUrl = attachment.fileUrl },
|
||||
),
|
||||
) {
|
||||
VideoAttachmentCard(
|
||||
url = attachment.fileUrl,
|
||||
fileType = attachment.fileType,
|
||||
)
|
||||
}
|
||||
}
|
||||
fileType.startsWith("audio/") -> {
|
||||
Box(
|
||||
modifier = Modifier.combinedClickable(
|
||||
onClick = {},
|
||||
onLongClick = { contextAttachmentUrl = attachment.fileUrl },
|
||||
),
|
||||
) {
|
||||
AudioAttachmentPlayer(url = attachment.fileUrl)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
Box(
|
||||
modifier = Modifier.combinedClickable(
|
||||
onClick = {},
|
||||
onLongClick = { contextAttachmentUrl = attachment.fileUrl },
|
||||
),
|
||||
) {
|
||||
FileAttachmentRow(
|
||||
fileUrl = attachment.fileUrl,
|
||||
fileType = attachment.fileType,
|
||||
fileSize = attachment.fileSize,
|
||||
compact = showAsFileList,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
}
|
||||
}
|
||||
if (!contextAttachmentUrl.isNullOrBlank()) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||
) {
|
||||
Button(onClick = { onAttachmentImageClick(contextAttachmentUrl!!) }) {
|
||||
Text("Open")
|
||||
}
|
||||
Button(
|
||||
onClick = {
|
||||
clipboard.setText(AnnotatedString(contextAttachmentUrl!!))
|
||||
contextAttachmentUrl = null
|
||||
},
|
||||
) {
|
||||
Text("Copy link")
|
||||
}
|
||||
Button(onClick = { contextAttachmentUrl = null }) {
|
||||
Text("Close")
|
||||
}
|
||||
}
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
|
||||
Reference in New Issue
Block a user