diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt index ca308e4815..0b8da1bd94 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt @@ -21,8 +21,10 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -31,6 +33,7 @@ import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser import io.element.android.features.startchat.impl.R import io.element.android.features.startchat.impl.components.UserListView +import io.element.android.libraries.androidutils.ui.hideKeyboardAndAwaitAnimation import io.element.android.libraries.designsystem.components.async.AsyncActionView import io.element.android.libraries.designsystem.components.async.AsyncActionViewDefaults import io.element.android.libraries.designsystem.components.button.BackButton @@ -47,6 +50,7 @@ import io.element.android.libraries.matrix.ui.components.CreateDmConfirmationBot import io.element.android.libraries.matrix.ui.components.MatrixUserRow import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.launch @Composable fun StartChatView( @@ -59,6 +63,8 @@ fun StartChatView( onRoomDirectorySearchClick: () -> Unit, modifier: Modifier = Modifier, ) { + val coroutineScope = rememberCoroutineScope() + Scaffold( modifier = modifier.fillMaxWidth(), topBar = { @@ -73,6 +79,8 @@ fun StartChatView( .consumeWindowInsets(paddingValues), verticalArrangement = Arrangement.spacedBy(8.dp), ) { + val view = LocalView.current + UserListView( modifier = Modifier.fillMaxWidth(), // Do not render suggestions in this case, the suggestion will be rendered @@ -81,7 +89,10 @@ fun StartChatView( recentDirectRooms = persistentListOf(), ), onSelectUser = { - state.eventSink(StartChatEvents.StartDM(it)) + coroutineScope.launch { + view.hideKeyboardAndAwaitAnimation() + state.eventSink(StartChatEvents.StartDM(it)) + } }, onDeselectUser = { }, ) diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt index 96a1e5f9aa..ae724a7c44 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt @@ -9,12 +9,15 @@ package io.element.android.libraries.androidutils.ui import android.os.Build +import android.os.Bundle +import android.os.ResultReceiver import android.view.View import android.view.ViewTreeObserver import android.view.WindowInsets import android.view.inputmethod.InputMethodManager import androidx.core.content.getSystemService import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.sync.Mutex import kotlin.coroutines.resume fun View.hideKeyboard() { @@ -22,6 +25,32 @@ fun View.hideKeyboard() { imm?.hideSoftInputFromWindow(windowToken, 0) } +suspend fun View.hideKeyboardAndAwaitAnimation() { + val imm = context?.getSystemService() + + val mutex = Mutex() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + setOnApplyWindowInsetsListener { view, insets -> + if (!insets.isVisible(WindowInsets.Type.ime())) { + mutex.unlock() + } + insets + } + imm?.hideSoftInputFromWindow(windowToken, 0) + } else { + @Suppress("DEPRECATION") + imm?.hideSoftInputFromWindow(windowToken, 0, object : ResultReceiver(null) { + override fun onReceiveResult(resultCode: Int, resultData: Bundle?) { + if (resultCode == InputMethodManager.RESULT_UNCHANGED_HIDDEN || + resultCode == InputMethodManager.RESULT_HIDDEN) { + mutex.unlock() + } + } + }) + } + mutex.lock() +} + fun View.showKeyboard(andRequestFocus: Boolean = false) { if (andRequestFocus) { requestFocus() diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.kt index 95935947db..dca173d780 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.kt @@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Text +import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -54,14 +55,14 @@ fun CreateDmConfirmationBottomSheet( ModalBottomSheet( modifier = modifier, onDismissRequest = onDismiss, + sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true), ) { Column( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 16.dp), + .padding(top = 24.dp, bottom = 16.dp, start = 16.dp, end = 16.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { - Spacer(modifier = Modifier.height(24.dp)) Avatar( avatarData = matrixUser.getAvatarData(AvatarSize.DmCreationConfirmation), avatarType = AvatarType.User, @@ -93,7 +94,6 @@ fun CreateDmConfirmationBottomSheet( onClick = onDismiss, text = stringResource(CommonStrings.action_cancel), ) - Spacer(modifier = Modifier.height(16.dp)) } } }