diff --git a/features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt b/features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt index 1a2a581265..8ac71ab9c9 100644 --- a/features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt +++ b/features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt @@ -7,15 +7,18 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Visibility +import androidx.compose.material.icons.filled.VisibilityOff import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction -import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -61,8 +64,6 @@ fun LoginContent( onSubmitClicked: () -> Unit = {}, onLoginWithSuccess: () -> Unit = {}, ) { - var login by textFieldState(state.login) - var password by textFieldState(state.password) Surface(color = MaterialTheme.colorScheme.background) { Box( modifier = Modifier @@ -116,6 +117,7 @@ fun LoginContent( } ) } + var login by textFieldState(state.login) OutlinedTextField( value = login, modifier = Modifier @@ -133,6 +135,12 @@ fun LoginContent( imeAction = ImeAction.Next ), ) + var passwordVisible by remember { mutableStateOf(false) } + var password by textFieldState(state.password) + if (state.isLoggedIn is Loading) { + // Ensure password is hidden when user submits the form + passwordVisible = false + } OutlinedTextField( value = password, modifier = Modifier @@ -146,11 +154,21 @@ fun LoginContent( Text(text = "Password") }, isError = isError, + visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), + trailingIcon = { + val image = + if (passwordVisible) Icons.Filled.Visibility else Icons.Filled.VisibilityOff + val description = + if (passwordVisible) "Hide password" else "Show password" + + IconButton(onClick = { passwordVisible = !passwordVisible }) { + Icon(imageVector = image, description) + } + }, keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Password, imeAction = ImeAction.Done, ), - visualTransformation = PasswordVisualTransformation(), keyboardActions = KeyboardActions( onDone = { onSubmitClicked() } ), diff --git a/features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt b/features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt index aaca27e4ad..5c7690cd19 100644 --- a/features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt +++ b/features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt @@ -1,7 +1,5 @@ package io.element.android.x.features.login -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue import com.airbnb.mvrx.MavericksViewModel import com.airbnb.mvrx.Uninitialized import io.element.android.x.matrix.MatrixInstance diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt index df8233f02d..0b222413a0 100644 --- a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt +++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt @@ -1,14 +1,13 @@ package io.element.android.x.features.roomlist -import com.airbnb.mvrx.MavericksViewModel -import com.airbnb.mvrx.MavericksViewModelFactory -import com.airbnb.mvrx.ViewModelContext +import com.airbnb.mvrx.* import io.element.android.x.core.data.parallelMap import io.element.android.x.designsystem.components.avatar.AvatarData import io.element.android.x.designsystem.components.avatar.AvatarSize import io.element.android.x.features.roomlist.model.MatrixUser import io.element.android.x.features.roomlist.model.RoomListRoomSummary import io.element.android.x.features.roomlist.model.RoomListViewState +import io.element.android.x.features.roomlist.model.createFakePlaceHolders import io.element.android.x.matrix.MatrixClient import io.element.android.x.matrix.MatrixInstance import io.element.android.x.matrix.media.MediaResolver @@ -80,7 +79,19 @@ class RoomListViewModel( .map(::mapRoomSummaries) .flowOn(Dispatchers.Default) .execute { - copy(rooms = it) + copy( + rooms = when { + it is Loading || + // Note: this second case will prevent to handle correctly the empty case + (it is Success && it().isEmpty()) -> { + // Show fake placeholders to avoid having empty screen + Loading(createFakePlaceHolders()) + } + else -> { + it + } + } + ) } } diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/RoomListSummaryPlaceholders.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/RoomListSummaryPlaceholders.kt new file mode 100644 index 0000000000..aafb6bcada --- /dev/null +++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/RoomListSummaryPlaceholders.kt @@ -0,0 +1,13 @@ +package io.element.android.x.features.roomlist.model + + +/** + * Create a list of 16 RoomListRoomSummary placeholders + */ +fun createFakePlaceHolders(): List { + return mutableListOf().apply { + for (i in 0..15) { + add(RoomListRoomSummary.placeholder("\$fakeRoom$i")) + } + } +} diff --git a/plugins/src/main/java/io.element.android-compose.gradle.kts b/plugins/src/main/java/io.element.android-compose.gradle.kts index d9544bd098..ccc0db6937 100644 --- a/plugins/src/main/java/io.element.android-compose.gradle.kts +++ b/plugins/src/main/java/io.element.android-compose.gradle.kts @@ -19,6 +19,7 @@ dependencies { implementation("androidx.compose.ui:ui") implementation("androidx.compose.material:material") implementation("androidx.compose.material3:material3") + implementation("androidx.compose.material:material-icons-extended") implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.5.1") implementation("androidx.activity:activity-compose:1.6.1")