Animate user status state change

This commit is contained in:
Benoit Marty
2026-09-21 09:50:03 +02:00
parent ae36cc3b1e
commit cc3b788b3e
@@ -7,12 +7,12 @@
package io.element.android.features.preferences.impl.userstatus
import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.shape.CircleShape
@@ -72,47 +72,65 @@ fun UserStatusView(
emojiPickerRenderer: EmojiPickerRenderer,
modifier: Modifier = Modifier,
) {
when (val pickerState = state.pickerState) {
UserStatusPickerState.Hidden, UserStatusPickerState.ShowingPicker -> {
val displayedStatus = state.displayedStatus
if (displayedStatus != null) {
CurrentStatusRow(
displayedStatus = displayedStatus,
onClick = { state.eventSink(UserStatusEvent.OpenPicker) },
onClear = { state.eventSink(UserStatusEvent.ClearStatus) },
modifier = modifier,
)
} else {
EmptyStatusRow(
onClick = { state.eventSink(UserStatusEvent.OpenPicker) },
modifier = modifier,
)
AnimatedContent(
targetState = state,
contentKey = {
when (it.pickerState) {
UserStatusPickerState.Hidden,
UserStatusPickerState.ShowingPicker -> if (state.displayedStatus != null) 0 else 1
is UserStatusPickerState.CustomInput -> 2
}
if (pickerState == UserStatusPickerState.ShowingPicker) {
UserStatusPickerBottomSheet(
currentRawStatus = state.rawStatus,
onDismiss = { state.eventSink(UserStatusEvent.DismissPicker) },
onSelectPredefinedStatus = { status -> state.eventSink(UserStatusEvent.SetStatus(status)) },
onSelectCustomStatus = { state.eventSink(UserStatusEvent.OpenCustomInput) },
},
) { userStatusState ->
when (val pickerState = userStatusState.pickerState) {
UserStatusPickerState.Hidden,
UserStatusPickerState.ShowingPicker -> {
val displayedStatus = state.displayedStatus
if (displayedStatus != null) {
CurrentStatusRow(
displayedStatus = displayedStatus,
onClick = { state.eventSink(UserStatusEvent.OpenPicker) },
onClear = { state.eventSink(UserStatusEvent.ClearStatus) },
modifier = modifier,
)
} else {
EmptyStatusRow(
onClick = { state.eventSink(UserStatusEvent.OpenPicker) },
modifier = modifier,
)
}
}
is UserStatusPickerState.CustomInput -> {
CustomStatusInputRow(
emoji = pickerState.emoji,
textFieldState = pickerState.textFieldState,
rawStatus = state.rawStatus,
onConfirm = {
state.eventSink(
UserStatusEvent.SetStatus(UserStatus(pickerState.emoji, pickerState.textFieldState.text.toString()))
)
},
onCancel = { state.eventSink(UserStatusEvent.CancelCustomInput) },
onEmojiClick = { state.eventSink(UserStatusEvent.OpenEmojiPicker) },
modifier = modifier,
)
}
}
is UserStatusPickerState.CustomInput -> {
CustomStatusInputRow(
emoji = pickerState.emoji,
textFieldState = pickerState.textFieldState,
rawStatus = state.rawStatus,
onConfirm = {
state.eventSink(
UserStatusEvent.SetStatus(UserStatus(pickerState.emoji, pickerState.textFieldState.text.toString()))
)
},
onCancel = { state.eventSink(UserStatusEvent.CancelCustomInput) },
onEmojiClick = { state.eventSink(UserStatusEvent.OpenEmojiPicker) },
modifier = modifier,
}
when (val pickerState = state.pickerState) {
UserStatusPickerState.Hidden -> Unit
UserStatusPickerState.ShowingPicker -> {
UserStatusPickerBottomSheet(
currentRawStatus = state.rawStatus,
onDismiss = { state.eventSink(UserStatusEvent.DismissPicker) },
onSelectPredefinedStatus = { status -> state.eventSink(UserStatusEvent.SetStatus(status)) },
onSelectCustomStatus = { state.eventSink(UserStatusEvent.OpenCustomInput) },
)
}
is UserStatusPickerState.CustomInput -> {
when (val sheet = pickerState.emojiPickerSheetState) {
EmojiPickerSheetState.Hidden, EmojiPickerSheetState.Loading -> Unit
EmojiPickerSheetState.Hidden,
EmojiPickerSheetState.Loading -> Unit
is EmojiPickerSheetState.Shown -> EmojiPickerBottomSheet(
pickerState = sheet.state,
emojiPickerRenderer = emojiPickerRenderer,
@@ -133,7 +151,6 @@ private fun EmptyStatusRow(
content = {
Text(
text = stringResource(R.string.screen_settings_user_status_placeholder),
modifier = Modifier.padding(vertical = 16.dp),
)
},
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Reaction())),
@@ -153,7 +170,7 @@ private fun CurrentStatusRow(
is DisplayedStatus.InCall -> "🎧" to stringResource(CommonStrings.common_on_a_call)
}
ListItem(
content = { Text(text = text, modifier = Modifier.padding(vertical = 16.dp)) },
content = { Text(text = text) },
leadingContent = ListItemContent.Custom { EmojiText(emoji) },
trailingContent = ListItemContent.Custom({
IconButton(