summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Helen Qin <helenqin@google.com> 2022-09-23 17:45:40 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-09-23 17:45:40 +0000
commit6b5cf8a1b691081611aae4e82fb6269ea1f82ffd (patch)
tree44e07fda325c7ff0f1a80cf93c9ae74e7efb8ddc
parent94444a89d29358ce0fd220851522aca568d7b1cf (diff)
parentb802ce00d56ac8ceca1688afbba50c5b1e7968aa (diff)
Merge "UX impovements: removed navigation & smoothen dialog transition."
-rw-r--r--packages/CredentialManager/Android.bp1
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt148
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt59
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/DialogType.kt18
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt11
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyComponents.kt195
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyViewModel.kt49
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt65
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt28
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt5
10 files changed, 221 insertions, 358 deletions
diff --git a/packages/CredentialManager/Android.bp b/packages/CredentialManager/Android.bp
index ed92af997a68..51943fffb36d 100644
--- a/packages/CredentialManager/Android.bp
+++ b/packages/CredentialManager/Android.bp
@@ -26,7 +26,6 @@ android_app {
"androidx.lifecycle_lifecycle-livedata",
"androidx.lifecycle_lifecycle-runtime-ktx",
"androidx.lifecycle_lifecycle-viewmodel-compose",
- "androidx.navigation_navigation-compose",
"androidx.recyclerview_recyclerview",
],
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index f20104a19af2..59186336056e 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -2,28 +2,86 @@ package com.android.credentialmanager
import android.content.Context
import com.android.credentialmanager.createflow.CreateOptionInfo
+import com.android.credentialmanager.createflow.CreatePasskeyUiState
+import com.android.credentialmanager.createflow.CreateScreenState
import com.android.credentialmanager.createflow.ProviderInfo
-import com.android.credentialmanager.createflow.ProviderList
import com.android.credentialmanager.getflow.CredentialOptionInfo
+import com.android.credentialmanager.getflow.GetCredentialUiState
+import com.android.credentialmanager.getflow.GetScreenState
+// Consider repo per screen, similar to view model?
class CredentialManagerRepo(
private val context: Context
) {
- fun getCredentialProviderList(): List<com.android.credentialmanager.getflow.ProviderInfo> {
+ private fun getCredentialProviderList():
+ List<com.android.credentialmanager.getflow.ProviderInfo> {
+ return listOf(
+ com.android.credentialmanager.getflow.ProviderInfo(
+ icon = context.getDrawable(R.drawable.ic_passkey)!!,
+ name = "Google Password Manager",
+ appDomainName = "tribank.us",
+ credentialTypeIcon = context.getDrawable(R.drawable.ic_passkey)!!,
+ credentialOptions = listOf(
+ CredentialOptionInfo(
+ icon = context.getDrawable(R.drawable.ic_passkey)!!,
+ title = "Elisa Backett",
+ subtitle = "elisa.beckett@gmail.com",
+ id = "id-1",
+ ),
+ CredentialOptionInfo(
+ icon = context.getDrawable(R.drawable.ic_passkey)!!,
+ title = "Elisa Backett Work",
+ subtitle = "elisa.beckett.work@google.com",
+ id = "id-2",
+ ),
+ )
+ ),
+ com.android.credentialmanager.getflow.ProviderInfo(
+ icon = context.getDrawable(R.drawable.ic_passkey)!!,
+ name = "Lastpass",
+ appDomainName = "tribank.us",
+ credentialTypeIcon = context.getDrawable(R.drawable.ic_passkey)!!,
+ credentialOptions = listOf(
+ CredentialOptionInfo(
+ icon = context.getDrawable(R.drawable.ic_passkey)!!,
+ title = "Elisa Backett",
+ subtitle = "elisa.beckett@lastpass.com",
+ id = "id-1",
+ ),
+ )
+ ),
+ com.android.credentialmanager.getflow.ProviderInfo(
+ icon = context.getDrawable(R.drawable.ic_passkey)!!,
+ name = "Dashlane",
+ appDomainName = "tribank.us",
+ credentialTypeIcon = context.getDrawable(R.drawable.ic_passkey)!!,
+ credentialOptions = listOf(
+ CredentialOptionInfo(
+ icon = context.getDrawable(R.drawable.ic_passkey)!!,
+ title = "Elisa Backett",
+ subtitle = "elisa.beckett@dashlane.com",
+ id = "id-1",
+ ),
+ )
+ ),
+ )
+ }
+
+ private fun createCredentialProviderList(): List<ProviderInfo> {
return listOf(
- com.android.credentialmanager.getflow.ProviderInfo(
+ ProviderInfo(
icon = context.getDrawable(R.drawable.ic_passkey)!!,
name = "Google Password Manager",
appDomainName = "tribank.us",
credentialTypeIcon = context.getDrawable(R.drawable.ic_passkey)!!,
- credentialOptions = listOf(
- CredentialOptionInfo(
+ createOptions = listOf(
+ CreateOptionInfo(
icon = context.getDrawable(R.drawable.ic_passkey)!!,
title = "Elisa Backett",
subtitle = "elisa.beckett@gmail.com",
id = "id-1",
),
- CredentialOptionInfo(
+ CreateOptionInfo(
icon = context.getDrawable(R.drawable.ic_passkey)!!,
title = "Elisa Backett Work",
subtitle = "elisa.beckett.work@google.com",
@@ -31,13 +89,13 @@ class CredentialManagerRepo(
),
)
),
- com.android.credentialmanager.getflow.ProviderInfo(
+ ProviderInfo(
icon = context.getDrawable(R.drawable.ic_passkey)!!,
name = "Lastpass",
appDomainName = "tribank.us",
credentialTypeIcon = context.getDrawable(R.drawable.ic_passkey)!!,
- credentialOptions = listOf(
- CredentialOptionInfo(
+ createOptions = listOf(
+ CreateOptionInfo(
icon = context.getDrawable(R.drawable.ic_passkey)!!,
title = "Elisa Backett",
subtitle = "elisa.beckett@lastpass.com",
@@ -45,13 +103,13 @@ class CredentialManagerRepo(
),
)
),
- com.android.credentialmanager.getflow.ProviderInfo(
+ ProviderInfo(
icon = context.getDrawable(R.drawable.ic_passkey)!!,
name = "Dashlane",
appDomainName = "tribank.us",
credentialTypeIcon = context.getDrawable(R.drawable.ic_passkey)!!,
- credentialOptions = listOf(
- CredentialOptionInfo(
+ createOptions = listOf(
+ CreateOptionInfo(
icon = context.getDrawable(R.drawable.ic_passkey)!!,
title = "Elisa Backett",
subtitle = "elisa.beckett@dashlane.com",
@@ -62,58 +120,20 @@ class CredentialManagerRepo(
)
}
- fun createCredentialProviderList(): ProviderList {
- return ProviderList(
- listOf(
- ProviderInfo(
- icon = context.getDrawable(R.drawable.ic_passkey)!!,
- name = "Google Password Manager",
- appDomainName = "tribank.us",
- credentialTypeIcon = context.getDrawable(R.drawable.ic_passkey)!!,
- createOptions = listOf(
- CreateOptionInfo(
- icon = context.getDrawable(R.drawable.ic_passkey)!!,
- title = "Elisa Backett",
- subtitle = "elisa.beckett@gmail.com",
- id = "id-1",
- ),
- CreateOptionInfo(
- icon = context.getDrawable(R.drawable.ic_passkey)!!,
- title = "Elisa Backett Work",
- subtitle = "elisa.beckett.work@google.com",
- id = "id-2",
- ),
- )
- ),
- ProviderInfo(
- icon = context.getDrawable(R.drawable.ic_passkey)!!,
- name = "Lastpass",
- appDomainName = "tribank.us",
- credentialTypeIcon = context.getDrawable(R.drawable.ic_passkey)!!,
- createOptions = listOf(
- CreateOptionInfo(
- icon = context.getDrawable(R.drawable.ic_passkey)!!,
- title = "Elisa Backett",
- subtitle = "elisa.beckett@lastpass.com",
- id = "id-1",
- ),
- )
- ),
- ProviderInfo(
- icon = context.getDrawable(R.drawable.ic_passkey)!!,
- name = "Dashlane",
- appDomainName = "tribank.us",
- credentialTypeIcon = context.getDrawable(R.drawable.ic_passkey)!!,
- createOptions = listOf(
- CreateOptionInfo(
- icon = context.getDrawable(R.drawable.ic_passkey)!!,
- title = "Elisa Backett",
- subtitle = "elisa.beckett@dashlane.com",
- id = "id-1",
- ),
- )
- ),
- )
+ fun getCredentialInitialUiState(): GetCredentialUiState {
+ val providerList = getCredentialProviderList()
+ return GetCredentialUiState(
+ providerList,
+ GetScreenState.CREDENTIAL_SELECTION,
+ providerList.first()
+ )
+ }
+
+ fun createPasskeyInitialUiState(): CreatePasskeyUiState {
+ val providerList = createCredentialProviderList()
+ return CreatePasskeyUiState(
+ providers = providerList,
+ currentScreenState = CreateScreenState.PASSKEY_INTRO,
)
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
index dd4ba11e9202..5cd6a13a377a 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
@@ -1,18 +1,14 @@
package com.android.credentialmanager
import android.os.Bundle
+import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.navigation.NavHostController
-import androidx.navigation.compose.NavHost
-import androidx.navigation.compose.rememberNavController
-import com.android.credentialmanager.createflow.CreatePasskeyViewModel
-import com.android.credentialmanager.createflow.createPasskeyGraph
-import com.android.credentialmanager.getflow.GetCredentialViewModel
-import com.android.credentialmanager.getflow.getCredentialsGraph
+import com.android.credentialmanager.common.DialogType
+import com.android.credentialmanager.createflow.CreatePasskeyScreen
+import com.android.credentialmanager.getflow.GetCredentialScreen
import com.android.credentialmanager.ui.theme.CredentialSelectorTheme
@ExperimentalMaterialApi
@@ -22,42 +18,35 @@ class CredentialSelectorActivity : ComponentActivity() {
CredentialManagerRepo.setup(this)
val startDestination = intent.extras?.getString(
"start_destination",
- "getCredentials"
- ) ?: "getCredentials"
+ "CREATE_PASSKEY"
+ ) ?: "CREATE_PASSKEY"
setContent {
CredentialSelectorTheme {
- AppNavHost(
- startDestination = startDestination,
- onCancel = {this.finish()}
- )
+ CredentialManagerBottomSheet(startDestination)
}
}
}
@ExperimentalMaterialApi
@Composable
- fun AppNavHost(
- modifier: Modifier = Modifier,
- navController: NavHostController = rememberNavController(),
- startDestination: String,
- onCancel: () -> Unit,
- ) {
- NavHost(
- modifier = modifier,
- navController = navController,
- startDestination = startDestination
- ) {
- createPasskeyGraph(
- navController = navController,
- viewModel = CreatePasskeyViewModel(CredentialManagerRepo.repo),
- onCancel = onCancel
- )
- getCredentialsGraph(
- navController = navController,
- viewModel = GetCredentialViewModel(CredentialManagerRepo.repo),
- onCancel = onCancel
- )
+ fun CredentialManagerBottomSheet(operationType: String) {
+ val dialogType = DialogType.toDialogType(operationType)
+ when (dialogType) {
+ DialogType.CREATE_PASSKEY -> {
+ CreatePasskeyScreen(cancelActivity = onCancel)
+ }
+ DialogType.GET_CREDENTIALS -> {
+ GetCredentialScreen(cancelActivity = onCancel)
+ }
+ else -> {
+ Log.w("AccountSelector", "Unknown type, not rendering any UI")
+ this.finish()
+ }
}
}
+
+ private val onCancel = {
+ this@CredentialSelectorActivity.finish()
+ }
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/DialogType.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/DialogType.kt
new file mode 100644
index 000000000000..8bb80a1b02fd
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/DialogType.kt
@@ -0,0 +1,18 @@
+package com.android.credentialmanager.common
+
+enum class DialogType {
+ CREATE_PASSKEY,
+ GET_CREDENTIALS,
+ CREATE_PASSWORD,
+ UNKNOWN;
+
+ companion object {
+ fun toDialogType(value: String): DialogType {
+ return try {
+ valueOf(value)
+ } catch (e: IllegalArgumentException) {
+ UNKNOWN
+ }
+ }
+ }
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
index 62c244cfb121..5aa1e9ba6183 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
@@ -10,13 +10,16 @@ data class ProviderInfo(
val createOptions: List<CreateOptionInfo>,
)
-data class ProviderList(
- val providers: List<ProviderInfo>,
-)
-
data class CreateOptionInfo(
val icon: Drawable,
val title: String,
val subtitle: String,
val id: String,
)
+
+/** The name of the current screen. */
+enum class CreateScreenState {
+ PASSKEY_INTRO,
+ PROVIDER_SELECTION,
+ CREATION_OPTION_SELECTION,
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyComponents.kt
index fb6db2172123..60a8e4b24d57 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyComponents.kt
@@ -25,22 +25,15 @@ import androidx.compose.material.Text
import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.graphics.drawable.toBitmap
-import androidx.navigation.NavController
-import androidx.navigation.NavGraphBuilder
-import androidx.navigation.NavType
-import androidx.navigation.compose.composable
-import androidx.navigation.navArgument
-import androidx.navigation.navigation
+import androidx.lifecycle.viewmodel.compose.viewModel
import com.android.credentialmanager.R
import com.android.credentialmanager.ui.theme.Grey100
import com.android.credentialmanager.ui.theme.Shapes
@@ -50,53 +43,10 @@ import com.android.credentialmanager.ui.theme.lightColorAccentSecondary
import com.android.credentialmanager.ui.theme.lightSurface1
@ExperimentalMaterialApi
-fun NavGraphBuilder.createPasskeyGraph(
- navController: NavController,
- viewModel: CreatePasskeyViewModel,
- onCancel: () -> Unit,
- startDestination: String = "intro", // TODO: get this from view model
-) {
- navigation(startDestination = startDestination, route = "createPasskey") {
- composable("intro") {
- CreatePasskeyIntroDialog(
- onCancel = onCancel,
- onConfirm = {viewModel.onConfirm(navController)}
- )
- }
- composable("providerSelection") {
- ProviderSelectionDialog(
- providerList = viewModel.uiState.collectAsState().value.providerList,
- onProviderSelected = {viewModel.onProviderSelected(it, navController)},
- onCancel = onCancel
- )
- }
- composable(
- "createCredentialSelection/{providerName}",
- arguments = listOf(navArgument("providerName") {type = NavType.StringType})
- ) {
- val arguments = it.arguments
- if (arguments == null) {
- throw java.lang.IllegalStateException("createCredentialSelection without a provider name")
- }
- CreationSelectionDialog(
- providerInfo = viewModel.getProviderInfoByName(arguments.getString("providerName")!!),
- onOptionSelected = {viewModel.onCreateOptionSelected(it)},
- onCancel = onCancel,
- multiProvider = viewModel.uiState.collectAsState().value.providerList.providers.size > 1,
- onMoreOptionSelected = {viewModel.onMoreOptionSelected(navController)},
- )
- }
- }
-}
-
-/**
- * BEGIN INTRO CONTENT
- */
-@ExperimentalMaterialApi
@Composable
-fun CreatePasskeyIntroDialog(
- onCancel: () -> Unit = {},
- onConfirm: () -> Unit = {},
+fun CreatePasskeyScreen(
+ viewModel: CreatePasskeyViewModel = viewModel(),
+ cancelActivity: () -> Unit,
) {
val state = rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Expanded,
@@ -105,9 +55,25 @@ fun CreatePasskeyIntroDialog(
ModalBottomSheetLayout(
sheetState = state,
sheetContent = {
- ConfirmationCard(
- onCancel = onCancel, onConfirm = onConfirm
- )
+ val uiState = viewModel.uiState
+ when (uiState.currentScreenState) {
+ CreateScreenState.PASSKEY_INTRO -> ConfirmationCard(
+ onConfirm = {viewModel.onConfirmIntro()},
+ onCancel = cancelActivity,
+ )
+ CreateScreenState.PROVIDER_SELECTION -> ProviderSelectionCard(
+ providerList = uiState.providers,
+ onCancel = cancelActivity,
+ onProviderSelected = {viewModel.onProviderSelected(it)}
+ )
+ CreateScreenState.CREATION_OPTION_SELECTION -> CreationSelectionCard(
+ providerInfo = uiState.selectedProvider!!,
+ onOptionSelected = {viewModel.onCreateOptionSelected(it)},
+ onCancel = cancelActivity,
+ multiProvider = uiState.providers.size > 1,
+ onMoreOptionSelected = {viewModel.onMoreOptionSelected()}
+ )
+ }
},
scrimColor = Color.Transparent,
sheetShape = Shapes.medium,
@@ -115,7 +81,7 @@ fun CreatePasskeyIntroDialog(
LaunchedEffect(state.currentValue) {
when (state.currentValue) {
ModalBottomSheetValue.Hidden -> {
- onCancel()
+ cancelActivity()
}
}
}
@@ -178,49 +144,10 @@ fun ConfirmationCard(
}
}
-/**
- * END INTRO CONTENT
- */
-
-/**
- * BEGIN PROVIDER SELECTION CONTENT
- */
-@ExperimentalMaterialApi
-@Composable
-fun ProviderSelectionDialog(
- providerList: ProviderList,
- onProviderSelected: (String) -> Unit,
- onCancel: () -> Unit,
-) {
- val state = rememberModalBottomSheetState(
- initialValue = ModalBottomSheetValue.Expanded,
- skipHalfExpanded = true
- )
- ModalBottomSheetLayout(
- sheetState = state,
- sheetContent = {
- ProviderSelectionCard(
- providerList = providerList,
- onCancel = onCancel,
- onProviderSelected = onProviderSelected
- )
- },
- scrimColor = Color.Transparent,
- sheetShape = Shapes.medium,
- ) {}
- LaunchedEffect(state.currentValue) {
- when (state.currentValue) {
- ModalBottomSheetValue.Hidden -> {
- onCancel()
- }
- }
- }
-}
-
@ExperimentalMaterialApi
@Composable
fun ProviderSelectionCard(
- providerList: ProviderList,
+ providerList: List<ProviderInfo>,
onProviderSelected: (String) -> Unit,
onCancel: () -> Unit
) {
@@ -251,7 +178,7 @@ fun ProviderSelectionCard(
LazyColumn(
verticalArrangement = Arrangement.spacedBy(2.dp)
) {
- providerList.providers.forEach {
+ providerList.forEach {
item {
ProviderRow(providerInfo = it, onProviderSelected = onProviderSelected)
}
@@ -304,14 +231,6 @@ fun ProviderRow(providerInfo: ProviderInfo, onProviderSelected: (String) -> Unit
}
}
-/**
- * END PROVIDER SELECTION CONTENT
- */
-
-/**
- * BEGIN COMMON COMPONENTS
- */
-
@Composable
fun CancelButton(text: String, onclick: () -> Unit) {
val colors = ButtonDefaults.buttonColors(
@@ -352,45 +271,6 @@ fun NavigationButton(
}
}
-/**
- * BEGIN CREATE OPTION SELECTION CONTENT
- */
-@ExperimentalMaterialApi
-@Composable
-fun CreationSelectionDialog(
- providerInfo: ProviderInfo,
- onOptionSelected: (String) -> Unit,
- onCancel: () -> Unit,
- multiProvider: Boolean,
- onMoreOptionSelected: () -> Unit,
-) {
- val state = rememberModalBottomSheetState(
- initialValue = ModalBottomSheetValue.Expanded,
- skipHalfExpanded = true
- )
- ModalBottomSheetLayout(
- sheetState = state,
- sheetContent = {
- CreationSelectionCard(
- providerInfo = providerInfo,
- onCancel = onCancel,
- onOptionSelected = onOptionSelected,
- multiProvider = multiProvider,
- onMoreOptionSelected = onMoreOptionSelected,
- )
- },
- scrimColor = Color.Transparent,
- sheetShape = Shapes.medium,
- ) {}
- LaunchedEffect(state.currentValue) {
- when (state.currentValue) {
- ModalBottomSheetValue.Hidden -> {
- onCancel()
- }
- }
- }
-}
-
@ExperimentalMaterialApi
@Composable
fun CreationSelectionCard(
@@ -516,26 +396,3 @@ fun MoreOptionRow(onSelect: () -> Unit) {
)
}
}
-/**
- * END CREATE OPTION SELECTION CONTENT
- */
-
-/**
- * END COMMON COMPONENTS
- */
-
-@ExperimentalMaterialApi
-@Preview(showBackground = true)
-@Composable
-fun CreatePasskeyEntryScreenPreview() {
- // val providers = ProviderList(
- // listOf(
- // ProviderInfo(null),
- // ProviderInfo(null, "Dashlane"),
- // ProviderInfo(null, "LastPass")
- // )
- // )
- // TatiAccountSelectorTheme {
- // ConfirmationCard({}, {})
- // }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyViewModel.kt
index 355428555735..e42016d59b0b 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyViewModel.kt
@@ -1,38 +1,45 @@
package com.android.credentialmanager.createflow
import android.util.Log
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
-import androidx.navigation.NavController
import com.android.credentialmanager.CredentialManagerRepo
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
data class CreatePasskeyUiState(
- val providerList: ProviderList,
+ val providers: List<ProviderInfo>,
+ val currentScreenState: CreateScreenState,
+ val selectedProvider: ProviderInfo? = null,
)
class CreatePasskeyViewModel(
- credManRepo: CredentialManagerRepo
+ credManRepo: CredentialManagerRepo = CredentialManagerRepo.getInstance()
) : ViewModel() {
- private val _uiState = MutableStateFlow(
- CreatePasskeyUiState(credManRepo.createCredentialProviderList())
- )
- val uiState: StateFlow<CreatePasskeyUiState> = _uiState.asStateFlow()
-
- fun onConfirm(navController: NavController) {
- if (uiState.value.providerList.providers.size > 1) {
- navController.navigate("providerSelection")
- } else if (uiState.value.providerList.providers.size == 1) {
- onProviderSelected(uiState.value.providerList.providers[0].name, navController)
+ var uiState by mutableStateOf(credManRepo.createPasskeyInitialUiState())
+ private set
+
+ fun onConfirmIntro() {
+ if (uiState.providers.size > 1) {
+ uiState = uiState.copy(
+ currentScreenState = CreateScreenState.PROVIDER_SELECTION
+ )
+ } else if (uiState.providers.size == 1){
+ uiState = uiState.copy(
+ currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION,
+ selectedProvider = uiState.providers.first()
+ )
} else {
throw java.lang.IllegalStateException("Empty provider list.")
}
}
- fun onProviderSelected(providerName: String, navController: NavController) {
- return navController.navigate("createCredentialSelection/$providerName")
+ fun onProviderSelected(providerName: String) {
+ uiState = uiState.copy(
+ currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION,
+ selectedProvider = getProviderInfoByName(providerName)
+ )
}
fun onCreateOptionSelected(createOptionId: String) {
@@ -40,12 +47,12 @@ class CreatePasskeyViewModel(
}
fun getProviderInfoByName(providerName: String): ProviderInfo {
- return uiState.value.providerList.providers.single {
+ return uiState.providers.single {
it.name.equals(providerName)
}
}
- fun onMoreOptionSelected(navController: NavController) {
- navController.navigate("moreOption")
+ fun onMoreOptionSelected() {
+ Log.d("Account Selector", "On more option selected")
}
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index 6ad14db00024..4b957e84fc2b 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -21,7 +21,6 @@ import androidx.compose.material.Text
import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@@ -29,10 +28,7 @@ import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.graphics.drawable.toBitmap
-import androidx.navigation.NavController
-import androidx.navigation.NavGraphBuilder
-import androidx.navigation.compose.composable
-import androidx.navigation.navigation
+import androidx.lifecycle.viewmodel.compose.viewModel
import com.android.credentialmanager.R
import com.android.credentialmanager.createflow.CancelButton
import com.android.credentialmanager.ui.theme.Grey100
@@ -41,36 +37,10 @@ import com.android.credentialmanager.ui.theme.Typography
import com.android.credentialmanager.ui.theme.lightBackgroundColor
@ExperimentalMaterialApi
-fun NavGraphBuilder.getCredentialsGraph(
- navController: NavController,
- viewModel: GetCredentialViewModel,
- onCancel: () -> Unit,
- startDestination: String = "credentialSelection", // TODO: get this from view model
-) {
- navigation(startDestination = startDestination, route = "getCredentials") {
- composable("credentialSelection") {
- CredentialSelectionDialog(
- providerInfo = viewModel.getDefaultProviderInfo(),
- onOptionSelected = {viewModel.onCredentailSelected(it, navController)},
- onCancel = onCancel,
- multiProvider = viewModel.uiState.collectAsState().value.providers.size > 1,
- onMoreOptionSelected = {viewModel.onMoreOptionSelected(navController)}
- )
- }
- }
-}
-
-/**
- * BEGIN CREATE OPTION SELECTION CONTENT
- */
-@ExperimentalMaterialApi
@Composable
-fun CredentialSelectionDialog(
- providerInfo: ProviderInfo,
- onOptionSelected: (String) -> Unit,
- onCancel: () -> Unit,
- multiProvider: Boolean,
- onMoreOptionSelected: () -> Unit,
+fun GetCredentialScreen(
+ viewModel: GetCredentialViewModel = viewModel(),
+ cancelActivity: () -> Unit,
) {
val state = rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Expanded,
@@ -79,13 +49,16 @@ fun CredentialSelectionDialog(
ModalBottomSheetLayout(
sheetState = state,
sheetContent = {
- CredentialSelectionCard(
- providerInfo = providerInfo,
- onCancel = onCancel,
- onOptionSelected = onOptionSelected,
- multiProvider = multiProvider,
- onMoreOptionSelected = onMoreOptionSelected,
- )
+ val uiState = viewModel.uiState
+ when (uiState.currentScreenState) {
+ GetScreenState.CREDENTIAL_SELECTION -> CredentialSelectionCard(
+ providerInfo = uiState.selectedProvider!!,
+ onCancel = cancelActivity,
+ onOptionSelected = {viewModel.onCredentailSelected(it)},
+ multiProvider = uiState.providers.size > 1,
+ onMoreOptionSelected = {viewModel.onMoreOptionSelected()},
+ )
+ }
},
scrimColor = Color.Transparent,
sheetShape = Shapes.medium,
@@ -93,7 +66,7 @@ fun CredentialSelectionDialog(
LaunchedEffect(state.currentValue) {
when (state.currentValue) {
ModalBottomSheetValue.Hidden -> {
- onCancel()
+ cancelActivity()
}
}
}
@@ -121,7 +94,9 @@ fun CredentialSelectionCard(
Text(
text = stringResource(R.string.choose_sign_in_title),
style = Typography.subtitle1,
- modifier = Modifier.padding(all = 24.dp).align(alignment = Alignment.CenterHorizontally)
+ modifier = Modifier
+ .padding(all = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally)
)
Text(
text = providerInfo.appDomainName,
@@ -184,7 +159,6 @@ fun CredentialOptionRow(
leadingIcon = {
Image(modifier = Modifier.size(24.dp, 24.dp).padding(start = 10.dp),
bitmap = credentialOptionInfo.icon.toBitmap().asImageBitmap(),
- // painter = painterResource(R.drawable.ic_passkey),
// TODO: add description.
contentDescription = "")
},
@@ -227,6 +201,3 @@ fun MoreOptionRow(onSelect: () -> Unit) {
)
}
}
-/**
- * END CREATE OPTION SELECTION CONTENT
- */
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt
index 20057de8fec2..06bcd7fedc6f 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt
@@ -1,36 +1,30 @@
package com.android.credentialmanager.getflow
import android.util.Log
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
-import androidx.navigation.NavController
import com.android.credentialmanager.CredentialManagerRepo
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
data class GetCredentialUiState(
- val providers: List<ProviderInfo>
+ val providers: List<ProviderInfo>,
+ val currentScreenState: GetScreenState,
+ val selectedProvider: ProviderInfo? = null,
)
class GetCredentialViewModel(
- credManRepo: CredentialManagerRepo
+ credManRepo: CredentialManagerRepo = CredentialManagerRepo.getInstance()
) : ViewModel() {
- private val _uiState = MutableStateFlow(
- GetCredentialUiState(credManRepo.getCredentialProviderList())
- )
- val uiState: StateFlow<GetCredentialUiState> = _uiState.asStateFlow()
+ var uiState by mutableStateOf(credManRepo.getCredentialInitialUiState())
+ private set
- fun getDefaultProviderInfo(): ProviderInfo {
- // TODO: correctly get the default provider.
- return uiState.value.providers.first()
- }
-
- fun onCredentailSelected(credentialId: String, navController: NavController) {
+ fun onCredentailSelected(credentialId: String) {
Log.d("Account Selector", "credential selected: $credentialId")
}
- fun onMoreOptionSelected(navController: NavController) {
+ fun onMoreOptionSelected() {
Log.d("Account Selector", "More Option selected")
}
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
index 8710eceeb723..867e9c2acc63 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
@@ -16,3 +16,8 @@ data class CredentialOptionInfo(
val subtitle: String,
val id: String,
)
+
+/** The name of the current screen. */
+enum class GetScreenState {
+ CREDENTIAL_SELECTION,
+}