Browse Source

Merge pull request #1738 from vector-im/feature/bma/AsyncView

Introduce AsyncView to avoid repeating ourselves
jonny/vm-set-media
Benoit Marty 11 months ago committed by GitHub
parent
commit
9e63dfa9b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 36
      features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt
  2. 46
      features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootView.kt
  3. 27
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcView.kt
  4. 27
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageView.kt
  5. 22
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt
  6. 31
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt
  7. 33
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt
  8. 38
      features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt
  9. 34
      features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/edit/RoomDetailsEditView.kt
  10. 43
      features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt
  11. 31
      features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/ShowChangeNotificationSettingError.kt
  12. 40
      features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/UserDefinedRoomNotificationSettingsView.kt
  13. 23
      features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyView.kt
  14. 1
      libraries/designsystem/build.gradle.kts
  15. 30
      libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncProvider.kt
  16. 119
      libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncView.kt
  17. 2
      tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt
  18. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.oidc.webview_OidcView_null_OidcView-Day-3_4_null_1,NEXUS_5,1.0,en].png
  19. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.oidc.webview_OidcView_null_OidcView-Night-3_5_null_1,NEXUS_5,1.0,en].png
  20. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Day-7_7_null_5,NEXUS_5,1.0,en].png
  21. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Night-7_8_null_5,NEXUS_5,1.0,en].png
  22. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Day-0_0_null_2,NEXUS_5,1.0,en].png
  23. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Day-0_0_null_3,NEXUS_5,1.0,en].png
  24. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Night-0_1_null_2,NEXUS_5,1.0,en].png
  25. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Night-0_1_null_3,NEXUS_5,1.0,en].png
  26. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Day_0_null_0,NEXUS_5,1.0,en].png
  27. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Day_0_null_1,NEXUS_5,1.0,en].png
  28. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Day_0_null_2,NEXUS_5,1.0,en].png
  29. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Day_0_null_3,NEXUS_5,1.0,en].png
  30. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Night_1_null_0,NEXUS_5,1.0,en].png
  31. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Night_1_null_1,NEXUS_5,1.0,en].png
  32. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Night_1_null_2,NEXUS_5,1.0,en].png
  33. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Night_1_null_3,NEXUS_5,1.0,en].png

36
features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt

@ -36,7 +36,6 @@ import androidx.compose.material.ModalBottomSheetValue @@ -36,7 +36,6 @@ import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -49,13 +48,11 @@ import androidx.compose.ui.tooling.preview.PreviewParameter @@ -49,13 +48,11 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.features.createroom.impl.R
import io.element.android.features.createroom.impl.components.RoomPrivacyOption
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.components.LabelledTextField
import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.async.AsyncView
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.RetryDialog
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
@ -84,12 +81,6 @@ fun ConfigureRoomView( @@ -84,12 +81,6 @@ fun ConfigureRoomView(
initialValue = ModalBottomSheetValue.Hidden,
)
if (state.createRoomAction is Async.Success) {
LaunchedEffect(state.createRoomAction) {
onRoomCreated(state.createRoomAction.data)
}
}
fun onAvatarClicked() {
focusManager.clearFocus()
coroutineScope.launch {
@ -158,21 +149,14 @@ fun ConfigureRoomView( @@ -158,21 +149,14 @@ fun ConfigureRoomView(
onActionSelected = { state.eventSink(ConfigureRoomEvents.HandleAvatarAction(it)) }
)
when (state.createRoomAction) {
is Async.Loading -> {
ProgressDialog(text = stringResource(CommonStrings.common_creating_room))
}
is Async.Failure -> {
RetryDialog(
content = stringResource(R.string.screen_create_room_error_creating_room),
onDismiss = { state.eventSink(ConfigureRoomEvents.CancelCreateRoom) },
onRetry = { state.eventSink(ConfigureRoomEvents.CreateRoom(state.config)) },
)
}
else -> Unit
}
AsyncView(
async = state.createRoomAction,
progressText = stringResource(CommonStrings.common_creating_room),
onSuccess = { onRoomCreated(it) },
errorMessage = { stringResource(R.string.screen_create_room_error_creating_room) },
onRetry = { state.eventSink(ConfigureRoomEvents.CreateRoom(state.config)) },
onErrorDismiss = { state.eventSink(ConfigureRoomEvents.CancelCreateRoom) },
)
PermissionsView(
state = state.cameraPermissionState,

46
features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootView.kt

@ -30,7 +30,6 @@ import androidx.compose.foundation.layout.size @@ -30,7 +30,6 @@ import androidx.compose.foundation.layout.size
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
@ -38,12 +37,10 @@ import androidx.compose.ui.tooling.preview.PreviewParameter @@ -38,12 +37,10 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.features.createroom.impl.R
import io.element.android.features.createroom.impl.components.UserListView
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.async.AsyncView
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.RetryDialog
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Scaffold
@ -64,12 +61,6 @@ fun CreateRoomRootView( @@ -64,12 +61,6 @@ fun CreateRoomRootView(
onOpenDM: (RoomId) -> Unit = {},
onInviteFriendsClicked: () -> Unit = {},
) {
if (state.startDmAction is Async.Success) {
LaunchedEffect(state.startDmAction) {
onOpenDM(state.startDmAction.data)
}
}
Scaffold(
modifier = modifier.fillMaxWidth(),
topBar = {
@ -102,26 +93,19 @@ fun CreateRoomRootView( @@ -102,26 +93,19 @@ fun CreateRoomRootView(
}
}
when (state.startDmAction) {
is Async.Loading -> {
ProgressDialog(text = stringResource(id = CommonStrings.common_starting_chat))
}
is Async.Failure -> {
RetryDialog(
content = stringResource(id = R.string.screen_start_chat_error_starting_chat),
onDismiss = { state.eventSink(CreateRoomRootEvents.CancelStartDM) },
onRetry = {
state.userListState.selectedUsers.firstOrNull()
?.let { state.eventSink(CreateRoomRootEvents.StartDM(it)) }
// Cancel start DM if there is no more selected user (should not happen)
?: state.eventSink(CreateRoomRootEvents.CancelStartDM)
},
)
}
else -> Unit
}
AsyncView(
async = state.startDmAction,
progressText = stringResource(CommonStrings.common_starting_chat),
onSuccess = { onOpenDM(it) },
errorMessage = { stringResource(R.string.screen_start_chat_error_starting_chat) },
onRetry = {
state.userListState.selectedUsers.firstOrNull()
?.let { state.eventSink(CreateRoomRootEvents.StartDM(it)) }
// Cancel start DM if there is no more selected user (should not happen)
?: state.eventSink(CreateRoomRootEvents.CancelStartDM)
},
onErrorDismiss = { state.eventSink(CreateRoomRootEvents.CancelStartDM) },
)
}
@OptIn(ExperimentalMaterial3Api::class)

27
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcView.kt

@ -25,17 +25,14 @@ import androidx.compose.runtime.getValue @@ -25,17 +25,14 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.viewinterop.AndroidView
import io.element.android.features.login.impl.oidc.OidcUrlParser
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.components.async.AsyncView
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
@Composable
fun OidcView(
@ -79,21 +76,11 @@ fun OidcView( @@ -79,21 +76,11 @@ fun OidcView(
}
)
when (state.requestState) {
Async.Uninitialized -> Unit
is Async.Failure -> {
ErrorDialog(
content = state.requestState.error.toString(),
onDismiss = { state.eventSink(OidcEvents.ClearError) }
)
}
is Async.Loading -> {
CircularProgressIndicator(
modifier = Modifier.align(Alignment.Center)
)
}
is Async.Success -> onNavigateBack()
}
AsyncView(
async = state.requestState,
onSuccess = { onNavigateBack() },
onErrorDismiss = { state.eventSink(OidcEvents.ClearError) }
)
}
}

27
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageView.kt

@ -34,7 +34,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api @@ -34,7 +34,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Switch
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.stringResource
@ -42,10 +41,10 @@ import androidx.compose.ui.text.style.TextAlign @@ -42,10 +41,10 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.components.async.AsyncView
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
@ -64,21 +63,13 @@ fun ReportMessageView( @@ -64,21 +63,13 @@ fun ReportMessageView(
) {
val focusManager = LocalFocusManager.current
val isSending = state.result is Async.Loading
when (state.result) {
is Async.Success -> {
LaunchedEffect(state.result) {
onBackClicked()
}
return
}
is Async.Failure -> {
ErrorDialog(
content = stringResource(CommonStrings.error_unknown),
onDismiss = { state.eventSink(ReportMessageEvents.ClearError) }
)
}
else -> Unit
}
AsyncView(
async = state.result,
showProgressDialog = false,
onSuccess = { onBackClicked() },
errorMessage = { stringResource(CommonStrings.error_unknown) },
onErrorDismiss = { state.eventSink(ReportMessageEvents.ClearError) }
)
Scaffold(
topBar = {

22
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt

@ -24,9 +24,8 @@ import androidx.compose.ui.res.stringResource @@ -24,9 +24,8 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.lifecycle.Lifecycle
import io.element.android.libraries.androidutils.system.startNotificationSettingsIntent
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.atomic.molecules.DialogLikeBannerMolecule
import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.async.AsyncView
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
@ -79,19 +78,12 @@ fun NotificationSettingsView( @@ -79,19 +78,12 @@ fun NotificationSettingsView(
// onCallsNotificationsChanged = { state.eventSink(NotificationSettingsEvents.SetCallNotificationsEnabled(it)) },
)
}
when (state.changeNotificationSettingAction) {
is Async.Loading -> {
ProgressDialog()
}
is Async.Failure -> {
ErrorDialog(
title = stringResource(CommonStrings.dialog_title_error),
content = stringResource(CommonStrings.screen_notification_settings_edit_failed_updating_default_mode),
onDismiss = { state.eventSink(NotificationSettingsEvents.ClearNotificationChangeError) },
)
}
else -> Unit
}
AsyncView(
async = state.changeNotificationSettingAction,
errorMessage = { stringResource(CommonStrings.screen_notification_settings_edit_failed_updating_default_mode) },
onErrorDismiss = { state.eventSink(NotificationSettingsEvents.ClearNotificationChangeError) },
onSuccess = {},
)
}
}

31
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt

@ -22,20 +22,18 @@ import androidx.compose.runtime.Composable @@ -22,20 +22,18 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.async.AsyncView
import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.components.list.ListItemContent
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.ListItem
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.ui.strings.CommonStrings
@ -46,11 +44,10 @@ import io.element.android.libraries.ui.strings.CommonStrings @@ -46,11 +44,10 @@ import io.element.android.libraries.ui.strings.CommonStrings
@Composable
fun EditDefaultNotificationSettingView(
state: EditDefaultNotificationSettingState,
openRoomNotificationSettings:(roomId: RoomId) -> Unit,
openRoomNotificationSettings: (roomId: RoomId) -> Unit,
onBackPressed: () -> Unit,
modifier: Modifier = Modifier,
) {
val title = if (state.isOneToOne) {
CommonStrings.screen_notification_settings_direct_chats
} else {
@ -118,21 +115,15 @@ fun EditDefaultNotificationSettingView( @@ -118,21 +115,15 @@ fun EditDefaultNotificationSettingView(
}
}
}
when (state.changeNotificationSettingAction) {
is Async.Loading -> {
ProgressDialog()
}
is Async.Failure -> {
ErrorDialog(
title = stringResource(CommonStrings.dialog_title_error),
content = stringResource(CommonStrings.screen_notification_settings_edit_failed_updating_default_mode),
onDismiss = { state.eventSink(EditDefaultNotificationSettingStateEvents.ClearError) },
)
}
else -> Unit
}
AsyncView(
async = state.changeNotificationSettingAction,
errorMessage = { stringResource(CommonStrings.screen_notification_settings_edit_failed_updating_default_mode) },
onErrorDismiss = { state.eventSink(EditDefaultNotificationSettingStateEvents.ClearError) },
onSuccess = {},
)
}
}
@PreviewsDayNight
@Composable
internal fun EditDefaultNotificationSettingViewPreview(

33
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt

@ -31,7 +31,6 @@ import androidx.compose.material.ModalBottomSheetValue @@ -31,7 +31,6 @@ import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -43,14 +42,12 @@ import androidx.compose.ui.text.style.TextAlign @@ -43,14 +42,12 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.features.preferences.impl.R
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.components.LabelledOutlinedTextField
import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.async.AsyncView
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
@ -150,24 +147,14 @@ fun EditUserProfileView( @@ -150,24 +147,14 @@ fun EditUserProfileView(
onActionSelected = { state.eventSink(EditUserProfileEvents.HandleAvatarAction(it)) }
)
when (state.saveAction) {
is Async.Loading -> {
ProgressDialog(text = stringResource(R.string.screen_edit_profile_updating_details))
}
is Async.Failure -> {
ErrorDialog(
title = stringResource(R.string.screen_edit_profile_error_title),
content = stringResource(R.string.screen_edit_profile_error),
onDismiss = { state.eventSink(EditUserProfileEvents.CancelSaveChanges) },
)
}
is Async.Success -> {
LaunchedEffect(state.saveAction) {
onProfileEdited()
}
}
else -> Unit
}
AsyncView(
async = state.saveAction,
progressText = stringResource(R.string.screen_edit_profile_updating_details),
onSuccess = { onProfileEdited() },
errorTitle = { stringResource(R.string.screen_edit_profile_error_title) },
errorMessage = { stringResource(R.string.screen_edit_profile_error) },
onErrorDismiss = { state.eventSink(EditUserProfileEvents.CancelSaveChanges) },
)
}
PermissionsView(
state = state.cameraPermissionState,

38
features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt

@ -23,7 +23,6 @@ import androidx.compose.foundation.layout.height @@ -23,7 +23,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
@ -39,16 +38,15 @@ import coil.compose.AsyncImage @@ -39,16 +38,15 @@ import coil.compose.AsyncImage
import coil.request.ImageRequest
import io.element.android.features.rageshake.impl.R
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.components.async.AsyncView
import io.element.android.libraries.designsystem.components.form.textFieldState
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
import io.element.android.libraries.designsystem.components.preferences.PreferenceRow
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.debugPlaceholderBackground
import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.LogCompositions
@ -63,13 +61,6 @@ fun BugReportView( @@ -63,13 +61,6 @@ fun BugReportView(
) {
LogCompositions(tag = "Rageshake", msg = "Root")
val eventSink = state.eventSink
if (state.sending is Async.Success) {
LaunchedEffect(state.sending) {
eventSink(BugReportEvents.ResetAll)
onDone()
}
return
}
Box(modifier = modifier) {
PreferencePage(
@ -151,6 +142,7 @@ fun BugReportView( @@ -151,6 +142,7 @@ fun BugReportView(
text = stringResource(id = CommonStrings.action_send),
onClick = { eventSink(BugReportEvents.SendBugReport) },
enabled = state.submitEnabled,
showProgress = state.sending.isLoading(),
modifier = Modifier
.fillMaxWidth()
.padding(top = 24.dp, bottom = 16.dp)
@ -158,19 +150,15 @@ fun BugReportView( @@ -158,19 +150,15 @@ fun BugReportView(
}
}
when (state.sending) {
is Async.Loading -> {
// Indeterminate indicator, to avoid the freeze effect if the connection takes time to initialize.
CircularProgressIndicator(
modifier = Modifier.align(Alignment.Center)
)
}
is Async.Failure -> ErrorDialog(
content = state.sending.error.toString(),
onDismiss = { state.eventSink(BugReportEvents.ClearError) }
)
else -> Unit
}
AsyncView(
async = state.sending,
showProgressDialog = false,
onSuccess = {
eventSink(BugReportEvents.ResetAll)
onDone()
},
onErrorDismiss = { eventSink(BugReportEvents.ClearError) },
)
}
}

34
features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/edit/RoomDetailsEditView.kt

@ -36,7 +36,6 @@ import androidx.compose.material.rememberModalBottomSheetState @@ -36,7 +36,6 @@ import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusManager
@ -47,14 +46,12 @@ import androidx.compose.ui.text.input.KeyboardCapitalization @@ -47,14 +46,12 @@ import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.features.roomdetails.impl.R
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.components.LabelledTextField
import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.async.AsyncView
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
@ -174,26 +171,13 @@ fun RoomDetailsEditView( @@ -174,26 +171,13 @@ fun RoomDetailsEditView(
onActionSelected = { state.eventSink(RoomDetailsEditEvents.HandleAvatarAction(it)) }
)
when (state.saveAction) {
is Async.Loading -> {
ProgressDialog(text = stringResource(R.string.screen_room_details_updating_room))
}
is Async.Failure -> {
ErrorDialog(
content = stringResource(R.string.screen_room_details_edition_error),
onDismiss = { state.eventSink(RoomDetailsEditEvents.CancelSaveChanges) },
)
}
is Async.Success -> {
LaunchedEffect(state.saveAction) {
onRoomEdited()
}
}
else -> Unit
}
AsyncView(
async = state.saveAction,
progressText = stringResource(R.string.screen_room_details_updating_room),
onSuccess = { onRoomEdited() },
errorMessage = { stringResource(R.string.screen_room_details_edition_error) },
onErrorDismiss = { state.eventSink(RoomDetailsEditEvents.CancelSaveChanges) }
)
PermissionsView(
state = state.cameraPermissionState,

43
features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt

@ -32,9 +32,8 @@ import androidx.compose.ui.text.style.TextAlign @@ -32,9 +32,8 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.features.roomdetails.impl.R
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.core.bool.orTrue
import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.async.AsyncView
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
@ -49,7 +48,6 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationMode @@ -49,7 +48,6 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings
@Composable
fun RoomNotificationSettingsView(
state: RoomNotificationSettingsState,
@ -57,7 +55,7 @@ fun RoomNotificationSettingsView( @@ -57,7 +55,7 @@ fun RoomNotificationSettingsView(
onShowGlobalNotifications: () -> Unit = {},
onBackPressed: () -> Unit = {},
) {
if(state.showUserDefinedSettingStyle) {
if (state.showUserDefinedSettingStyle) {
UserDefinedRoomNotificationSettingsView(
state = state,
modifier = modifier,
@ -117,7 +115,7 @@ private fun RoomSpecificNotificationSettingsView( @@ -117,7 +115,7 @@ private fun RoomSpecificNotificationSettingsView(
ClickableText(
text = text,
onClick = {
onShowGlobalNotifications()
onShowGlobalNotifications()
},
modifier = Modifier
.padding(start = 16.dp, bottom = 16.dp, end = 16.dp),
@ -127,7 +125,7 @@ private fun RoomSpecificNotificationSettingsView( @@ -127,7 +125,7 @@ private fun RoomSpecificNotificationSettingsView(
textAlign = TextAlign.Center,
)
)
if(state.defaultRoomNotificationMode != null){
if (state.defaultRoomNotificationMode != null) {
val defaultModeTitle = when (state.defaultRoomNotificationMode) {
RoomNotificationMode.ALL_MESSAGES -> stringResource(id = R.string.screen_room_notification_settings_mode_all_messages)
RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> {
@ -150,29 +148,24 @@ private fun RoomSpecificNotificationSettingsView( @@ -150,29 +148,24 @@ private fun RoomSpecificNotificationSettingsView(
enabled = !state.displayIsDefault.orTrue(),
onOptionSelected = {
state.eventSink(RoomNotificationSettingsEvents.RoomNotificationModeChanged(it.mode))
},)
},
)
}
}
when (state.setNotificationSettingAction) {
is Async.Loading -> {
ProgressDialog()
}
is Async.Failure -> {
ShowChangeNotificationSettingError(state, RoomNotificationSettingsEvents.ClearSetNotificationError)
}
else -> Unit
}
AsyncView(
async = state.setNotificationSettingAction,
onSuccess = {},
errorMessage = { stringResource(CommonStrings.screen_notification_settings_edit_failed_updating_default_mode) },
onErrorDismiss = { state.eventSink(RoomNotificationSettingsEvents.ClearSetNotificationError) },
)
when (state.restoreDefaultAction) {
is Async.Loading -> {
ProgressDialog()
}
is Async.Failure -> {
ShowChangeNotificationSettingError(state, RoomNotificationSettingsEvents.ClearRestoreDefaultError)
}
else -> Unit
}
AsyncView(
async = state.restoreDefaultAction,
onSuccess = {},
errorMessage = { stringResource(CommonStrings.screen_notification_settings_edit_failed_updating_default_mode) },
onErrorDismiss = { state.eventSink(RoomNotificationSettingsEvents.ClearRestoreDefaultError) },
)
}
}
}

31
features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/ShowChangeNotificationSettingError.kt

@ -1,31 +0,0 @@ @@ -1,31 +0,0 @@
/*
* 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.roomdetails.impl.notificationsettings
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.ui.strings.CommonStrings
@Composable
fun ShowChangeNotificationSettingError(state: RoomNotificationSettingsState, event: RoomNotificationSettingsEvents) {
ErrorDialog(
title = stringResource(CommonStrings.dialog_title_error),
content = stringResource(CommonStrings.screen_notification_settings_edit_failed_updating_default_mode),
onDismiss = { state.eventSink(event) },
)
}

40
features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/UserDefinedRoomNotificationSettingsView.kt

@ -24,7 +24,6 @@ import androidx.compose.foundation.layout.padding @@ -24,7 +24,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
@ -32,9 +31,8 @@ import androidx.compose.ui.res.vectorResource @@ -32,9 +31,8 @@ import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.features.roomdetails.impl.R
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.core.bool.orTrue
import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.async.AsyncView
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
import io.element.android.libraries.designsystem.preview.ElementPreview
@ -43,6 +41,7 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold @@ -43,6 +41,7 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.ui.strings.CommonStrings
@Composable
fun UserDefinedRoomNotificationSettingsView(
@ -86,30 +85,19 @@ fun UserDefinedRoomNotificationSettingsView( @@ -86,30 +85,19 @@ fun UserDefinedRoomNotificationSettingsView(
}
)
when (state.setNotificationSettingAction) {
is Async.Loading -> {
ProgressDialog()
}
is Async.Failure -> {
ShowChangeNotificationSettingError(state, RoomNotificationSettingsEvents.ClearSetNotificationError)
}
else -> Unit
}
AsyncView(
async = state.setNotificationSettingAction,
onSuccess = {},
errorMessage = { stringResource(CommonStrings.screen_notification_settings_edit_failed_updating_default_mode) },
onErrorDismiss = { state.eventSink(RoomNotificationSettingsEvents.ClearSetNotificationError) },
)
when (state.restoreDefaultAction) {
is Async.Loading -> {
ProgressDialog()
}
is Async.Failure -> {
ShowChangeNotificationSettingError(state, RoomNotificationSettingsEvents.ClearRestoreDefaultError)
}
is Async.Success -> {
LaunchedEffect(state.restoreDefaultAction) {
onBackPressed()
}
}
else -> Unit
}
AsyncView(
async = state.restoreDefaultAction,
onSuccess = { onBackPressed() },
errorMessage = { stringResource(CommonStrings.screen_notification_settings_edit_failed_updating_default_mode) },
onErrorDismiss = { state.eventSink(RoomNotificationSettingsEvents.ClearRestoreDefaultError) },
)
}
}
}

23
features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyView.kt

@ -20,19 +20,17 @@ import androidx.compose.foundation.layout.fillMaxWidth @@ -20,19 +20,17 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.features.securebackup.impl.R
import io.element.android.features.securebackup.impl.setup.views.RecoveryKeyView
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.components.async.AsyncView
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Button
@ -48,19 +46,12 @@ fun SecureBackupEnterRecoveryKeyView( @@ -48,19 +46,12 @@ fun SecureBackupEnterRecoveryKeyView(
onBackClicked: () -> Unit,
modifier: Modifier = Modifier,
) {
when (state.submitAction) {
Async.Uninitialized -> Unit
is Async.Failure -> ErrorDialog(
content = state.submitAction.error.message ?: state.submitAction.error.toString(),
onDismiss = {
state.eventSink(SecureBackupEnterRecoveryKeyEvents.ClearDialog)
}
)
is Async.Loading -> Unit
is Async.Success -> LaunchedEffect(state.submitAction) {
onDone()
}
}
AsyncView(
async = state.submitAction,
onSuccess = { onDone() },
showProgressDialog = false,
onErrorDismiss = { state.eventSink(SecureBackupEnterRecoveryKeyEvents.ClearDialog) },
)
HeaderFooterPage(
modifier = modifier,

1
libraries/designsystem/build.gradle.kts

@ -39,6 +39,7 @@ android { @@ -39,6 +39,7 @@ android {
// Should not be there, but this is a POC
implementation(libs.coil.compose)
implementation(libs.vanniktech.blurhash)
implementation(projects.libraries.architecture)
implementation(projects.libraries.testtags)
implementation(projects.libraries.uiStrings)

30
libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncProvider.kt

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
/*
* 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.designsystem.components.async
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.architecture.Async
open class AsyncProvider : PreviewParameterProvider<Async<Unit>> {
override val values: Sequence<Async<Unit>>
get() = sequenceOf(
Async.Uninitialized,
Async.Loading(),
Async.Failure(Exception("An error occurred")),
Async.Success(Unit),
)
}

119
libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncView.kt

@ -0,0 +1,119 @@ @@ -0,0 +1,119 @@
/*
* 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.designsystem.components.async
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialogDefaults
import io.element.android.libraries.designsystem.components.dialogs.RetryDialog
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
/**
* Render an Async object.
* - If Success, invoke the callback [onSuccess], only once.
* - If Failure, display a dialog with the error, which can be transformed, using [errorMessage]. When
* closed, [onErrorDismiss] will be invoked. If [onRetry] is not null, a retry button will be displayed.
* - When loading, display a loading dialog, if [showProgressDialog] is true, with on optional [progressText].
*/
@Composable
fun <T> AsyncView(
async: Async<T>,
onSuccess: (T) -> Unit,
onErrorDismiss: () -> Unit,
showProgressDialog: Boolean = true,
progressText: String? = null,
errorTitle: @Composable (Throwable) -> String = { ErrorDialogDefaults.title },
errorMessage: @Composable (Throwable) -> String = { it.message ?: it.toString() },
onRetry: (() -> Unit)? = null,
) {
AsyncView(
async = async,
onSuccess = onSuccess,
onErrorDismiss = onErrorDismiss,
progressDialog = {
if (showProgressDialog) {
AsyncViewDefaults.ProgressDialog(progressText)
}
},
errorTitle = errorTitle,
errorMessage = errorMessage,
onRetry = onRetry,
)
}
@Composable
fun <T> AsyncView(
async: Async<T>,
onSuccess: (T) -> Unit,
onErrorDismiss: () -> Unit,
progressDialog: @Composable () -> Unit = { AsyncViewDefaults.ProgressDialog() },
errorTitle: @Composable (Throwable) -> String = { ErrorDialogDefaults.title },
errorMessage: @Composable (Throwable) -> String = { it.message ?: it.toString() },
onRetry: (() -> Unit)? = null,
) {
when (async) {
Async.Uninitialized -> Unit
is Async.Loading -> progressDialog()
is Async.Failure -> {
if (onRetry == null) {
ErrorDialog(
title = errorTitle(async.error),
content = errorMessage(async.error),
onDismiss = onErrorDismiss
)
} else {
RetryDialog(
title = errorTitle(async.error),
content = errorMessage(async.error),
onDismiss = onErrorDismiss,
onRetry = onRetry,
)
}
}
is Async.Success -> {
LaunchedEffect(async) {
onSuccess(async.data)
}
}
}
}
object AsyncViewDefaults {
@Composable
fun ProgressDialog(progressText: String? = null) {
ProgressDialog(
text = progressText,
)
}
}
@PreviewsDayNight
@Composable
internal fun AsyncViewPreview(
@PreviewParameter(AsyncProvider::class) async: Async<Unit>,
) = ElementPreview {
AsyncView(
async = async,
onSuccess = {},
onErrorDismiss = {},
)
}

2
tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt

@ -55,6 +55,8 @@ class KonsistClassNameTest { @@ -55,6 +55,8 @@ class KonsistClassNameTest {
val providedType = it.text
.substringBefore(">")
.substringAfter("<")
// Get the substring before the first '<' to remove the generic type
.substringBefore("<")
.removeSuffix("?")
.replace(".", "")
it.name.endsWith("Provider") && it.name.contains(providedType)

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.oidc.webview_OidcView_null_OidcView-Day-3_4_null_1,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.oidc.webview_OidcView_null_OidcView-Night-3_5_null_1,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Day-7_7_null_5,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Night-7_8_null_5,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Day-0_0_null_2,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Day-0_0_null_3,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Night-0_1_null_2,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Night-0_1_null_3,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Day_0_null_0,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Day_0_null_1,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Day_0_null_2,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Day_0_null_3,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Night_1_null_0,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Night_1_null_1,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Night_1_null_2,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.async_AsyncView_null_AsyncView-Night_1_null_3,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.
Loading…
Cancel
Save