fix(deps): update dependency androidx.compose:compose-bom to v2025.04.01 (#4631)
* fix(deps): update dependency androidx.compose:compose-bom to v2025.04.01 * Fix autofill deprecations * Adapt our custom BottomSheetState and scaffold to the new APIs * Get rid of all the custom bottom sheet implementation It doesn't seem to be needed anymore 🎉 * Replace `semantics { invisibleToUser() }` with `hideFromAccessibility()` * Update screenshots * Add commit and cancel callbacks for autofill on the login view * Fix broken tests caused mainly by https://issuetracker.google.com/issues/366255137 Add `LocalUiTestMode` composition local and helper functions. * Remove dependency that caused a new license to need to be approved * Let setSafeContent handle setting the value for LocalUiTestMode * Fix broken test * Apply fix to RoomMemberModerationViewTest and RoomListDeclineInviteMenuTest --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge Martín <jorgem@element.io> Co-authored-by: ElementBot <android@element.io> Co-authored-by: Benoit Marty <benoit@matrix.org>
This commit is contained in:
parent
b59ddeb652
commit
7bb1e24ff5
37 changed files with 189 additions and 1012 deletions
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
package io.element.android.features.login.impl.screens.loginpassword
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
|
|
@ -30,10 +31,13 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.autofill.AutofillType
|
||||
import androidx.compose.ui.autofill.ContentType
|
||||
import androidx.compose.ui.focus.FocusDirection
|
||||
import androidx.compose.ui.platform.LocalAutofillManager
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.contentType
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
|
|
@ -51,7 +55,6 @@ import io.element.android.libraries.designsystem.components.BigIcon
|
|||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
||||
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||
import io.element.android.libraries.designsystem.modifiers.autofill
|
||||
import io.element.android.libraries.designsystem.modifiers.onTabOrEnterKeyFocusNext
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
|
|
@ -71,6 +74,13 @@ fun LoginPasswordView(
|
|||
onBackClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val autofillManager = LocalAutofillManager.current
|
||||
|
||||
BackHandler {
|
||||
autofillManager?.cancel()
|
||||
onBackClick()
|
||||
}
|
||||
|
||||
val isLoading by remember(state.loginAction) {
|
||||
derivedStateOf {
|
||||
state.loginAction is AsyncData.Loading
|
||||
|
|
@ -82,6 +92,8 @@ fun LoginPasswordView(
|
|||
// Clear focus to prevent keyboard issues with textfields
|
||||
focusManager.clearFocus(force = true)
|
||||
|
||||
autofillManager?.commit()
|
||||
|
||||
state.eventSink(LoginPasswordEvents.Submit)
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +102,12 @@ fun LoginPasswordView(
|
|||
topBar = {
|
||||
TopAppBar(
|
||||
title = {},
|
||||
navigationIcon = { BackButton(onClick = onBackClick) },
|
||||
navigationIcon = {
|
||||
BackButton(onClick = {
|
||||
autofillManager?.cancel()
|
||||
onBackClick()
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
) { padding ->
|
||||
|
|
@ -175,14 +192,9 @@ private fun LoginForm(
|
|||
.fillMaxWidth()
|
||||
.onTabOrEnterKeyFocusNext(focusManager)
|
||||
.testTag(TestTags.loginEmailUsername)
|
||||
.autofill(
|
||||
autofillTypes = listOf(AutofillType.Username),
|
||||
onFill = {
|
||||
val sanitized = it.sanitize()
|
||||
loginFieldState = sanitized
|
||||
eventSink(LoginPasswordEvents.SetLogin(sanitized))
|
||||
}
|
||||
),
|
||||
.semantics {
|
||||
contentType = ContentType.Username
|
||||
},
|
||||
placeholder = stringResource(CommonStrings.common_username),
|
||||
onValueChange = {
|
||||
val sanitized = it.sanitize()
|
||||
|
|
@ -227,14 +239,9 @@ private fun LoginForm(
|
|||
.fillMaxWidth()
|
||||
.onTabOrEnterKeyFocusNext(focusManager)
|
||||
.testTag(TestTags.loginPassword)
|
||||
.autofill(
|
||||
autofillTypes = listOf(AutofillType.Password),
|
||||
onFill = {
|
||||
val sanitized = it.sanitize()
|
||||
passwordFieldState = sanitized
|
||||
eventSink(LoginPasswordEvents.SetPassword(sanitized))
|
||||
}
|
||||
),
|
||||
.semantics {
|
||||
contentType = ContentType.Password
|
||||
},
|
||||
onValueChange = {
|
||||
val sanitized = it.sanitize()
|
||||
passwordFieldState = sanitized
|
||||
|
|
|
|||
|
|
@ -8,17 +8,21 @@
|
|||
package io.element.android.features.login.impl.screens.loginpassword
|
||||
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.ui.test.assert
|
||||
import androidx.compose.ui.test.assertIsEnabled
|
||||
import androidx.compose.ui.test.assertIsNotEnabled
|
||||
import androidx.compose.ui.test.hasText
|
||||
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
|
||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithContentDescription
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import io.element.android.libraries.matrix.test.A_PASSWORD
|
||||
import io.element.android.libraries.matrix.test.A_USER_NAME
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.tests.testutils.EnsureNeverCalled
|
||||
import io.element.android.tests.testutils.EventsRecorder
|
||||
|
|
@ -120,15 +124,15 @@ class LoginPasswordViewTest {
|
|||
eventSink = eventsRecorder,
|
||||
),
|
||||
)
|
||||
rule.onNodeWithText(A_PASSWORD).assertDoesNotExist()
|
||||
rule.onNodeWithTag(TestTags.loginPassword.value).assert(hasText("••••••••"))
|
||||
// Show password
|
||||
val a11yShowPassword = rule.activity.getString(CommonStrings.a11y_show_password)
|
||||
rule.onNodeWithContentDescription(a11yShowPassword).performClick()
|
||||
rule.onNodeWithText(A_PASSWORD).assertExists()
|
||||
rule.onNodeWithTag(TestTags.loginPassword.value).assert(hasText(A_PASSWORD))
|
||||
// Hide password
|
||||
val a11yHidePassword = rule.activity.getString(CommonStrings.a11y_hide_password)
|
||||
rule.onNodeWithContentDescription(a11yHidePassword).performClick()
|
||||
rule.onNodeWithText(A_PASSWORD).assertDoesNotExist()
|
||||
rule.onNodeWithTag(TestTags.loginPassword.value).assert(hasText("••••••••"))
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue