diff options
| author | 2024-01-29 07:12:30 +0000 | |
|---|---|---|
| committer | 2024-02-06 01:09:44 +0000 | |
| commit | 3e352e4ebf69801ac03f05eadaf08aacfe8cf1f2 (patch) | |
| tree | 90b6db7b3a0bafc913987e5fbee66a0d41fdd95f | |
| parent | 6892184b02d5f7a5b6f320731e37bd6b83da4fb9 (diff) | |
Single provider password screen changes
Test: Manual. See go/credential-selector-ui
Bug: 322797031
Change-Id: I3a955f8e5d86bdb4c316daee8009db55fa28cc23
| -rw-r--r-- | packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt | 6 | ||||
| -rw-r--r-- | packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/UiState.kt (renamed from packages/CredentialManager/wear/src/com/android/credentialmanager/ui/model/PasswordUiModel.kt) | 18 | ||||
| -rw-r--r-- | packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt | 72 | ||||
| -rw-r--r-- | packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreenViewModel.kt | 43 |
4 files changed, 69 insertions, 70 deletions
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt index 790f5b1f27f3..f8e22eed90f0 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -58,9 +58,9 @@ fun WearApp( scrollable(Screen.SinglePasswordScreen.route) { SinglePasswordScreen( - state = viewModel.uiState.value as SingleEntry, + credentialSelectorUiState = viewModel.uiState.value as SingleEntry, + screenIcon = null, columnState = it.columnState, - onCloseApp = onCloseApp, ) } } diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/model/PasswordUiModel.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/UiState.kt index 52bbfaa818ed..42a88e2ea303 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/model/PasswordUiModel.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/UiState.kt @@ -1,11 +1,11 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * 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.0N + * 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, @@ -14,6 +14,16 @@ * limitations under the License. */ -package com.android.credentialmanager.ui.model +package com.android.credentialmanager.ui.screens.single -data class PasswordUiModel(val email: String) +import androidx.activity.result.IntentSenderRequest + +sealed class UiState { + data object CredentialScreen : UiState() + + data class CredentialSelected( + val intentSenderRequest: IntentSenderRequest? + ) : UiState() + + data object Cancel : UiState() +}
\ No newline at end of file diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt index 95ef7dbfef30..a8be94466a2e 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt @@ -18,8 +18,9 @@ package com.android.credentialmanager.ui.screens.single.password -import android.util.Log +import android.graphics.drawable.Drawable import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.SideEffect @@ -29,47 +30,52 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.android.credentialmanager.CredentialSelectorUiState.Get.SingleEntry +import androidx.navigation.NavHostController +import androidx.navigation.compose.rememberNavController +import com.android.credentialmanager.CredentialSelectorUiState import com.android.credentialmanager.R -import com.android.credentialmanager.TAG import com.android.credentialmanager.activity.StartBalIntentSenderForResultContract import com.android.credentialmanager.ui.components.PasswordRow +import com.android.credentialmanager.ui.components.ContinueChip +import com.android.credentialmanager.ui.components.DismissChip import com.android.credentialmanager.ui.components.SignInHeader -import com.android.credentialmanager.ui.model.PasswordUiModel +import com.android.credentialmanager.ui.components.SignInOptionsChip import com.android.credentialmanager.ui.screens.single.SingleAccountScreen +import com.android.credentialmanager.model.get.CredentialEntryInfo +import com.android.credentialmanager.ui.screens.single.UiState import com.google.android.horologist.annotations.ExperimentalHorologistApi import com.google.android.horologist.compose.layout.ScalingLazyColumnState +@OptIn(ExperimentalHorologistApi::class) @Composable fun SinglePasswordScreen( - state: SingleEntry, + credentialSelectorUiState: CredentialSelectorUiState.Get.SingleEntry, + screenIcon: Drawable?, columnState: ScalingLazyColumnState, - onCloseApp: () -> Unit, modifier: Modifier = Modifier, viewModel: SinglePasswordScreenViewModel = hiltViewModel(), + navController: NavHostController = rememberNavController(), ) { - viewModel.initialize(state.entry) + viewModel.initialize(credentialSelectorUiState.entry) val uiState by viewModel.uiState.collectAsStateWithLifecycle() when (val state = uiState) { - SinglePasswordScreenUiState.Idle -> { - // TODO: b/301206470 implement latency version of the screen - } - - is SinglePasswordScreenUiState.Loaded -> { + UiState.CredentialScreen -> { SinglePasswordScreen( - passwordUiModel = state.passwordUiModel, - columnState = columnState, - modifier = modifier + credentialSelectorUiState.entry, + screenIcon, + columnState, + modifier, + viewModel ) } - is SinglePasswordScreenUiState.PasswordSelected -> { + is UiState.CredentialSelected -> { val launcher = rememberLauncherForActivityResult( StartBalIntentSenderForResultContract() ) { - viewModel.onPasswordInfoRetrieved(it.resultCode, it.data) + viewModel.onPasswordInfoRetrieved(it.resultCode, null) } SideEffect { @@ -79,37 +85,32 @@ fun SinglePasswordScreen( } } - SinglePasswordScreenUiState.Cancel -> { - // TODO: b/301206470 implement navigation for when user taps cancel - } - - SinglePasswordScreenUiState.Error -> { - // TODO: b/301206470 implement navigation for when there is an error to load screen - } - - SinglePasswordScreenUiState.Completed -> { - Log.d(TAG, "Received signal to finish the activity.") - onCloseApp() + UiState.Cancel -> { + // TODO(b/322797032) add valid navigation path here for going back + navController.popBackStack() } } } +@OptIn(ExperimentalHorologistApi::class) @Composable -fun SinglePasswordScreen( - passwordUiModel: PasswordUiModel, +private fun SinglePasswordScreen( + entry: CredentialEntryInfo, + screenIcon: Drawable?, columnState: ScalingLazyColumnState, modifier: Modifier = Modifier, + viewModel: SinglePasswordScreenViewModel, ) { SingleAccountScreen( headerContent = { SignInHeader( - icon = null, + icon = screenIcon, title = stringResource(R.string.use_password_title), ) }, accountContent = { PasswordRow( - email = passwordUiModel.email, + email = entry.userName, modifier = Modifier.padding(top = 10.dp), ) }, @@ -117,6 +118,13 @@ fun SinglePasswordScreen( modifier = modifier.padding(horizontal = 10.dp) ) { item { + Column { + ContinueChip(viewModel::onContinueClick) + SignInOptionsChip(viewModel::onSignInOptionsClick) + DismissChip(viewModel::onDismissClick) + } } } } + + diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreenViewModel.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreenViewModel.kt index c9c66b4a7271..3f841b8af146 100644 --- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreenViewModel.kt +++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreenViewModel.kt @@ -17,16 +17,15 @@ package com.android.credentialmanager.ui.screens.single.password import android.content.Intent -import android.credentials.selection.ProviderPendingIntentResponse import android.credentials.selection.UserSelectionDialogResult -import androidx.activity.result.IntentSenderRequest +import android.credentials.selection.ProviderPendingIntentResponse import androidx.annotation.MainThread import androidx.lifecycle.ViewModel import com.android.credentialmanager.ktx.getIntentSenderRequest import com.android.credentialmanager.model.Request import com.android.credentialmanager.client.CredentialManagerClient import com.android.credentialmanager.model.get.CredentialEntryInfo -import com.android.credentialmanager.ui.model.PasswordUiModel +import com.android.credentialmanager.ui.screens.single.UiState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -37,36 +36,31 @@ class SinglePasswordScreenViewModel @Inject constructor( private val credentialManagerClient: CredentialManagerClient, ) : ViewModel() { - private var initializeCalled = false - private lateinit var requestGet: Request.Get private lateinit var entryInfo: CredentialEntryInfo private val _uiState = - MutableStateFlow<SinglePasswordScreenUiState>(SinglePasswordScreenUiState.Idle) - val uiState: StateFlow<SinglePasswordScreenUiState> = _uiState + MutableStateFlow<UiState>(UiState.CredentialScreen) + val uiState: StateFlow<UiState> = _uiState @MainThread fun initialize(entryInfo: CredentialEntryInfo) { - if (initializeCalled) return - initializeCalled = true - _uiState.value = SinglePasswordScreenUiState.Loaded( - PasswordUiModel( - email = entryInfo.userName, - ) - ) + this.entryInfo = entryInfo } - fun onCancelClick() { - _uiState.value = SinglePasswordScreenUiState.Cancel + fun onDismissClick() { + _uiState.value = UiState.Cancel } - fun onOKClick() { - _uiState.value = SinglePasswordScreenUiState.PasswordSelected( + fun onContinueClick() { + _uiState.value = UiState.CredentialSelected( intentSenderRequest = entryInfo.getIntentSenderRequest() ) } + fun onSignInOptionsClick() { + } + fun onPasswordInfoRetrieved( resultCode: Int? = null, resultData: Intent? = null, @@ -79,18 +73,5 @@ class SinglePasswordScreenViewModel @Inject constructor( if (resultCode != null) ProviderPendingIntentResponse(resultCode, resultData) else null ) credentialManagerClient.sendResult(userSelectionDialogResult) - _uiState.value = SinglePasswordScreenUiState.Completed } } - -sealed class SinglePasswordScreenUiState { - data object Idle : SinglePasswordScreenUiState() - data class Loaded(val passwordUiModel: PasswordUiModel) : SinglePasswordScreenUiState() - data class PasswordSelected( - val intentSenderRequest: IntentSenderRequest? - ) : SinglePasswordScreenUiState() - - data object Cancel : SinglePasswordScreenUiState() - data object Error : SinglePasswordScreenUiState() - data object Completed : SinglePasswordScreenUiState() -} |