Browse Source

Use user friendly error messages in login following iOS logic (#174)

* Use user friendly error messages in login following iOS logic, fix dialog colors.

* Use `AlertDialogDefaults` for the default properties of dialogs

* Improve Maestro tests with wrong password dialog

* Add tests for error messages
misc/jme/add-logging-to-state-machine
Jorge Martin Espinosa 2 years ago committed by GitHub
parent
commit
d36ca2907c
  1. 8
      .maestro/tests/account/login.yaml
  2. 1
      changelog.d/132.bugfix
  3. 6
      features/login/build.gradle.kts
  4. 3
      features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerView.kt
  5. 40
      features/login/src/main/kotlin/io/element/android/features/login/error/ErrorFormatter.kt
  6. 15
      features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootScreen.kt
  7. 98
      features/login/src/test/kotlin/io/element/android/features/login/error/ErrorFormatterTests.kt
  8. 8
      libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ConfirmationDialog.kt
  9. 14
      libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ErrorDialog.kt
  10. 2
      libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorsLight.kt
  11. 3
      libraries/matrix/api/build.gradle.kts
  12. 34
      libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/AuthErrorCode.kt
  13. 49
      libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/auth/AuthErrorCodeTests.kt
  14. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.changeserver_null_DefaultGroup_ChangeServerViewLightPreview_0_null_0,NEXUS_5,1,en].png
  15. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.changeserver_null_DefaultGroup_ChangeServerViewLightPreview_0_null_1,NEXUS_5,1,en].png
  16. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.changeserver_null_DefaultGroup_ChangeServerViewLightPreview_0_null_2,NEXUS_5,1,en].png
  17. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.changeserver_null_DefaultGroup_ChangeServerViewLightPreview_0_null_3,NEXUS_5,1,en].png
  18. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.changeserver_null_DefaultGroup_ChangeServerViewLightPreview_0_null_4,NEXUS_5,1,en].png
  19. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.root_null_DefaultGroup_LoginRootScreenDarkPreview_0_null_4,NEXUS_5,1,en].png
  20. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.root_null_DefaultGroup_LoginRootScreenLightPreview_0_null_0,NEXUS_5,1,en].png
  21. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.root_null_DefaultGroup_LoginRootScreenLightPreview_0_null_1,NEXUS_5,1,en].png
  22. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.root_null_DefaultGroup_LoginRootScreenLightPreview_0_null_2,NEXUS_5,1,en].png
  23. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.root_null_DefaultGroup_LoginRootScreenLightPreview_0_null_3,NEXUS_5,1,en].png
  24. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.root_null_DefaultGroup_LoginRootScreenLightPreview_0_null_4,NEXUS_5,1,en].png
  25. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.root_null_DefaultGroup_LoginRootScreenLightPreview_0_null_5,NEXUS_5,1,en].png
  26. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.root_null_DefaultGroup_PreferencesRootViewLightPreview_0_null_0,NEXUS_5,1,en].png
  27. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.root_null_DefaultGroup_PreferencesRootViewLightPreview_0_null_1,NEXUS_5,1,en].png
  28. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_0,NEXUS_5,1,en].png
  29. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_1,NEXUS_5,1,en].png
  30. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.crash.ui_null_DefaultGroup_CrashDetectionViewDarkPreview_0_null,NEXUS_5,1,en].png
  31. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.crash.ui_null_DefaultGroup_CrashDetectionViewLightPreview_0_null,NEXUS_5,1,en].png
  32. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.detection_null_DefaultGroup_RageshakeDialogContentDarkPreview_0_null,NEXUS_5,1,en].png
  33. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.detection_null_DefaultGroup_RageshakeDialogContentLightPreview_0_null,NEXUS_5,1,en].png
  34. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.preferences_null_DefaultGroup_RageshakePreferencesViewLightPreview_0_null_0,NEXUS_5,1,en].png
  35. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.components_null_DefaultGroup_DefaultRoomListTopBarLightPreview_0_null,NEXUS_5,1,en].png
  36. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist_null_DefaultGroup_RoomListViewLightPreview_0_null_0,NEXUS_5,1,en].png
  37. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_DefaultGroup_ConfirmationDialogDarkPreview_0_null,NEXUS_5,1,en].png
  38. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_DefaultGroup_ConfirmationDialogLightPreview_0_null,NEXUS_5,1,en].png
  39. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_DefaultGroup_ErrorDialogDarkPreview_0_null,NEXUS_5,1,en].png
  40. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_DefaultGroup_ErrorDialogLightPreview_0_null,NEXUS_5,1,en].png
  41. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components_null_DefaultGroup_ProgressDialogLightPreview_0_null,NEXUS_5,1,en].png
  42. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_DefaultGroup_CheckboxesLightPreview_0_null,NEXUS_5,1,en].png
  43. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_DefaultGroup_OutlinedTextFieldsLightPreview_0_null,NEXUS_5,1,en].png
  44. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_DefaultGroup_TextFieldLightPreview_0_null,NEXUS_5,1,en].png
  45. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_DefaultGroup_TextLightPreview_0_null,NEXUS_5,1,en].png
  46. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme_null_DefaultGroup_ColorsSchemePreviewLight_0_null,NEXUS_5,1,en].png

8
.maestro/tests/account/login.yaml

@ -9,9 +9,15 @@ appId: ${APP_ID}
id: "login-email_username" id: "login-email_username"
- inputText: ${USERNAME} - inputText: ${USERNAME}
- pressKey: Enter - pressKey: Enter
- tapOn: "Password"
- tapOn: - tapOn:
id: "login-password" id: "login-password"
- inputText: "wrong-password"
- pressKey: Enter
- tapOn: "Continue"
- tapOn: "OK"
- tapOn:
id: "login-password"
- eraseText: 20
- inputText: ${PASSWORD} - inputText: ${PASSWORD}
- pressKey: Enter - pressKey: Enter
- tapOn: "Continue" - tapOn: "Continue"

1
changelog.d/132.bugfix

@ -0,0 +1 @@
Use user friendly error messages in login following iOS logic, fix dialog colors.

6
features/login/build.gradle.kts

@ -25,6 +25,12 @@ plugins {
android { android {
namespace = "io.element.android.features.login" namespace = "io.element.android.features.login"
testOptions {
unitTests {
isIncludeAndroidResources = true
}
}
} }
anvil { anvil {

3
features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerView.kt

@ -51,6 +51,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.features.login.R import io.element.android.features.login.R
import io.element.android.features.login.error.changeServerError
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.ElementTextStyles import io.element.android.libraries.designsystem.ElementTextStyles
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
@ -239,7 +240,7 @@ fun ChangeServerView(
@Composable @Composable
internal fun ChangeServerErrorDialog(error: Throwable, onDismiss: () -> Unit) { internal fun ChangeServerErrorDialog(error: Throwable, onDismiss: () -> Unit) {
ErrorDialog( ErrorDialog(
content = error.localizedMessage ?: stringResource(id = StringR.string.unknown_error), content = stringResource(changeServerError(error)),
onDismiss = onDismiss onDismiss = onDismiss
) )
} }

40
features/login/src/main/kotlin/io/element/android/features/login/error/ErrorFormatter.kt

@ -16,34 +16,28 @@
package io.element.android.features.login.error package io.element.android.features.login.error
import androidx.compose.runtime.Composable import io.element.android.libraries.matrix.api.auth.AuthErrorCode
import androidx.compose.ui.res.stringResource import io.element.android.libraries.matrix.api.auth.errorCode
import io.element.android.features.login.root.LoginFormState import org.matrix.rustcomponents.sdk.AuthenticationException
import io.element.android.libraries.core.uri.isValidUrl import io.element.android.libraries.ui.strings.R.string as StringR
import io.element.android.libraries.ui.strings.R as StringR
@Composable
fun loginError( fun loginError(
data: LoginFormState, throwable: Throwable
throwable: Throwable? ): Int {
): String { val authException = throwable as? AuthenticationException ?: return StringR.unknown_error
return when { return when (authException.errorCode) {
data.login.isEmpty() -> "Please enter a login" AuthErrorCode.FORBIDDEN -> StringR.auth_invalid_login_param
data.password.isEmpty() -> "Please enter a password" AuthErrorCode.USER_DEACTIVATED -> StringR.auth_invalid_login_deactivated_account
throwable != null -> stringResource(id = StringR.string.auth_invalid_login_param) AuthErrorCode.UNKNOWN -> StringR.unknown_error
else -> "No error provided"
} }
} }
@Composable
fun changeServerError( fun changeServerError(
data: String, throwable: Throwable
throwable: Throwable? ): Int {
): String { val authException = throwable as? AuthenticationException ?: return StringR.unknown_error
return when { return when (authException) {
data.isEmpty() -> "Please enter a server URL" is AuthenticationException.InvalidServerName -> StringR.login_error_homeserver_not_found
!data.isValidUrl() -> stringResource(id = StringR.string.login_error_invalid_home_server) else -> StringR.unknown_error
throwable != null -> "That server doesn’t seem right. Please check the address."
else -> "No error provided"
} }
} }

15
features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootScreen.kt

@ -62,6 +62,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.features.login.error.loginError
import io.element.android.libraries.designsystem.ElementTextStyles import io.element.android.libraries.designsystem.ElementTextStyles
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.components.form.textFieldState import io.element.android.libraries.designsystem.components.form.textFieldState
@ -153,6 +154,12 @@ fun LoginRootScreen(
} }
} }
} }
if (state.loggedInState is LoggedInState.ErrorLoggingIn) {
LoginErrorDialog(error = state.loggedInState.failure, onDismiss = {
state.eventSink(LoginRootEvents.ClearError)
})
}
} }
@Composable @Composable
@ -299,12 +306,6 @@ internal fun LoginForm(
singleLine = true, singleLine = true,
maxLines = 1, maxLines = 1,
) )
if (state.loggedInState is LoggedInState.ErrorLoggingIn) {
LoginErrorDialog(error = state.loggedInState.failure, onDismiss = {
eventSink(LoginRootEvents.ClearError)
})
}
Spacer(Modifier.height(28.dp)) Spacer(Modifier.height(28.dp))
// Submit // Submit
@ -323,7 +324,7 @@ internal fun LoginForm(
@Composable @Composable
internal fun LoginErrorDialog(error: Throwable, onDismiss: () -> Unit) { internal fun LoginErrorDialog(error: Throwable, onDismiss: () -> Unit) {
ErrorDialog( ErrorDialog(
content = error.localizedMessage ?: stringResource(id = StringR.string.unknown_error), content = stringResource(loginError(error)),
onDismiss = onDismiss onDismiss = onDismiss
) )
} }

98
features/login/src/test/kotlin/io/element/android/features/login/error/ErrorFormatterTests.kt

@ -0,0 +1,98 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.login.error
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import io.element.android.libraries.ui.strings.R
import org.matrix.rustcomponents.sdk.AuthenticationException
class ErrorFormatterTests {
// region loginError
@Test
fun `loginError - invalid unknown error returns unknown error message`() {
val error = Throwable("Some unknown error")
assertThat(loginError(error)).isEqualTo(R.string.unknown_error)
}
@Test
fun `loginError - invalid auth error returns unknown error message`() {
val error = AuthenticationException.SlidingSyncNotAvailable("Some message. Also contains M_FORBIDDEN, but won't be parsed")
assertThat(loginError(error)).isEqualTo(R.string.unknown_error)
}
@Test
fun `loginError - unknown error returns unknown error message`() {
val error = AuthenticationException.Generic("M_UNKNOWN")
assertThat(loginError(error)).isEqualTo(R.string.unknown_error)
}
@Test
fun `loginError - forbidden error returns incorrect credentials message`() {
val error = AuthenticationException.Generic("M_FORBIDDEN")
assertThat(loginError(error)).isEqualTo(R.string.auth_invalid_login_param)
}
@Test
fun `loginError - user_deactivated error returns deactivated account message`() {
val error = AuthenticationException.Generic("M_USER_DEACTIVATED")
assertThat(loginError(error)).isEqualTo(R.string.auth_invalid_login_deactivated_account)
}
// endregion loginError
// region changeServerError
@Test
fun `changeServerError - invalid unknown error returns unknown error message`() {
val error = Throwable("Some unknown error")
assertThat(changeServerError(error)).isEqualTo(R.string.unknown_error)
}
@Test
fun `changeServerError - invalid auth error returns unknown error message`() {
val error = AuthenticationException.SlidingSyncNotAvailable("Some message. Also contains M_FORBIDDEN, but won't be parsed")
assertThat(changeServerError(error)).isEqualTo(R.string.unknown_error)
}
@Test
fun `changeServerError - unknown error returns unknown error message`() {
val error = AuthenticationException.Generic("M_UNKNOWN")
assertThat(changeServerError(error)).isEqualTo(R.string.unknown_error)
}
@Test
fun `changeServerError - forbidden error returns unknown error message`() {
val error = AuthenticationException.Generic("M_FORBIDDEN")
assertThat(changeServerError(error)).isEqualTo(R.string.unknown_error)
}
@Test
fun `changeServerError - user_deactivated error returns unknown error message`() {
val error = AuthenticationException.Generic("M_USER_DEACTIVATED")
assertThat(changeServerError(error)).isEqualTo(R.string.unknown_error)
}
@Test
fun `changeServerError - invalid server name error returns invalid server name error message`() {
val error = AuthenticationException.InvalidServerName("Server is not valid")
assertThat(changeServerError(error)).isEqualTo(R.string.login_error_homeserver_not_found)
}
// endregion changeServerError
}

8
libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ConfirmationDialog.kt

@ -48,10 +48,10 @@ fun ConfirmationDialog(
onThirdButtonClicked: () -> Unit = {}, onThirdButtonClicked: () -> Unit = {},
onDismiss: () -> Unit = {}, onDismiss: () -> Unit = {},
shape: Shape = AlertDialogDefaults.shape, shape: Shape = AlertDialogDefaults.shape,
containerColor: Color = MaterialTheme.colorScheme.surfaceVariant, containerColor: Color = AlertDialogDefaults.containerColor,
iconContentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant, iconContentColor: Color = AlertDialogDefaults.iconContentColor,
titleContentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant, titleContentColor: Color = AlertDialogDefaults.titleContentColor,
textContentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant, textContentColor: Color = AlertDialogDefaults.textContentColor,
tonalElevation: Dp = AlertDialogDefaults.TonalElevation, tonalElevation: Dp = AlertDialogDefaults.TonalElevation,
) { ) {
AlertDialog( AlertDialog(

14
libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ErrorDialog.kt

@ -16,10 +16,6 @@
package io.element.android.libraries.designsystem.components.dialogs package io.element.android.libraries.designsystem.components.dialogs
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.AlertDialogDefaults import androidx.compose.material3.AlertDialogDefaults
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@ -31,10 +27,8 @@ import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.ui.strings.R as StringR import io.element.android.libraries.ui.strings.R as StringR
@ -46,10 +40,10 @@ fun ErrorDialog(
submitText: String = stringResource(id = StringR.string.ok), submitText: String = stringResource(id = StringR.string.ok),
onDismiss: () -> Unit = {}, onDismiss: () -> Unit = {},
shape: Shape = AlertDialogDefaults.shape, shape: Shape = AlertDialogDefaults.shape,
containerColor: Color = MaterialTheme.colorScheme.surfaceVariant, containerColor: Color = AlertDialogDefaults.containerColor,
iconContentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant, iconContentColor: Color = AlertDialogDefaults.iconContentColor,
titleContentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant, titleContentColor: Color = AlertDialogDefaults.titleContentColor,
textContentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant, textContentColor: Color = AlertDialogDefaults.textContentColor,
tonalElevation: Dp = AlertDialogDefaults.TonalElevation, tonalElevation: Dp = AlertDialogDefaults.TonalElevation,
) { ) {
AlertDialog( AlertDialog(

2
libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorsLight.kt

@ -60,7 +60,7 @@ val materialColorSchemeLight = lightColorScheme(
surface = Color.White, surface = Color.White,
onSurface = Color.Black, onSurface = Color.Black,
surfaceVariant = Gray_25, surfaceVariant = Gray_25,
onSurfaceVariant = Gray_150, onSurfaceVariant = Gray_200,
// TODO surfaceTint = primary, // TODO surfaceTint = primary,
// TODO inverseSurface = ColorLightTokens.InverseSurface, // TODO inverseSurface = ColorLightTokens.InverseSurface,
// TODO inverseOnSurface = ColorLightTokens.InverseOnSurface, // TODO inverseOnSurface = ColorLightTokens.InverseOnSurface,

3
libraries/matrix/api/build.gradle.kts

@ -41,4 +41,7 @@ dependencies {
implementation(libs.serialization.json) implementation(libs.serialization.json)
api(projects.libraries.sessionStorage.api) api(projects.libraries.sessionStorage.api)
implementation(libs.coroutines.core) implementation(libs.coroutines.core)
testImplementation(libs.test.junit)
testImplementation(libs.test.truth)
} }

34
libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/AuthErrorCode.kt

@ -0,0 +1,34 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.matrix.api.auth
import org.matrix.rustcomponents.sdk.AuthenticationException
enum class AuthErrorCode(val value: String) {
UNKNOWN("M_UNKNOWN"),
USER_DEACTIVATED("M_USER_DEACTIVATED"),
FORBIDDEN("M_FORBIDDEN")
}
// This is taken from the iOS version. It seems like currently there's no better way to extract error codes
val AuthenticationException.errorCode: AuthErrorCode
get() {
val message = (this as? AuthenticationException.Generic)?.message ?: return AuthErrorCode.UNKNOWN
return enumValues<AuthErrorCode>()
.firstOrNull { message.contains(it.value) }
?: AuthErrorCode.UNKNOWN
}

49
libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/auth/AuthErrorCodeTests.kt

@ -0,0 +1,49 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.matrix.api.auth
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.matrix.rustcomponents.sdk.AuthenticationException
class AuthErrorCodeTests {
@Test
fun `errorCode finds UNKNOWN code`() {
val error = AuthenticationException.Generic("M_UNKNOWN")
assertThat(error.errorCode).isEqualTo(AuthErrorCode.UNKNOWN)
}
@Test
fun `errorCode finds USER_DEACTIVATED code`() {
val error = AuthenticationException.Generic("M_USER_DEACTIVATED")
assertThat(error.errorCode).isEqualTo(AuthErrorCode.USER_DEACTIVATED)
}
@Test
fun `errorCode finds FORBIDDEN code`() {
val error = AuthenticationException.Generic("M_FORBIDDEN")
assertThat(error.errorCode).isEqualTo(AuthErrorCode.FORBIDDEN)
}
@Test
fun `errorCode cannot find code so it returns UNKNOWN`() {
val error = AuthenticationException.Generic("Some other error")
assertThat(error.errorCode).isEqualTo(AuthErrorCode.UNKNOWN)
}
}

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.changeserver_null_DefaultGroup_ChangeServerViewLightPreview_0_null_0,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.changeserver_null_DefaultGroup_ChangeServerViewLightPreview_0_null_1,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.changeserver_null_DefaultGroup_ChangeServerViewLightPreview_0_null_2,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.changeserver_null_DefaultGroup_ChangeServerViewLightPreview_0_null_3,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.changeserver_null_DefaultGroup_ChangeServerViewLightPreview_0_null_4,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.root_null_DefaultGroup_LoginRootScreenDarkPreview_0_null_4,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.root_null_DefaultGroup_LoginRootScreenLightPreview_0_null_0,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.root_null_DefaultGroup_LoginRootScreenLightPreview_0_null_1,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.root_null_DefaultGroup_LoginRootScreenLightPreview_0_null_2,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.root_null_DefaultGroup_LoginRootScreenLightPreview_0_null_3,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.root_null_DefaultGroup_LoginRootScreenLightPreview_0_null_4,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.root_null_DefaultGroup_LoginRootScreenLightPreview_0_null_5,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.root_null_DefaultGroup_PreferencesRootViewLightPreview_0_null_0,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.root_null_DefaultGroup_PreferencesRootViewLightPreview_0_null_1,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_0,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_1,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.crash.ui_null_DefaultGroup_CrashDetectionViewDarkPreview_0_null,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.crash.ui_null_DefaultGroup_CrashDetectionViewLightPreview_0_null,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.detection_null_DefaultGroup_RageshakeDialogContentDarkPreview_0_null,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.detection_null_DefaultGroup_RageshakeDialogContentLightPreview_0_null,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.preferences_null_DefaultGroup_RageshakePreferencesViewLightPreview_0_null_0,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.components_null_DefaultGroup_DefaultRoomListTopBarLightPreview_0_null,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist_null_DefaultGroup_RoomListViewLightPreview_0_null_0,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_DefaultGroup_ConfirmationDialogDarkPreview_0_null,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_DefaultGroup_ConfirmationDialogLightPreview_0_null,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_DefaultGroup_ErrorDialogDarkPreview_0_null,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_DefaultGroup_ErrorDialogLightPreview_0_null,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components_null_DefaultGroup_ProgressDialogLightPreview_0_null,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_DefaultGroup_CheckboxesLightPreview_0_null,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_DefaultGroup_OutlinedTextFieldsLightPreview_0_null,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_DefaultGroup_TextFieldLightPreview_0_null,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_DefaultGroup_TextLightPreview_0_null,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme_null_DefaultGroup_ColorsSchemePreviewLight_0_null,NEXUS_5,1,en].png (Stored with Git LFS)

Binary file not shown.
Loading…
Cancel
Save