android: refine multi-select ui to telegram-like layout
This commit is contained in:
@@ -1015,3 +1015,11 @@
|
||||
- Message actions are now driven by Telegram-like context UI:
|
||||
- tap -> context sheet actions,
|
||||
- long-press -> selection mode flow.
|
||||
|
||||
### Step 138 - Multi-select UX closer to Telegram
|
||||
- Refined selection top bar:
|
||||
- removed extra overflow/load action from selection mode,
|
||||
- kept focused actions only: close, selected count, forward, delete.
|
||||
- In `MULTI` selection mode, composer is now replaced with a compact bottom action row:
|
||||
- `Reply` (enabled for single selected message),
|
||||
- `Forward`.
|
||||
|
||||
@@ -419,9 +419,6 @@ fun ChatScreen(
|
||||
) {
|
||||
Icon(imageVector = Icons.Filled.DeleteOutline, contentDescription = "Delete selected")
|
||||
}
|
||||
IconButton(onClick = onLoadMore, enabled = !state.isLoadingMore) {
|
||||
Icon(imageVector = Icons.Filled.MoreVert, contentDescription = "Selection menu")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Row(
|
||||
@@ -1045,7 +1042,14 @@ fun ChatScreen(
|
||||
}
|
||||
}
|
||||
|
||||
if (isChannelChat && !state.canSendMessages) {
|
||||
if (state.actionState.mode == MessageSelectionMode.MULTI && state.actionState.hasSelection) {
|
||||
MultiSelectActionBar(
|
||||
selectedCount = state.actionState.selectedCount,
|
||||
canReply = state.actionState.selectedCount == 1 && state.selectedMessage != null,
|
||||
onReply = { state.selectedMessage?.let(onReplySelected) },
|
||||
onForward = onForwardSelected,
|
||||
)
|
||||
} else if (isChannelChat && !state.canSendMessages) {
|
||||
ChannelReadOnlyBar(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -2161,6 +2165,50 @@ private fun ChannelReadOnlyBar(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MultiSelectActionBar(
|
||||
selectedCount: Int,
|
||||
canReply: Boolean,
|
||||
onReply: () -> Unit,
|
||||
onForward: () -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.navigationBarsPadding()
|
||||
.padding(horizontal = 10.dp, vertical = 6.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(999.dp),
|
||||
color = MaterialTheme.colorScheme.surface.copy(alpha = 0.95f),
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
TextButton(
|
||||
onClick = onReply,
|
||||
enabled = canReply,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Text("Reply")
|
||||
}
|
||||
}
|
||||
Surface(
|
||||
shape = RoundedCornerShape(999.dp),
|
||||
color = MaterialTheme.colorScheme.surface.copy(alpha = 0.95f),
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
TextButton(
|
||||
onClick = onForward,
|
||||
enabled = selectedCount > 0,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Text("Forward")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseMessageLocalDate(createdAt: String): LocalDate? {
|
||||
return runCatching {
|
||||
Instant.parse(createdAt).atZone(ZoneId.systemDefault()).toLocalDate()
|
||||
|
||||
Reference in New Issue
Block a user