Fix crash when starting a DM (#6419)
`AnchoredDraggable.requireOffset` was called before it was populated when displaying `CreateDmConfirmationBottomSheet`, because the keyboard and the bottom sheet were causing conflicting animations related to the insets. Hiding the keyboard before displaying the bottom sheet seems to fix the issue, and `skipPartiallyExpanded` results in a better UX (and also worked around the issue by itself).
This commit is contained in:
committed by
GitHub
parent
93ab9f43dc
commit
9074692189
@@ -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 = { },
|
||||
)
|
||||
|
||||
@@ -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<InputMethodManager>()
|
||||
|
||||
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()
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user